1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Unity】PhotonFusion メモ

Last updated at Posted at 2023-04-29

実装

ConnectionToken

ConnectionToken は入室制限や再接続時の入力権限再割り当て等に役立つ。

入室制限

以下のような手順で、Token を知っている Client だけが入室できる部屋を作れる。

1 : Backend でマッチングが決定したら、Server と Client に部屋名や Token 等の情報を送る
2 : Server は Backend から全 Cilent の Token を受け取ったら、部屋を作成する
3 : Client は Backend から固有の Token を受け取ったら、入室する
4 : Client が入室する際、StartGameArgs.ConnectionToken を利用し、Server に Token を送る

Client Side.cs
runner.StartGame(new StartGameArgs()
{
    /* 省略 */
    ConnectionToken = System.Text.Encoding.ASCII.GetBytes(userToken),
});

5 : Server は OnConnectRequest() で Token が有効か判定する(入室拒否したいなら Refuse())

Server Side.cs
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関数が長くなる際は、他の関数を呼び出すことで簡潔に書ける。

例.cs
[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 の設定を可視化した画像。
image.png

確定している挙動

一定時間で動く床などは、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 されるようになる。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?