実装
ConnectionToken
ConnectionToken は入室制限や再接続時の入力権限再割り当て等に役立つ。
入室制限
以下のような手順で、Token を知っている Client だけが入室できる部屋を作れる。
1 : Backend でマッチングが決定したら、Server と Client に部屋名や Token 等の情報を送る
2 : Server は Backend から全 Cilent の Token を受け取ったら、部屋を作成する
3 : Client は Backend から固有の Token を受け取ったら、入室する
4 : Client が入室する際、StartGameArgs.ConnectionToken を利用し、Server に Token を送る
runner.StartGame(new StartGameArgs()
{
/* 省略 */
ConnectionToken = System.Text.Encoding.ASCII.GetBytes(userToken),
});
5 : Server は OnConnectRequest() で Token が有効か判定する(入室拒否したいなら Refuse())
public void OnConnectRequest(NetworkRunner runner, NetworkRunnerCallbackArgs.ConnectRequest request, byte[] token)
{
if (tokens.Contains(System.Text.Encoding.ASCII.GetString(token))) request.Accept();
else request.Refuse();
}
※Client 側では、Accept() なら OnPlayerJoined(), Refuse() なら OnConnectFailed() が実行される
簡易的なパスワード付きの部屋
Backend サーバを用意できない場合でも、ConnectionToken を利用すれば鍵付きの部屋が作れる。
StartGameArgs.ConnectionToken の先頭または末尾をパスワードで上書きすれば、Server 側で OnConnectRequest() からパスワードの正誤判定ができる。
再接続時の入力権限再割り当て
Networked プロパティ
変更リスナを簡潔に書く
Networked プロパティに設定するstatic関数が長くなる際は、他の関数を呼び出すことで簡潔に書ける。
[Networked(OnChanged = nameof(OnChangedMatColor))] Color MatColor { get; set; }
private static void OnChangedMatColor(Changed<Player> changed) => changed.Behaviour.OnUpdatedMatColor(changed);
private void OnUpdatedMatColor(Changed<Player> changed)
{
material.color = MatColor;
/* 実装 */
}
Networked プロパティの節約
フレームを跨ぐ変数は基本的に Networked プロパティにするべき。
ただ、一つ前の予測を利用して、精度を犠牲に Networked プロパティを減らせる場合もある。
private Vector3 _prevTickPos;
public Vector3 PrevPos { get; private set; }
public override void FixedUpdateNetwork()
{
/* 省略 */
if (Runner.IsClient && Runner.IsResimulation && Runner.IsFirstTick)
{
PrevPos = _prevTickPos;
_prevTickPos = Rigidbody.Position;
}
else
{
PrevPos = Rigidbody.Position;
}
}
予測
Transform や Rigidbody は予測動作、スポーンはスポーン予想を利用する。
下図は Interpolated Error の設定を可視化した画像。
確定している挙動
一定時間で動く床などは、FixedUpdateNetwork()
内でRunner.SimulationTime
を使って挙動を実装し、Render()
内でRunner.SimulationRenderTime
を使って描画を行う。Host/Client モード
や Server モード
で確定挙動をクライアント予測する際はローカル外挿が適している。
Tips
拡張メソッド/便利メソッド
Host/Client Mode と Server Mode の両立
Hose Mode で作ったゲームは以下のサンプルを参考にして、入室処理周りを改修すれば Server Mode でも動かせる。
サーバに不要な処理は以下のように省ける。
#if !UNITY_SERVER
/* 効果音やパーティクル発生等の処理 */
#endif
実装中は Host Mode で確認し、プルリク前の動作確認は ParrelSync で専用サーバを用意して Server Mode で確認。
アップデート前は Dedicated Server ビルドして Server Mode で確認するのがいい塩梅かも。
Multi-Peer
Multi-Peer Mode を使うと、違う Session 同士で物理的な干渉が起きなくなる。
また Physics を Runner.GetPhysicsScene() に置き替える必要がある。
Shutdown() しても空の Scene が残る問題は、Runner.Shutdown()
の直後にSceneManager.UnloadSceneAsync(Runner.MultiplePeerUnityScene)
を呼ぶことで解決できる。
Networked
Tick は Networked プロパティで扱えない。使おうとすると下記のエラーが出る。
公式サンプルでは代わりに int を使っている。
System.ArgumentException: Value types need to implement either INetworkStruct or INetworkInput interface (type: Fusion.Tick)
Addressables
WebGL で Addressables な NetworkObject を Spawn
WebGL 上で読み込んでいない Addressables な NetworkObject を Spawn しようとすると失敗する。
Spawn() する際はクライアントに読込依頼を出し、全員から読込完了の連絡を待つなどする必要がある。
Release
Fusion 1.1.x 時点では Despawn() しても Addressables は Release されない。
Photon の Discord にある有志が書いたスクリプト FusionAssetReference を NetworkObject に付けると Release されるようになる。