PUN Classic (v1)、Boltはメンテナンスモードとなっております。Unity2022についてはPUN 2でサポートいたしますが、新機能が追加されることはありません。お客様のPUNプロジェクトおよびBoltプロジェクトが停止することはなく、将来にわたってパフォーマンス性能が落ちることはありません。
今後の新しいプロジェクトについては、Photon FusionまたはQuantumへ切り替えていただくようよろしくお願いいたします。
State(状態)
Boltは「State(状態)」と呼ばれるコンセプトを採用しています。BoltのState実装を使用して、オブジェクトのネットワーク状態を、回転・位置や多くのビルトインプリミティブ型プロパティを含むテンプレートとして定義します(Bolt Assetsウィンドウを使用します。いくつかのチュートリアルに出てきますので参照してください)。さらに、IProtocolTokenとして状態プロパティを実装できます。これは、任意のデータタイプを状態プロパティとして実装する基本の方法となります。
Bolt Stateが素晴らしいのは、ネットワークプロパティを自動的に、そして変更があったときのみ同期できる点です。さらに、Stateを使うことで、途中参加(late joining)の実装がほとんど意識しなくて済むようになります。Bolt Stateの所有者がプロパティに変更を加えると、Boltがそのエンティティを同期対象にしているクライアントに該当の値を送信します。ユーザーは、Entity BehaviourのAttachedコールバック内で、各種コールバックを受け取るよう設定できます。(こちらをご参照ください。)状態について記述されたドキュメントは数多くありますが、Bolt Stateについてよく質問される点について以下に記載いたします。
- Boltでは各状態プロパティにデフォルトの値を設定しています。エンティティを新しい接続先へ同期する際には、デフォルト値のままになっているプロパティは送信されません(最適化によるものです)。
- Boltの状態プロパティのThereデフォルト値をカスタマイズすることはできません。
- 状態プロパティ変更はそのエンティティをスコープにしている接続にのみ送信されます。(デフォルトではすべての接続が対象になりますが、手動スコープを行う場合は、明示的にそのエンティティにスコープされた接続のみが対象になります)
- Boltは状態の変更を各送信ティック単位で送ります(設定で定義)。変更はオーナー(または、状態プロパティが「コントローラを覗く全員」に設定されている場合はコントローラ。ただし、その場合はコールバックを受け取るのはコントローラのみとなります。)で状態プロパティの値を変更されることで生じます。 このモードでは、内部の動作が見えやすくなるという利点があります。)
- 状態プロパティはすぐには送信されません。実質「更新が必要(dirty)」としてマークされ、次の送信ティック(またはシミュレーションティック。この点については要確認です)まで評価されません。つまり、次にプロパティが送信されるときまでに何回か値の変更を行った場合、クライアントに送信されるのは最後の値のみということになります(途中の値は送信されません)。
- 状態プロパティは優先順位をつけてクライアントに送信されます(Bolt設定における優先順位に準じます)。ただし、状態の処理に入る前に、Boltが優先順位に応じてエンティティの順番を入れ替え、処理します。各エンティティについて、BoltはDirtyなプロパティをソートし、パケット容量がなくなるまで各エンティティごとにに一定数のプロパティ(設定で定義)を送信します。なお、エンティティは優先順位に応じてもソートされます。(Packets Under the Hoodを参照してください)。これは接続ごとに行われます。パケットサイズとBolt設定の両方により、状態プロパティを変更した後、その次のティックでBoltがそれを送信するとは限りません。
- エンティティがアタッチされている場合、すべての状態プロパティがクライアントに到達するとは限りません。絶対に届けたいデータがある場合は、該当データにアタッチトークンを使用してください。データをインスタンス化した時に、トークンで送信するということです。アタッチトークンは比較的重いのでご注意ください。作成操作が受信確認されるまで、送信ティックごとに送信されます。
- 状態プロパティは順番通りに到着するとは限りませんが、優先順位に応じて受信されることが一般的です(保証はされていません)。“結果整合性(eventual consistency)”と呼ばれるもので、結果的にオーナーと状態が一致します。
- エンティティにコールバックを取得するには
Bolt.EntityBehaviour(see here)を実装してください。 - 新しいエンティティを受信すると、
Attachedの後に、初回パケットで受信した変更済みプロパティごとにコールバックが呼び出されます。 - ビルトインの状態プロパティに不足しているものがあれば、ProtocolTokenで実装できます。これによりカスタムビジネスロジックのシリアライゼーションに応じて管理することが可能になります。ただし、このようにトークン内で変更されたものが、変更された通りにBoltで送信されるわけではありません。Boltは、トークンレファレンスそのものが変更されたとき、つまり既存のトークンを別のトークンに変えたり、nullに設定したり(またはnullトークンからnullではないトークンに変えたり)した場合のみトークンを送信します。トークンはファクトリから生成されるため、Boltに登録する必要がある点にご注意ください。
- 新しい接続先が参加すると、エンティティは自動的に(スコープに応じて)その接続先を同期します。変更されたすべてのプロパティも同期されます。エンティティ/プロパティの数によってかかる時間はまちまちです。Boltが1秒ごとに送信するパケット数には上限があります ( Packets Under the Hoodを参照してください)。ですが、結果的にはすべてのデータがクライアントに到達します。これにより、後から参加機能の実装がとてもシンプルになり、関連するあらゆるハッキング(一般的にはメッセージバッファリングなど)を防ぐことができます。
- 最大パケットサイズは、Bolt設定のデフォルト値(1200)を超えないようにしてください。分割されたパケットを再度つなぎ合わせることはしないため、パケットのフラグメンテーションには対応していません。デフォルト値よりも高く設定してしまうと、結果的にクラッシュしてしまいます。デフォルト馬篭は、MTUよりも少し低い1200であることを忘れないでください。
- Boltは通常とは異なる処理を行う「Transform」プロパティを実装しています。ページ上部に記載のリンク先にあるWebドキュメントでこのトピックを取り扱っています。Transformプロパティは内挿・外挿を透過的に処理するとともに、任意の簡単な「レンダリング」内挿も実装しています。Transformの状態が送信されるのは、Transformに動きがあったときのみです。オブジェクトに動きがなければ、帯域は使用されません。