- 投稿日:2020-04-07T23:55:00+09:00
C# メモリ上の数値の改ざんを防ぐ
成果物
C#のコンソールテスト用です
https://github.com/Oinary/SecureValue/blob/master/Program.cs1.やりたいこと
・改ざんされちゃマズい数値を守りたい!(ゲーム内のHPやお金など)
・ファイルだけではなくメモリ上の数値も保護したい。(今回はInt型とFloat型)2.何を使えば出来るか
XOR(排他的論理和)で解決。
https://qiita.com/kuuso1/items/778acaa7011d98a3ff3a簡単に言うと2進数で2つの数を演算したとき
片方がTrue(1)ならTrue。 0 xor 1 → 1
両方がTrue又はFalse(0)ならFalse。 0 xor 0 → 0これって同じ値で演算しなおすと元の値に戻るんです。
1010 xor 0110 → 1100
1100 xor 0110 → 1010科学の力ってすげぇ(てきとう
3.実装してみた
まずXORを使うのには、元の値とそれを合わせる値が必要。
C#でランダムな整数をもらってきます。(これはちゃんと保存しましょう)Random.Next()
https://docs.microsoft.com/ja-jp/dotnet/api/system.random.next?view=netframework-4.8あとは ^ 演算子で保存、復元すれば解決!
SecureInt.csprivate int Seed; private int Value; public int _Value { get { return Value ^ Seed; } set { Seed = new Random().Next()//ランダムなInt Value = value ^ Seed;//あとはお好きに } }3-1.そうは上手くいかなかった
Int型は何も問題なく実装できましたが…。
Float型ってXORを直接は使えない。(馬鹿には分からなかった。3-2.じゃぁどう回避しようか
ヒントがここにあった…。
https://qiita.com/nia_tn1012/items/d26f0fc993895a09b30bFloatで後ろ23ビットは仮数部と呼ばれる、我々が目にする数が格納されているところがあります。
例 2.345 → 2345 (小数点を無くした値になります)
その仮数部を隠せば良さげです。
※これはイメージですSamplefloat F = 1.55f;//得たfloat var I = BitConverter.ToInt32(BitConverter.GetBytes(F),0);//これをbyte[]にして、Int型にさせる var SignificandPart = I << 9;//左に9ビットシフトすると仮数部だけ残る var SecureValue = SignificandPart ^ Seed;//あとは煮るなり焼くなり //戻すときはこの逆でで出来上がりなのですが、まぁ操作多いんですよ。
なんかこう、もっとサクッとFloatをIntにできないんですかね…。・・・あったわ
その参照記事の下に別の方法が書かれています。
ポインタを扱うことがポイント♪で内部値をInt型で取得できます。SecureFloat.csprivate int SecValue; private int Seed; public unsafe float _Value { get { var result = SecValue ^ Seed; return BitConverter.ToSingle(BitConverter.GetBytes(result), 0);//戻すときは一度byte[]にしてからFloatに変換。 } set { CalculatingSeed(); int v = *((int*)&value);//&valueでvalueのポインタを取得、(int*)でInt型のポインタを格納、最初の*でそのポインタの値を指す。 SecValue = v ^ Seed;//あとはお好きに } }ポインタの使用は、本来はバグなど意図しない動作を防ぐために制限されています。
それを解除するため、unsafe を明示します。(VisualStudioの設定もお忘れずに)これで守りたい値の保護方法が実装できそうです。
4.さいごに
不正の種類はいくつもあるので、それ相応の対応をしなければなりません。
が、あの手この手で不正してくるはずです。
実装するコストと見合っているかどうかも検討しないと、クオリティや製作時間に響いちゃいます。僕みたいな初級の個人ゲームクリエイターならお遊び程度でいいんじゃないでしょうかね。
では初記事をご覧いただきありがとうございました。
※ってか一番大事なメモリエディタの画像なくね?
- 投稿日:2020-04-07T23:23:01+09:00
期間限定無料の Unity Learn Premium の ML-Agents: Penguins が良かった
Unity Learn Premium が無料で提供されているものの、たくさんあるし、英語だしと怯んでいましたが、その中の一つをやってみたらとても良かったというお話です。
良かった理由
- わずか5時間で、
- 環境構築から始まって強化学習させたモデルを利用した、
- 魚を採って子どもに与えるペンギンを作って動かす体験ができます
どうやって学習するの?なにこの数値?とか、
なんかわからないから難しい、怖いというところから脱することができます。5時間
頑張れば1日でできるぐらいの量なのが良いと思っています。長いと疲れるし、途中でき飽きちゃいますが、やるぞって決めてやり切れるぐらいの量。間延びしても2日あればやり切れるぐらい。
強化学習させたモデル
環境構築から始めたにもかかわらず、終わるときには学習した結果(モデル)が手元に残ります。Unity と python の繋ぎこみや、Machine Learningに必要な知識がある程度のレベルに隠蔽されているので、詰まることもありません。
動くペンギン
学習させた数値だけ見ていても実感はわきませんが、これは実際に魚を捕まえるのがうまくなったペンギンを見ることができます。Unity の良さでもあり、そしてその Unity の良さをきちんと体験できるものだと思いました。
どういう人にオススメ?
- Machine Learning に興味があるけど、まだ知識がない人
- Unity やってるけど、単純なのに飽きてきた人
- 無料でやりたい人
- 英語できなくても、google 翻訳でなんとかなります(自分はなった)
- ちょっと厳しい人
時間はどれぐらい?
サイトでは約2.5時間となっていますが、ダウンロードとか、間に色々挟まったりして5時間程度かかりました。
(Unity や IDE はインストールした状態から開始しています。)肝心の講義はこちら
注意
一番ハマったのが ML-Agents のバージョンです。更新が順次入っているので、このサイトのバージョン(0.13.x, 私は0.13.1でやった)に合わせてやったほうが良いです。そうでないとプログラムとかをいちいち最新バージョンに合わせて修正しないと動きません。
補足
これだけでは足りない(当たり前)
- ハイパーパラメーターや学習モデルの話とかは、良くも悪くも出てこないので、そういうところは全く理解できません
- 横展開したくても、現状のバージョンはペンギン専用らしいです
Unity Learn Premium が無料
「Unity Learn Premium」を3か月間無料化(6月20日まで)
ちょっと厳しい人
体験はできると思うけど、意味があるかは?が付くという意味で、ちょっと厳しい。
- プログラムほとんど書けない人
- 基本的な構文(if/for)とかが何か見ないと書けない人
- Unityほとんど知らない人
- Start/Update/FixedUpdate/rigidbody/GameObject を知らないレベルの人
- 投稿日:2020-04-07T11:34:07+09:00
MacでPhotonVoiceを使用したときに他アプリケーションの音量が小さくなる問題
概要
PhotonVoice を使用した Unity 製アプリを起動した途端、別アプリケーションとして起動している Google Chrome 上の YouTube や Spotify 等の音量が極小になる。また、通話中の Discord に至っては音量だけではなくマイク入力も極小になるようだった。本事象は UnityEditor 上でアプリケーションを実行しても発生した。
同じ事象は PhotonVoice を使用していないと思われる LINE や Skype, Zoom の通話中でも発生しているが、Discord や Slack, Google Chrome 上の Facebook Messenger の通話中では発生していないので、何か解決方法があることが分かる。
確定的な原因は分からなかったが、対処方法は分かったので記事として残しておく。
各種バージョン
環境 バージョン macOS macOS 10.15.4 Unity Unity 2018.2.21f1 Photon Unity Network PUN 1.91 (全体的にバージョンが古くてお恥ずかしい限りです)
対処方法
PhotonVoiceRecorder にある Microphone Type で「Unity」を使用する。
自分のプロジェクトでは「Photon」を使用していたが、これを「Unity」に変更したら解決した。ただし、基本的には Unity マイクよりも Photon マイクのほうが何かと優秀なので、Mac で起動したときのみ「Unity」マイクを使用するようにするために下記コードを書いた。 (PhotonマイクのクライアントとUnityマイクのクライアント同士で音声通信が正常に出来ることは検証済み)
private void Start() { GetComponent<PhotonVoiceRecorder>().MicrophoneType = IsMacOs() ? PhotonVoiceRecorder.MicAudioSourceType.Unity : PhotonVoiceRecorder.MicAudioSourceType.Photon; // 念の為PhotonVoiceSettingも変更しておく PhotonVoiceSettings.Instance.MicrophoneType = IsMacOs() ? PhotonVoiceSettings.MicAudioSourceType.Unity : PhotonVoiceSettings.MicAudioSourceType.Photon; } // Macで実行されていたらtrue private bool IsMacOs() { #if UNITY_STANDALONE_OSX || UNITY_EDITOR_OSX return true; #endif return false; }原因究明 (未解決)
下記のフォーラムで探して回ったが、とにかく同じ事で悩んでいる人が少なかった。
また、投稿があっても回答が無いパターンも多かった。
- Unity Forum
- Apple Developer Forums
- Photon Engine Support Forum
- Stack Overflow
似たような問題を抱えている人
本事象に一番近いなと思ったのは、Apple Developer Forums に投稿されていた下記の質問。
(もしかしたら全く関係無いかもしれないが)
VoiceProcessingIO lowers the volume of all othe... |Apple Developer ForumsVoIPアプリケーションでVoiceProcessingIO(kAudioUnitSubType_VoiceProcessingIO)オーディオユニットを使用してオーディオを録音および再生しています。ユニットが初期化されている場合を除き、すべてが正常に動作します。他に何かがオーディオを再生している場合、そのオーディオは非常に静かになりますが、出力はすべてフルボリュームで聞こえます。
こちらの投稿には回答が付いていなかったが、macOS のオーディオ API 周りの機能が原因である事が分かる。
(上記記事で紹介されていた kAUVoiceIOProperty_DuckNonVoiceAudio - AudioToolbox | Apple Developer Documentation のプロパティをドキュメントから参照したが、非推奨と書いてあったので対応出来なかった。)全てのアプリケーションにおいて音声入力時に他のアプリケーションの音量が小さくなるのならここで諦めるが、上述した通り Discord や Slack の通話では音量が変わる事が無かったので、もう少し調べてみることにした。
Photon Voice のマイクタイプについて
公式ドキュメントの「Photon」マイクの説明を見ると、ネイティブのオーディオAPIとやりとりしている事が分かる。
Unityマイクは、ほぼ同じコードベースを使用して複数のプラットフォームをターゲットにすることを容易にするのに最適です。ただし、いくつかの点で、UnityのマイクAPIは制限されているか、あちこちにいくつかの問題があります。そのため、オーディオ入力デバイスと直接やり取りし、UnityのマイクAPIをバイパスする独自の方法を導入しました。これの主な理由の1つは、デバイスのハードウェアに組み込まれているエコーキャンセレーションを利用することです。 ※ Photon Voice For PUN | Photon Engine より引用
macOS の API (特にオーディオ周り)には詳しくないが、オーディオ API が本事象の原因であり、Photon マイクの実装がネイティブのオーディオ API を利用しているのならもしかして?と思ってマイクタイプを「Unity」に変更したら他アプリケーションの音量に影響を与えない事が出来た。
最後に
Unity マイクも内部的にはネイティブのオーディオ API を参照しているのでは?と思ったが、他アプリケーションの音量操作は Unity API 側で無効にされているという認識で良かったのだろうか。
結局、具体的に何のオーディオ API の何のパラメータが原因で、どのような場合に音量操作を行うのかというのは分からなかったので、もし詳しい方がいらっしゃいましたらご教示いただけますと幸いです。
参考リンク
- Photon Voice For PUN | Photon Engine
- アプリケーションの音量調節を制限する方法-Appleコミュニティ
- 自動ゲインコントロールを無効にする(コアオーディオ)-Unityフォーラム
- ios-プログラムでVoiceProcessingIO AGCをオフにする-スタックオーバーフロー
- mountain lion - Mac OSX microphone input volume level auto-adjusts - can it be disabled? - Ask Different
- VoiceProcessingIOは他のすべての音量を下げます... | Apple開発者フォーラム
- kAUVoiceIOProperty_DuckNonVoiceAudio - AudioToolbox | Apple Developer Documentation
- 投稿日:2020-04-07T07:30:23+09:00
【Unity】初心者が覚えるべきDebug.Logの使い方
環境
Unity 2019.3.7f1
Debug.Logって?
Unity側で用意された標準機能
Debug.Log()
は定型文です。呪文として覚えましょう!
開発中めちゃくちゃ使うので勝手に覚えちゃうと思います笑どんな時に使う?
・変数の中身を知りたいとき
・何の処理が行われたかをわかるようにしたいとき(テキストを表示)
・処理が実行されたか確認したいとき前準備 コンソールウインドウを開く
このような画面が出ます。
ここにDebug.Logの中身が表示されます。
使ってみる
・変数の中身を知りたいとき
スクリプトを用意
名前はTEST_scriptにしました。using System.Collections; using System.Collections.Generic; using UnityEngine; public class TEST_script : MonoBehaviour{ int a;//aというint型の変数を宣言 void Start() { a = 10;//変数aの中身を10に設定 Debug.Log(a);//コンソールウインドウに変数aの持っている数値を表示 } }空のゲームオブジェクトを用意
ヒエラルキー上で右クリック→空のオブジェクト作成
空のオブジェクトが作成された!
先程作ったスクリプトを空のオブジェクトへドラッグ&ドロップ
インスペクターにスクリプトが割り当てられたことを確認
・何の処理が行われたかをわかるようにしたいとき
スクリプトのDebug.Log()のかっこ内を"ダブルクォーテーションで囲んで文字を入力
using System.Collections; using System.Collections.Generic; using UnityEngine; public class TEST_script : MonoBehaviour { int a;//aというint型の変数を宣言 // Start is called before the first frame update void Start() { a = 10;//変数aの中身を10に設定 Debug.Log("aに10を代入");//コンソールウインドウにテキストを表示 } }・処理が実行されたか確認したいとき
if分の中身が実行されたか見てみましょう。
using System.Collections; using System.Collections.Generic; using UnityEngine; public class TEST_script : MonoBehaviour { int a;//aというint型の変数を宣言 // Start is called before the first frame update void Start() { a = 10;//変数aの中身を10に設定 if(a == 10)//aが10だったらif分の中身の処理実行 { Debug.Log("if文の中身が処理された");//コンソールウインドウにテキストを表示 } } }少し応用
"a="+a といれるとテキストと変数の中身を同時表示できます。
using System.Collections; using System.Collections.Generic; using UnityEngine; public class TEST_script : MonoBehaviour { int a;//aというint型の変数を宣言 // Start is called before the first frame update void Start() { a = 10;//変数aの中身を10に設定 Debug.Log("a="+a); } }楽しいUnityライフを!
- 投稿日:2020-04-07T05:33:51+09:00
[Swift] Unity as a LibraryをSwiftから呼ぶ
基本的なところはここを見ながら進める。
https://qiita.com/tkyaji/items/7dbd56b41b6ac3e72635SwiftでUnityクラスを作る。上の記事ならこんなかんじ。
class Unity: NSObject, UnityFrameworkListener, NativeCallsProtocol { static let shared = Unity() private let unityFramework: UnityFramework override init() { let bundlePath = Bundle.main.bundlePath let frameworkPath = bundlePath + "/Frameworks/UnityFramework.framework" let bundle = Bundle(path: frameworkPath)! if !bundle.isLoaded { bundle.load() } let frameworkClass = bundle.principalClass as! UnityFramework.Type let framework = frameworkClass.getInstance()! if framework.appController() == nil { var header = _mh_execute_header framework.setExecuteHeader(&header) } unityFramework = framework super.init() } func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) { unityFramework.register(self) FrameworkLibAPI.registerAPIforNativeCalls(self) unityFramework.setDataBundleId("com.unity3d.framework") unityFramework.runEmbedded(withArgc: CommandLine.argc, argv: CommandLine.unsafeArgv, appLaunchOpts: launchOptions) } var view: UIView { unityFramework.appController()!.rootView! } func showHostMainWindow(_ color: String!) { } }ViewControllerを作る。
class LaunchViewController: UIViewController {} class ViewController: UIViewController { private let unityView = Unity.shared.view override func loadView() { super.loadView() view.addSubview(unityView) NSLayoutConstraint.activate([ unityView.topAnchor.constraint(equalTo: view.topAnchor), unityView.leftAnchor.constraint(equalTo: view.leftAnchor), unityView.rightAnchor.constraint(equalTo: view.rightAnchor), unityView.bottomAnchor.constraint(equalTo: view.bottomAnchor), ]) } }後述するが、
LaunchViewController
なるものを作っておく。AppDelegate.swift@UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { lazy var window: UIWindow? = .init(frame: UIScreen.main.bounds) func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { window?.rootViewController = LaunchViewController() window?.makeKeyAndVisible() Unity.shared.application(application, didFinishLaunchingWithOptions: launchOptions) window?.rootViewController = ViewController() return true } }起動時にUnityクラスを初期化しておく。
runEmbedded
はwindowが無いと上手く動かないので、先ほど作ったLaunchViewController
でwindowを作り、そのあとでメインのViewControllerに差し替える。
起動直後にUnityを出さないのであれば、適当にwindowが出来てから呼べばOK
- 投稿日:2020-04-07T02:27:14+09:00
JKがRustでgRPCで簡易マルチプレイサーバー書いてUnityで動かしてみた
こんにちは、あんはるです!
コロナで暇なので、紹介してなかったプロジェクトを紹介したいと思います.
突然ですけど、このGIF見てみてください.
右のウィンドウと左のウィンドウはサーバー経由で座標を共有しあっています〜
これが簡易マルチプレイです!
きっかけ・目的
荒野行動を始めると、100人のユーザーがリアルタイムに走っててすごいなぁと思いました。どうやったらこんなサーバ作れるのだろうという興味がきっかけです。
とりあえず、自前で実装してみたい!となったのでやってみます。
このプロジェクトの構成
バックエンド
- gRPC
- MongoDB
フロントエンド
- Unity
です。
上のデモはローカルで完結させてます。なぜgRPC?
Unityで、リアルタイムに処理したいという時に、MagicOnion – C#による .NET Core/Unity 用のリアルタイム通信フレームワークがよく記事に書かれています。
MagicOnionの通信は、gRPCを用いています。
また、Protocol BufferでRPCの定義をするだけで、ホスト、クライアントのコードが生成されることに無駄のなさを感じでクールだなと感じだので、使ってみたいと思いました。
なぜMongoDB?
速度が求められるので。
マルチプレイサーバー
ソースコードは、https://github.com/anharu2394/multiplay-grpc-server
Rustで書いてみた
このプロジェクトを書いた当時、一番Githubスター数が多かったgrpc-rsを使いました。
Protocol Bufferでマルチプレイサーバーの使用を定義。
UserPositionは、ユーザーのidとどこにいるかを表しています。
ConnectPositionで双方向ストリーミングで座標を同期しています。multiplay.protosyntax = "proto3"; package anharu; service Multiplay { rpc GetUsers(GetUsersRequest) returns (stream GetUsersResponse); rpc SetPosition(stream SetPositionRequest) returns (SetPositionResponse); rpc ConnectPosition(stream ConnectPositionRequest) returns (stream ConnectPositionResponse); } message GetUsersRequest { string room_id = 1; } message GetUsersResponse { repeated UserPosition users = 1; } message UserPosition { string id = 1; double x = 2; double y = 3; double z = 4; } message SetPositionRequest { string id = 1; double x = 2; double y = 3; double z = 4; } message SetPositionResponse { string status = 1; string id = 2; string error = 3; } message ConnectPositionRequest { string id = 1; double x = 2; double y = 3; double z = 4; } message ConnectPositionResponse { repeated UserPosition users = 1; } service User { rpc Create (CreateUserRequest) returns (CreateUserResponse); } message CreateUserRequest { string name = 1; } message CreateUserResponse { string id = 1; }そして、protoから生成されたコードを使って、それぞれ実装していきました。
マルチプレイクライアント
ソースコードは、 https://github.com/anharu2394/multiplay-grpc-client
Unityなのでc#で書いてます。Unityはそもそも、gRPCを使う環境を整えるのに時間がかかりました...
https://note.com/npaka/n/n050b1aba7772
これを参考にすると分かりやすいと思います!ストリーミングして、サーバーから座標が送られてくるごとに、キャラクターの座標を更新するという感じでやりました!
サーバーの動作確認がしたいだけなので、UIや見た目などは超手抜きですが、ジャンプのアニメーションをつけたり少しゲームっぽくして見ました!
まとめ
おそらく、本番環境では使い物にはならないかもしれませんが、ローカルの中でもgRPCの双方向ストリーミングが体感できてよかったです〜〜
RustもgRPCも頑張ります〜〜!