This document is about: FUSION 1
SWITCH TO

このページは編集中です。更新が保留になっている可能性があります。

ネットワークコレクション

概要

Fusionはネットワークプロパティに使用できる構造体ベースのコレクションタイプを提供します。

  • NetworkArray<T>
  • NetworkDictionary<K, V>
  • NetworkLinkedList<T>
  • NetworkString<Size>

これらのコレクションは構造体であり、参照型ではありません。これらのコレクションとC#のコレクションの間には、C#の使用法に関する若干の違いがあります(INetworkStructsでの使用法を参照)。

許容されるT/K/V型は以下の通りです:

  • プリミティブ
    • byte, sbyte
    • Int16, Int32, Int64
    • UInt16, UInt32, UInt64
    • float
    • double
    • float
    • double
  • Unity 構造体型 (ILWeaver.csで定義)
    • Vector2, Vector3, Vector4
    • Quaternion
    • Matrix4x4
    • Vector2Int, Vector3Int
    • BoundingSphere
    • Bounds
    • Rect
    • BoundsInt
    • RectInt
    • Color, Color32
  • System.Guid
  • ユーザー定義のINetworkStructs
  • Fusion定義のINetworkStructs
    • NetworkString<IFixedStorage>
    • NetworkBool
    • Ptr
    • Angle
    • BitSet64, BitSet128, BitSet192, BitSet256
    • PlayerRefSet
    • NetworkId
    • NetworkButtons
    • NetworkRNG
    • NetworkObjectGuid
    • NetworkPrefabRef
    • NetworkObjectHeader
    • NetworkPrefabId
    • SceneRef
    • TickTimer
    • IFixedStorage (_2, _4, _8, _16, _32, _64, _128, _256, _512)

宣言

NetworkArray, NetworkDictionary, NetworkLinkedList[Networked] 属性を持つプロパティとして定義する必要があります。[Networked]属性は ILWeaver に、これらのコレクションを関連する NetworkRunnerSimultation インスタンスのバッキングメモリに接続するためのプロパティコードを生成するように指示します。

[Capacity]属性は要素の最大数を指定するために使用されます。使用量に関係なく、この数の要素に対してメモリが割り当てられます。予想される最大の要素数をカバーするのに十分な最小の数を選択します。要素が値を変えない限り、ネットワークトラフィックを発生させることはありません。

C#

// A basic Network Collection declaration
[Networked, Capacity(4)]
NetworkArray<int> NetArray => default;

初期化

NetworkArray NetworkDictionaryNetworkLinkedListNetworkBehaviour の Networked Property として宣言されている場合、 MakeInitializer() を使用して初期値を定義することができます。

C#

[Networked]
[Capacity(4)] // Sets the fixed capacity of the collection
NetworkArray<int> NetArray { get; }
  // Optional initialization
  = MakeInitializer(new int[] { 0, 1, 2, 3 });

[Networked, Capacity(4)]
NetworkLinkedList<int> NetLList { get; }
  // Optional initialization
  = MakeInitializer(new int[] { 0, 1, 2, 3 });

[Networked, Capacity(2)]
NetworkDictionary<int, int> NetDict { get; }
  // Optional initialization
  = MakeInitializer(new Dictionary<int, int> { { 0, 0 }, { 1, 1 } });

NetworkArray<T>

NetworkArray は、C# の配列に代わる構造体で、Fusion の Networked Property として使用することができます。C#の配列と完全に同じではありませんが、NetworkArrayIEnumerable コレクションで、値の取得や設定、他のコレクションとのコピーのメソッドを備えています。

主なメソッドは以下の通りです:

  • Get(int index)
  • Set(int, T)

C#

public class CollectionTestsArray : NetworkBehaviour
{
  [Networked]
  [Capacity(4)] // Sets the fixed capacity of the collection
  NetworkArray<NetworkString<_32>> NetArray { get; } =
    MakeInitializer(new NetworkString<_32>[] { "#0", "#1", "#2", "#3" });

  public override void FixedUpdateNetwork()
  {
    NetArray.Set(0, "Zero");
    NetArray.Set(1, "One");
    NetArray.Set(2, "Two");

    // This is invalid with a NetworkDictionary property, use Set() instead.
    // NetArray[3] = "Three";

    NetArray.Set(0, NetArray[0].ToUpper());
    NetArray.Set(1, NetArray.Get(1).ToLower());
    NetArray.Set(2, default);

    for (int i = 0; i < NetArray.Length; ++i)
    {
      Debug.Log($"{i}: '{NetArray[i]}''");
    }
  }
}

NetworkDictionary<K, V>

NetworkDictionary は、C# の Dictionary に代わる構造体で、Fusion の Networked Property として使用することができます。 完全な IDictionary の実装ではありませんが、期待される主要なメンバはすべて利用可能であり、 Dictionary と同様の機能を備えています。

主なメソッドとプロパティは以下の通りです:

  • Clear()
  • Add(K, V)
  • Remove(k)
  • ContainsKey(K)
  • ContainsValue(V)
  • Get(K)
  • Set(K, V)
  • this[K]
  • Capacity
  • Count

C#

public class NetworkDictionaryExample : NetworkBehaviour
{  
  [Networked]
  [Capacity(4)] // Sets the fixed capacity of the collection
  [UnitySerializeField] // Show this private property in the inspector.
  private NetworkDictionary<int, NetworkString<_32>> NetDict => default;

  public override void FixedUpdateNetwork()
  {
    NetDict.Clear();
    NetDict.Add(0, "Zero");
    NetDict.Add(2, "Two");
    NetDict.Add(5, "Five");

    // Setting values with the indexer are not valid, this is one of the cases
    // where the struct based NetworkDictionary differs in usage from Dictionary.
    // NetDict[0] = "Foo"; // this is not valid.

    if (NetDict.ContainsKey(0))
    {
      NetDict.Set(0, NetDict[0].ToUpper());
    }

    if (NetDict.TryGet(5, out var value))
    {
      NetDict.Set(5, value.ToLower());
    }

    NetDict.Remove(2);

    foreach(var kvp in NetDict)
    {
      Debug.Log($"{NetDict.Count}/{NetDict.Capacity} Key:{kvp.Key} Value:{kvp.Value}");
    }
  }
}

NetworkLinkedList<T>

NetworkLinkedListNetworkArray に代わる構造体で、容量のサブセットを使用することができます。追加されたアイテムは、バッキングデータの空きスロットに追加されます。アイテムが削除されると、バックアレイデータはメモリ内の他の要素を移動させません。コレクションは、構造体の一部として要素の順序に関するデータを保存します。列挙器とインデクサは、バックアレイに存在する順序ではなく、追加された順序で要素を返します。

C#

public class NetworkLinkedListExample : NetworkBehaviour
{
  [Networked]
  [Capacity(4)] // Sets the fixed capacity of the collection
  [UnitySerializeField] // Show this private property in the inspector.
  private NetworkLinkedList<NetworkString<_32>> NetList { get; }
    = MakeInitializer(new NetworkString<_32>[] { "Zero", "One", "Two", "Four"});

  public override void Spawned()
  {
    // Remove the second entry, leaving one open capacity.
    NetList.Remove("One");

    // Find an entry by value
    NetList.Set(NetList.IndexOf("Two"), "TWO");

    // Add a new entry. In memory it backfills the now open memory position.
    NetList.Add("Five");

    // The indexed order however remains in sequence,
    // so only the changed memory position is dirty and networked.
    Debug.Log($"List {NetList.Count}/{NetList.Capacity}" +
      $"0:'{NetList[0]}' 1:'{NetList[1]}' 2:'{NetList[2]} 3:'{NetList[3]}'");
  }
}

NetworkString<Size>

NetworkString は文字列データ用の固定サイズのコレクションです。サイズには、あらかじめ定義されている IFixedStorage 型のいずれかを指定できます。X はストレージのサイズを表し、例えば _32 は uint[32] にバックされ、最大で 32 文字の文字列を格納することができます。

C#

public class NetworkStringExample : NetworkBehaviour
{
  [Networked]
  public NetworkString<_16> NetString { get; set; }

  public override void FixedUpdateNetwork()
  {
    if (Runner.IsServer) {
      NetString = System.IO.Path.GetRandomFileName();
    }
  }
}

INetworkStructs での使用

INetworkStruct である Networked Property の値を変更する際、次のいずれかを必ず行ってください:

  • INetworkStruct のコピーで作業し、変更したコピーを Networked Property に適用します。
  • または、Networked Property を ref として定義します。ネットワークプロパティが参照として宣言されている場合、参照は直接変更で きるので、値をコピーする必要はありません。

INetworkStruct 型のネットワークプロパティは、初期化することができます (例として、以下のコードを参照してください)。

これらのネットワーク・コレクションをネットワーク・プロパティとして INetworkStructs で使用します。

C#

public class NetworkDictionaryTest : NetworkBehaviour
{
  [System.Serializable]
  struct NetworkStruct : INetworkStruct
  {
    [Networked, Capacity(16)]
    public NetworkDictionary<int, int> NestedDict => default;

    // NetworkString is a normal struct, so it doesn't require any Fusion attributes
    public NetworkString<_16> NestedString;

    // Define default initialization as a property if needed.
    public static NetworkStruct Defaults
    {
      get
      {
        var result = new NetworkStruct();
        result.NestedDict.Add(0, 0);
        result.NestedString = "Initialized";
        return result;
      }
    }
  }

  // Property declared normally as a value type
  [Networked]
  [UnitySerializeField]
  private NetworkStruct NestedStruct { get; set; } = NetworkStruct.Defaults;

  public void ModifyValues()
  {
    // NestedStruct is a value type, so modifications need to be performed on a copy,
    // and the modified result must be applied back to the property.
    var copy = NestedStruct;
    copy.NestedDict.Add(copy.NestedDict.Count, default);
    copy.NestedString = System.IO.Path.GetRandomFileName();
    NestedStruct = copy;
  }
}

これらのネットワーク化されたコレクションを INetworkStruct参照 ネットワーク化されたプロパティとして使用します。

C#

public class NetworkDictionaryTest : NetworkBehaviour
{
  [System.Serializable]
  struct NetworkStruct : INetworkStruct
  {
    [Networked, Capacity(16)]
    public NetworkDictionary<int, int> NestedDict => default;

    // NetworkString is a normal struct, so it doesn't require any Fusion attributes
    public NetworkString<_16> NestedString;

    public static NetworkStruct Defaults
    {
      get
      {
        var result = new NetworkStruct();
        result.NestedDict.Add(0, 0);
        result.NestedString = "Initialized";
        return result;
      }
    }
  }

  // Property declared as ref type, allowing direct modification of values
  [Networked]
  [UnitySerializeField]
  private ref NetworkStruct NestedStruct => ref MakeRef(NetworkStruct.Defaults);

  public void ModifyValues()
  {
    // NestedStruct was declared as a ref above, so modifications
    // may be made directly to the reference, without need for copies.
    NestedStruct.NestedDict.Add(NestedStruct.NestedDict.Count, default);
    NestedStruct.NestedString = System.IO.Path.GetRandomFileName();
  }
}
Back to top