Network Collection - cheona-thousand-man/Unity-myBasics-Wiki GitHub Wiki

๊ฐœ์š”

  • Fusion์€ ๋„คํŠธ์›Œํฌ๋œ ์†์„ฑ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ตฌ์กฐ์ฒด ๊ธฐ๋ฐ˜์˜ ์ปฌ๋ ‰์…˜ ํƒ€์ž… ์ œ๊ณต
    • NetworkArray
    • NetwrkDictionary<K, V>
    • NetworkLinkedList
    • NetworkString

์ด ์ปฌ๋ ‰์…˜๋“ค์€ ์ฐธ์กฐ ํƒ€์ž…์ด ์•„๋‹Œ ๊ตฌ์กฐ์ฒด๋ผ๋Š” ์ ์„ ์œ ์˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ผ๋ถ€ C# ์ปฌ๋ ‰์…˜๊ณผ์˜ ์‚ฌ์šฉ๋ฒ• ์ฐจ์ด๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค (INetworkStructs์—์„œ ์‚ฌ์šฉ๋ฒ• ์ฐธ์กฐ)

ํ—ˆ์šฉ๋˜๋Š” T/K/V ํƒ€์ž…

  • ๊ธฐ๋ณธ ํƒ€์ž…๋“ค
    • byte, sbyte
    • Int16, Int32, Int64
    • UInt16, UInt32, UInt64
    • float
    • double
  • ์œ ๋‹ˆํ‹ฐ ๊ตฌ์กฐ์ฒด ํƒ€์ž… (ILWeaver.cs์— ์ •์˜๋จ)
    • Vector2, Vector3, Vector4
    • Quaternion
    • Matrix4x4
    • Vector2Int, Vector3Int
    • BoundingSphere
    • Bounds
    • Rect
    • BoundsInt
    • RectInt
    • Color, Color32
  • System.Guid
  • ์‚ฌ์šฉ์ž ์ •์˜ INetworkStructs
  • Fusion ์ •์˜ INetworkStructs
    • NetworkString
    • 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์—๊ฒŒ ์ด๋Ÿฌํ•œ ์ปฌ๋ ‰์…˜์„ ๊ด€๋ จ๋œ NetworkRunner์™€ Simulation ์ธ์Šคํ„ด์Šค์˜ ๋ฐฑ์—… ๋ฉ”๋ชจ๋ฆฌ์— ์—ฐ๊ฒฐํ•˜๋Š” ์†์„ฑ ์ฝ”๋“œ๋ฅผ ์ƒ์„ฑํ•˜๋„๋ก ์ง€์‹œ
  • [Capacity] ์†์„ฑ์€ ์ตœ๋Œ€ ์š”์†Œ ์ˆ˜๋ฅผ ์ง€์ •ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ
    • ์‚ฌ์šฉ ์—ฌ๋ถ€์— ๊ด€๊ณ„์—†์ด ์ด๋งŒํผ์˜ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ํ• ๋‹น๋˜๋ฏ€๋กœ ์˜ˆ์ƒ๋˜๋Š” ์ตœ๋Œ€ ์š”์†Œ ์ˆ˜๋ฅผ ์ถฉ์กฑํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ€์žฅ ์ž‘์€ ์ˆซ์ž ์„ ํƒ
    • ์š”์†Œ๋Š” ๊ฐ’์ด ๋ณ€๊ฒฝ๋˜์ง€ ์•Š๋Š” ํ•œ ๋„คํŠธ์›Œํฌ ํŠธ๋ž˜ํ”ฝ ์ƒ์„ฑX
// ๊ธฐ๋ณธ ๋„คํŠธ์›Œํฌ ์ปฌ๋ ‰์…˜ ์„ ์–ธ
[Networked, Capacity(4)]
NetworkArray<int> NetArray => default;

์ดˆ๊ธฐํ™”

NetworkArray, NetworkDictionary, NetworkLinkedList๊ฐ€ NetworkBehaviour์˜ ๋„คํŠธ์›Œํฌ๋œ ์†์„ฑ์œผ๋กœ ์„ ์–ธ๋  ๋•Œ MakeInitializer()๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ดˆ๊ธฐ ๊ฐ’ ์ •์˜

[Networked]
[Capacity(4)] // ์ปฌ๋ ‰์…˜์˜ ๊ณ ์ • ์šฉ๋Ÿ‰ ์„ค์ •
NetworkArray<int> NetArray { get; }
  // ์„ ํƒ์  ์ดˆ๊ธฐํ™”
  = MakeInitializer(new int[] { 0, 1, 2, 3 });

[Networked, Capacity(4)]
NetworkLinkedList<int> NetLList { get; }
  // ์„ ํƒ์  ์ดˆ๊ธฐํ™”
  = MakeInitializer(new int[] { 0, 1, 2, 3 });

[Networked, Capacity(2)]
NetworkDictionary<int, int> NetDict { get; }
  // ์„ ํƒ์  ์ดˆ๊ธฐํ™”
  = MakeInitializer(new Dictionary<int, int> { { 0, 0 }, { 1, 1 } });

NetworkArray

  • NetworkArray๋Š” Fusion์—์„œ ๋„คํŠธ์›Œํฌ๋œ ์†์„ฑ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” C# ๋ฐฐ์—ด์˜ ๊ตฌ์กฐ์ฒด ๋Œ€์ฒด๋ฌผ
  • NetworkArray๋Š” ๊ฐ’์„ ๊ฐ€์ ธ์˜ค๊ณ  ์„ค์ •ํ•˜๋Š” ๋ฉ”์„œ๋“œ์™€ ๋‹ค๋ฅธ ์ปฌ๋ ‰์…˜์œผ๋กœ ๋ณต์‚ฌํ•  ์ˆ˜ ์žˆ๋Š” IEnumerable ์ปฌ๋ ‰์…˜

์ฃผ์š” ๋ฉ”์„œ๋“œ

  • Get(int index)
  • Set(int, T)
public class CollectionTestsArray : NetworkBehaviour
{
  [Networked]
  [Capacity(4)] // ์ปฌ๋ ‰์…˜์˜ ๊ณ ์ • ์šฉ๋Ÿ‰ ์„ค์ •
  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");

    // NetworkDictionary ์†์„ฑ์—์„œ๋Š” ์œ ํšจํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ Set()์„ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
    // 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๋Š” Fusion์—์„œ ๋„คํŠธ์›Œํฌ๋œ ์†์„ฑ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” C# ๋”•์…”๋„ˆ๋ฆฌ์˜ ๊ตฌ์กฐ์ฒด ๋Œ€์ฒด๋ฌผ

์ฃผ์š” ๋ฉ”์„œ๋“œ ๋ฐ ์†์„ฑ

  • Clear()
  • Add(K, V)
  • Remove(K)
  • ContainsKey(K)
  • ContainsValue(V)
  • Get(K)
  • Set(K, V)
  • this[K]
  • Capacity
  • Count
public class NetworkDictionaryExample : NetworkBehaviour
{
  [Networked]
  [Capacity(4)] // ์ปฌ๋ ‰์…˜์˜ ๊ณ ์ • ์šฉ๋Ÿ‰ ์„ค์ •
  [UnitySerializeField] // ์ธ์ŠคํŽ™ํ„ฐ์— ์ด private ์†์„ฑ์„ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค.
  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");

    // ์ธ๋ฑ์„œ๋กœ ๊ฐ’์„ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์€ ์œ ํšจํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
    // ์ด๊ฒƒ์ด struct ๊ธฐ๋ฐ˜ NetworkDictionary์™€ C# Dictionary ์‚ฌ์šฉ๋ฒ•์˜ ์ฐจ์ด์  ์ค‘ ํ•˜๋‚˜์ž…๋‹ˆ๋‹ค.
    // NetDict[0] = "Foo"; // ์ด๋Š” ์œ ํšจํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

    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

  • NetworkLinkedList๋Š” NetworkArray์˜ ๊ตฌ์กฐ์ฒด ๋Œ€์ฒด๋ฌผ
    • ์ถ”๊ฐ€๋œ ํ•ญ๋ชฉ์€ ๋ฐฑ์—… ๋ฐ์ดํ„ฐ์˜ ๋นˆ ์Šฌ๋กฏ์— ์ถ”๊ฐ€
    • ํ•ญ๋ชฉ์ด ์ œ๊ฑฐ๋  ๋•Œ, ๋ฐฑ์—… ๋ฐฐ์—ด ๋ฐ์ดํ„ฐ๋Š” ๋‹ค๋ฅธ ์š”์†Œ๋ฅผ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ์ด๋™X
    • ๊ตฌ์กฐ์ฒด์˜ ์ผ๋ถ€๋กœ ์š”์†Œ ์ˆœ์„œ์— ๋Œ€ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅ
    • ์—ด๊ฑฐ์ž์™€ ์ธ๋ฑ์„œ๋Š” ๋ฐฑ์—… ๋ฐฐ์—ด์—์„œ ์š”์†Œ๊ฐ€ ์œ„์น˜ํ•œ ์ˆœ์„œ๊ฐ€ ์•„๋‹Œ ์ถ”๊ฐ€๋œ ์ˆœ์„œ๋Œ€๋กœ ์š”์†Œ ๋ฐ˜ํ™˜
public class NetworkLinkedListExample : NetworkBehaviour
{
  [Networked]
  [Capacity(4)] // ์ปฌ๋ ‰์…˜์˜ ๊ณ ์ • ์šฉ๋Ÿ‰ ์„ค์ •
  [UnitySerializeField] // ์ธ์ŠคํŽ™ํ„ฐ์— ์ด private ์†์„ฑ์„ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค.
  private NetworkLinkedList<NetworkString<_32>> NetList { get; }
    = MakeInitializer(new NetworkString<_32>[] { "Zero", "One", "Two", "Four"});

  public override void Spawned()
  {
    // ๋‘ ๋ฒˆ์งธ ํ•ญ๋ชฉ์„ ์ œ๊ฑฐํ•˜์—ฌ ํ•˜๋‚˜์˜ ๋นˆ ์šฉ๋Ÿ‰์„ ๋‚จ๊น๋‹ˆ๋‹ค.
    NetList.Remove("One");

    // ๊ฐ’์œผ๋กœ ํ•ญ๋ชฉ ์ฐพ๊ธฐ
    NetList.Set(NetList.IndexOf("Two"), "TWO");

    // ์ƒˆ ํ•ญ๋ชฉ ์ถ”๊ฐ€. ๋ฉ”๋ชจ๋ฆฌ์—์„œ๋Š” ์ด์ œ ์—ด๋ฆฐ ๋ฉ”๋ชจ๋ฆฌ ์œ„์น˜๋ฅผ ์ฑ„์›๋‹ˆ๋‹ค.
    NetList.Add("Five");

    // ์ธ๋ฑ์Šค ์ˆœ์„œ๋Š” ๊ทธ๋Œ€๋กœ ์œ ์ง€๋˜๋ฏ€๋กœ,
    // ๋ณ€๊ฒฝ๋œ ๋ฉ”๋ชจ๋ฆฌ ์œ„์น˜๋งŒ ๋”ํ‹ฐ ์ƒํƒœ๊ฐ€ ๋˜์–ด ๋„คํŠธ์›Œํฌ๋กœ ์ „์†ก๋ฉ๋‹ˆ๋‹ค.
    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์˜ ๊ฐ’์„ ์ˆ˜์ •ํ•  ๋•Œ๋Š” ๋‹ค์Œ ์ค‘ ํ•˜๋‚˜๋ฅผ ๋ฐ˜๋“œ์‹œ ์ˆ˜ํ–‰

  • INetworkStruct์˜ ๋ณต์‚ฌ๋ณธ์œผ๋กœ ์ž‘์—…ํ•œ ํ›„ ์ˆ˜์ •๋œ ๋ณต์‚ฌ๋ณธ์„ ๋„คํŠธ์›Œํฌ ์†์„ฑ์— ์ ์šฉ
  • ๋„คํŠธ์›Œํฌ ์†์„ฑ์„ ์ฐธ์กฐ๋กœ ์ •์˜
    • ๋„คํŠธ์›Œํฌ ์†์„ฑ์ด ์ฐธ์กฐ๋กœ ์„ ์–ธ๋œ ๊ฒฝ์šฐ, ๋ณต์‚ฌ๋ณธ์„ ๋งŒ๋“ค ํ•„์š” ์—†์ด ์ฐธ์กฐ๋ฅผ ์ง์ ‘ ์ˆ˜์ • ๊ฐ€๋Šฅ

๋„คํŠธ์›Œํฌ ์†์„ฑ ์œ ํ˜•์ธ INetworkStruct๋Š” ์ดˆ๊ธฐํ™” ๊ฐ€๋Šฅ

1. Networked Property๋กœ Networked Collection ์‚ฌ์šฉ

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

    // NetworkString์€ ์ผ๋ฐ˜ ๊ตฌ์กฐ์ฒด์ด๋ฏ€๋กœ Fusion ์†์„ฑ์ด ํ•„์š” ์—†์Šต๋‹ˆ๋‹ค.
    public NetworkString<_16> NestedString;

    // ํ•„์š”ํ•œ ๊ฒฝ์šฐ ๊ธฐ๋ณธ ์ดˆ๊ธฐํ™”๋ฅผ ์†์„ฑ์œผ๋กœ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.
    public static NetworkStruct Defaults
    {
      get
      {
        var result = new NetworkStruct();
        result.NestedDict.Add(0, 0);
        result.NestedString = "Initialized";
        return result;
      }
    }
  }

  // ๊ฐ’ ํƒ€์ž…์œผ๋กœ ์ •์ƒ์ ์œผ๋กœ ์„ ์–ธ๋œ ์†์„ฑ
  [Networked]
  [UnitySerializeField]
  private NetworkStruct NestedStruct { get; set; } = NetworkStruct.Defaults;

  public void ModifyValues()
  {
    // NestedStruct๋Š” ๊ฐ’ ํƒ€์ž…์ด๋ฏ€๋กœ ์ˆ˜์ •์€ ๋ณต์‚ฌ๋ณธ์—์„œ ์ˆ˜ํ–‰ํ•˜๊ณ ,
    // ์ˆ˜์ •๋œ ๊ฒฐ๊ณผ๋ฅผ ์†์„ฑ์— ๋‹ค์‹œ ์ ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
    var copy = NestedStruct;
    copy.NestedDict.Add(copy.NestedDict.Count, default);
    copy.NestedString = System.IO.Path.GetRandomFileName();
    NestedStruct = copy;
  }
}

2. ์ฐธ์กฐ๋œ Networked Property๋กœ Networked Collection ์‚ฌ์šฉ

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

    // NetworkString์€ ์ผ๋ฐ˜ ๊ตฌ์กฐ์ฒด์ด๋ฏ€๋กœ Fusion ์†์„ฑ์ด ํ•„์š” ์—†์Šต๋‹ˆ๋‹ค.
    public NetworkString<_16> NestedString;

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

  // ์ฐธ์กฐ ํƒ€์ž…์œผ๋กœ ์„ ์–ธ๋œ ์†์„ฑ, ๊ฐ’์˜ ์ง์ ‘ ์ˆ˜์ • ๊ฐ€๋Šฅ
  [Networked]
  [UnitySerializeField]
  private ref NetworkStruct NestedStruct => ref MakeRef(NetworkStruct.Defaults);

  public void ModifyValues()
  {
    // NestedStruct๋Š” ์œ„์—์„œ ์ฐธ์กฐ๋กœ ์„ ์–ธ๋˜์—ˆ์œผ๋ฏ€๋กœ,
    // ๋ณต์‚ฌ๋ณธ ์—†์ด ์ฐธ์กฐ๋ฅผ ์ง์ ‘ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    NestedStruct.NestedDict.Add(NestedStruct.NestedDict.Count, default);
    NestedStruct.NestedString = System.IO.Path.GetRandomFileName();
  }
}
โš ๏ธ **GitHub.com Fallback** โš ๏ธ