Fusionのオブジェクト型の同期
概要
NetworkObjectやNetworkBehaviourの参照は、ネットワークプロパティにすることができます。(備考:INetworkStruct内では無効です)
ネットワークプロパティのNetworkObject/NetworkBehaviourの参照は、内部的にNetworkId/NetworkBehaviourIdに変換されます。
ILWeaverが生成するSetメソッドは、オブジェクトの参照をIDに変換(ラップ)し、IDを値として同期します。
ILWeaverが生成するGetメソッドは、Runner.TryGetObject()やRunner.TryGetBehaviour()メソッドを使用して、IDをオブジェクトの参照に変換(アンラップ)します。
C#
[Networked] public NetworkObject MyNetworkObject { get; set; }
[Networked] public CustomNetworkBehaviour MyNetworkBehaviour { get; set; }
この自動化は便利ではありますが、
- 明示的なnull値
- アンラップの失敗
は、どちらもGetメソッドでnullが返るため、2つを区別する方法がありません。
代替案として、NetworkObject/NetworkBehaviourの参照を使用するかわりに、NetworkId/NetworkBehaviourIdの値を直接使用します。
オブジェクトをIDによって明示的に同期すると、null値を検知することができます。
- 0なら、明示的なnullを指す
- 0より大きい値なら、オブジェクトを指すが、そのオブジェクトは現在ローカルに存在しない(アンラップの失敗)
NetworkIdの使用例
C#
using Fusion;
public class SyncNetworkObjectExample : NetworkBehaviour
{
  // NetworkId is backed by one int value.
  // A zero value (default) represents null.
  [Networked] public NetworkId SyncedNetworkObjectId { get; set; }
  private void SetObject(NetworkObject netObj)
  {
    SyncedNetworkObjectId = netObj != null ? netObj.Id : default;
  }
  bool TryResolve(out NetworkObject no)
  {
    // A default (0) value indicates an explicit null value.
    // Return true to represent successfully resolving this to null.
    if (SyncedNetworkObjectId == default)
    {
      no = null;
      return true;
    }
    // Find the object using the non-null id value.
    // Return true if the lookup was successful.
    // Return false and null if the NetworkObject could not be found on the local Runner.
    bool found = Runner.TryFindObject(SyncedNetworkObjectId, out var obj);
    no = obj;
    return found;
  }
}
NetworkBehaviourIdの使用例
C#
using Fusion;
public class SyncNetworkBehaviourExample : NetworkBehaviour
{
  // NetworkId is backed by two int values.
  // Object = NetworkObject.Id (value of 0 represents null/Invalid).
  // Behaviour = NetworkBehaviour index in GameObject hierarchy.
  [Networked] public NetworkBehaviourId SyncedNetworkBehaviourId { get; set; }
  private void SetBehaviour(NetworkBehaviour nb)
  {
    SyncedNetworkBehaviourId = nb != null ? nb.Id : default;
  }
  bool TryResolve(out NetworkBehaviour no)
  {
    // A default (0) value indicates an explicit null value.
    // Return true to represent successfully resolving this to null.
    if (SyncedNetworkBehaviourId == default)
    {
      no = null;
      return true;
    }
    // Find the NetworkBehaviour using the non-default id value.
    // Return true if the lookup was successful.
    // Return false and null if the NetworkObject could not be found on the local Runner.
    bool found = Runner.TryFindBehaviour(SyncedNetworkBehaviourId, out var obj);
    no = obj;
    return found;
  }
}