なんで書いた?
すでに詳しい人が解説しており、私みたいな新参者が書く必要はないかと思いました
……が、なんかノリが合うような記事を見つけられませんでした。
実際のコードを自分で書いてまとめたほうが理解につながるな、と思ったのでここに書きながら理解を深めます。
参考
コードの借用とかはしてないですが、読んでる中で特に参考になったのでありがとうの意をこめて
前提とする知識
C#でFizzBuzzが組めるくらいの知識
「Unity+C#ではイベント関数をoverrideしたスクリプトをアタッチしているなあ」が理解できる程度の知識
「ネット同期なんもわからん」といえるくらいの謙虚さ
役割分担
VRCのUIと連携する必要がある機能、グラブ判定であるとか、トリガーであるとかはVRChatづてにもらう他ない。
オブジェクトに付与する必要のある性質はコンポーネントとして用意してある。
つまり、「持てるよ!」だけだったらわざわざUdonSharpを書かなくてもよいということだ。
しかしそれ以上のことがしたくなった。
投げたら3秒後に爆発するとか、ボタンを押したときに物が降ってくるとか、何をするかという動作を書くのにUdonSharpは使われる。
Unity+C#との違い
何にしてもVRCHATからの情報が大事になってくる。
UdonSharpプログラムはUdonSharpBehaviourを継承しているが、これのイベント関数を上書きすることで挙動を記述できる。
例えばOnPickupで持ったときの挙動を書いたり。
また、VRCHATのUIを通して更新される状況、例えばOwnerかどうかなどはグローバル関数で用意されているのでそれを呼び出す。
例えばNetworking.IsOwner。
UdonSharpはローカル動作に限ればほぼC#と変わらないのでそこに難しい部分は特にない。
が、リモート動作に関わる部分で制約があったり、超最新の機能が使えなかったりという方向で制約がかかる。
またそれをどのように送受信しているか、どのようにコールバックが呼び出されるかというVRCHAT側の実装に気を払う必要がある。
ここはいろいろ調べたり実験したりして進める。
・static変数は使えない
・Listがつかえない(arrayは使える)
・TryGetComponentがつかえない(GetComponentは使える)
・これは1.0以前のU#の話?
厄介な仕様の回避
どうやらFukuroUdonというライブラリが便利っぽい。
というより使わないと不便っぽい。
わかりやすく便利そうなのがその中の以下。
VRCHATデフォルトの同期方法だと融通が効かないのでUdonSharpとして同期させちゃる!
というのがこの機能。
うーん便利そう
(ただしアタッチの順で実行順が変わることには注意)
同期のさせ方
①SendCustomNetworkEventで引数なしイベントを起こす
(eventNameは関数名のstringなのでnameof(関数名)として渡そう)
②UdonSynced属性をつけた変数だけをRequestSerializationで同期する
(Synchronization MethodはManualにしている前提)
というざっくり2つの方法があるっぽい。
まあでも別にそんなにややこしくないか。
同期の具体的なさせ方
問題は、これを具体的にどう使うのかという話だ。
①は正直使いにくい。拡張性が皆無である。
ということで②を使ってごりごりとコーディングしていくことになるのだが、公式のAPIをみてもしっくりこない。
ということで具体例を見ていこう。
以下の記事はライブラリを提供しているみみーさんの記事。
https://note.com/mimyquality/n/n159a765dfa15
三目並べの例がとてもわかりやすいのだが、同期をリクエストしたのち、リクエストした本人はそれを反映、されたほうは変化後の変数に合わせて変化とする。
こういった更新フローになるので時系列を含めた「経緯」にかかわらず「結果」によって反映することになる。
逆にいえば経緯をうまく再現するような同期は面倒になる。
過去のA状態を保持しておき、B状態に同期されたときその差分を計算することになるからだ。
アンチパターン
この「経緯」自体を送信したくなるかもしれない。
しかしこれは一度でも抜けがあると成立しなくなることに注意だ。
10回のカウントアップで一度でも抜けがあると最終的な見た目に変化が起きる。
これを防ぐのが根本的に難しい。
擬似的なUDPなどを組まないといけなくなる。
一方結果を送るやり方の場合は最終結果を送る通信が失敗するとずれるのだが、なんども通信をやり直せばいつか同期される。
こっちのほうが数段楽なので、この結果を送信する方法をメインとするほうがよい。
(通信量を考えてときどき状態を同期するがほとんどはこの経緯にあたるところの差分を送信する方法もあるが……難しくなりすぎるし高度だし、そんな需要が出るほど複雑なゲームはVRCHAT上に実装するのが無理なのではと思ったりもする)