This document is about: FUSION 2
SWITCH TO

INetworkStruct

概述

INetworkStruct定義了一個結構,Fusion可以將其用於已連網屬性RPC方法。

使用者定義的INetworkStruct必須:

  • 是結構類型
  • 實作INetworkStruct介面
  • Blittable

這些結構也可以作為欄位巢狀在其他INetworkStructs中。

Blittable需求

INetworkStruct必須是Blittable,這意味著它在已管理和未管理脈絡中都有絕對的記憶體使用量。因此,欄位 成員 不可以是

  • 任何參照類型
  • 一個stringchar(而是使用NetworkString
  • 一個bool(而是使用NetworkBool或一個整數)。

注意:布林值可以編譯,並可能適用於大多數用例,但不能保證它們能跨平台工作,因此我們建議使用網路布林值。

了解更多關於.Net Blittable類型

允許的欄位類型

欄位成員直接影響結構的記憶體使用量和對齊,因此必須是Blittable類型。非自動實作的屬性成員和方法成員不會影響記憶體佈局,因此不限於這些類型。

安全欄位類型包括:

  • Blittable基本類型
    • byte, sbyte
    • short, int, long
    • ushort, uint, ulong
    • float, double
  • Blittable Unity結構類型
    • Vector2, Vector3, Vector4
    • Quaternion
    • Matrix4x4
    • Vector2Int, Vector3Int
    • BoundingSphere
    • Bounds
    • Rect
    • BoundsInt
    • RectInt
    • Color, Color32
  • 列舉
  • 系統Blittable類型(比如System.Guid)
  • 使用者定義的Blittable結構
  • 使用者定義的INetworkStructs
  • Fusion定義的INetworkStructs
    • NetworkString<>
    • NetworkBool
    • Ptr
    • Angle
    • BitSet64, BitSet128, BitSet192, BitSet256
    • PlayerRefSet
    • NetworkId
    • NetworkButtons
    • NetworkRNG
    • NetworkObjectGuid
    • NetworkPrefabRef
    • NetworkObjectHeader
    • NetworkPrefabId
    • PlayerRef
    • SceneRef
    • TickTimer
    • IFixedStorage (_2, _4, _8, _16, _32, _64, _128, _256, _512)
  • 網路集合
  • 固定大小的緩衝(不安全: 比如fixed int MyArray[32]

用途

INetworkStruct作為已連網屬性

請注意,結構是值類型。為方便起見,已連網屬性可以使用ref關鍵字。這允許直接修改屬性成員,而無需使用副本。

C#

using Fusion;
using UnityEngine;

public class NetworkStructSampleCode : NetworkBehaviour
{
  public struct NetworkStructExample : INetworkStruct
  {
    public int IntField;
  }

  // For convenience, declared Networked INetworkStructs can use the ref keyword,
  // which allows direct modification of members without needing to work with copies.
  [Networked]
  public ref NetworkStructExample NetworkedStructRef => ref MakeRef<NetworkStructExample>();

  // You can also declare Networked structs normally,
  // but be aware the getter will return a copy and not a reference.
  [Networked]
  public NetworkStructExample NetworkedStruct { get; set; }

  public override void Spawned()
  {
    NetworkedStruct.IntField = 5;
    Debug.Log(NetworkedStruct.IntField); // prints default value (0) and not 5.

    NetworkedStructRef.IntField = 5;
    Debug.Log(NetworkedStructRef.IntField); // prints 5
  }
}

簡單Blittable值類型

非浮點數Blittable基本類型可以宣告為基本欄位。不需要額外的編碼或屬性。對於浮點數類型或基於浮點數的Unity結構(如Vector3),請參閱浮點數類型部分。

C#

using Fusion;
using UnityEngine;


public class NetworkStructSampleCode : NetworkBehaviour
{
  public struct NetworkStructExample : INetworkStruct
  {
    // Non-float primitive structs and Enum types, can be used normally as a field.
    // Except bools, which are non-blittable and cannot be used as fields.
    public SnapAxis   EnumField;
    public int        IntField;
    public Color32    Color32Field;
    public Vector2Int VectorIntField;
  }

浮點數類型

浮點數類型(基礎類型和常見的基於Unity浮點數的類型,用於包裹浮點數)可以用作欄位。然而,當用作欄位時,Fusion ILWeaver不會生成壓縮處理。

為了自動壓縮這些浮點數類型,請在具有預設實作的屬性上使用[Networked]屬性。Fusion的ILWeaver將用壓縮處理取代實作。

C#

using Fusion;
using UnityEngine;
public class NetworkStructSampleCode : NetworkBehaviour
{
  public struct NetworkStructExample : INetworkStruct
  {
  // Recognized float-based Networked Properties will implement Fusion's compression.
  // Such as Float, Double, Vector2, Vector3, Color, Matrix etc.
  // Note: an auto-implemented property is allowed here.
  [Networked]
  public Vector3 CompressedVector { get; set; }

  [Networked]
  public float   CompressedFloat { get; set; }

  // Float types declared as fields will be uncompressed and will replicate bit for bit.
  // Typically you want compression, so this handling should not be used in most cases.
  public Vector3 UncompressedVector;
  public float   UncompressedFloat;
}

布林值

布林值非Blittable,因此bool類型 無法 安全地用於欄位。Fusion提供了一個NetworkBool類型,它可以與bool互換使用,後者比bool屬性需要更少的程式碼來實作,並且是Blittable。

C#

using Fusion;
using UnityEngine;

public class NetworkStructSampleCode : NetworkBehaviour
{
  public struct NetworkStructExample : INetworkStruct
  {
    // The preferred way to network a boolean is to use the NetworkBool type.
    public NetworkBool NetworkBool;

    // [Networked] is required for the primitive bool in order to instruct
    // the ILWeaver to create the required backing int and implementation.
    // Note that we do NOT declare this as an auto-implemented property,
    // but instead with an empty getter/setter.
    [Networked]
    public bool PrimitiveBool { get => default; set { } }

 }

bool類型可用於屬性,只要它們不是自動實作的。

字串

字串和Char類型非Blittable,因此string類型不能安全地用於欄位,但可用於非自動實作的屬性。

Fusion提供一個NetworkString<_size>類型,該類型可以與string互換使用,與string屬性相比,它產生的分配更少,效能更高,實作所需的程式碼更少。

C#

using Fusion;
using UnityEngine;

public class NetworkStructSampleCode : NetworkBehaviour
{
  public struct NetworkStructExample : INetworkStruct
  {
    // The easiest and cleanest way to use a string in an INetworkStruct
    // is to use the Fusion NetworkString<> type as a field.
    // _16 here indicates that we are allocating a capacity of 16 characters.
    public NetworkString<_16> Name;

    // Optionally a regular string can be used as a Property (not a field)
    [Networked]       // Notifies the ILWeaver to extend this property
    [Capacity(16)]    // allocates memory for 16 characters
    [UnityMultiline]  // Optional attribute to force multi-line in inspector.
    public string StringProperty { get => default; set { } }
  }

  // For convenience, declared Networked INetworkStructs can use the ref keyword,
  // which allows direct modification of members without needing to deal with copies.
  [Networked]
  public ref NetworkStructExample NetworkedStructRef => ref MakeRef<NetworkStructExample>();

  public override void Spawned()
  {
    NetworkedStructRef.Name = "John Conner";
  }
}

網路集合

關於使用網路集合的細節,請參照網路集合頁面。

C#

using Fusion;
using UnityEngine;

public class NetworkStructSampleCode : NetworkBehaviour
{
  public struct  NetworkStructExample : INetworkStruct
  {
    // Network Collections must be NOT be declared as auto-implemented properties,
    // and with only a default getter (the IL Weaver will replace the getter).
    [Networked, Capacity(16)]
    public NetworkDictionary<int, NetworkString<_4>> DictOfStrings => default;
  }

  // For convenience, declared Networked INetworkStructs can use the ref keyword,
  // which allows direct modification of members without needing to work with copies.
  [Networked]
  public ref NetworkStructExample NetworkedStructRef => ref MakeRef<NetworkStructExample>();

  public override void Spawned()
  {
    NetworkedStructRef.DictOfStrings.Set(1, "One");
    NetworkedStructRef.DictOfStrings.Set(4, "Four");

    Debug.Log($"Values Set: " +
              $"1:{NetworkedStructRef.DictOfStrings.Get(1)} " +
              $"4:{NetworkedStructRef.DictOfStrings[4]}");
  }
}

Fusion物件與ID類型

雖然INetworkStruct無法透過Fusion物件的ID解析Fusion物件(它不知道相關聯的網路運行器),但它仍然可以存儲這些ID。必須在網路行為中查找參照,因為需要網路運行器執行個體來解析這些查找。

C#

using Fusion;
using UnityEngine;

public class NetworkStructSampleCode : NetworkBehaviour
{
  public struct NetworkStructExample : INetworkStruct
  {
    // Fusion Object and Ref ID types are backed by integers,
    // so they are blittable and can be used as basic fields.
    public NetworkId          NetworkIdField;
    public NetworkBehaviourId NetworkBehaviourIdField;
    public PlayerRef          PlayerRefField;
  }

  [Networked]
  public ref NetworkStructExample NetworkedStructRef => ref MakeRef<NetworkStructExample>();


  public override void Spawned()
  {
    // Capture this NetworkBehaviour's Id.
    NetworkedStructRef.NetworkBehaviourIdField = this;
  }

  public override unsafe void FixedUpdateNetwork()
  {
    // Look up the NetworkObject on the Runner using the networked ID.
    Runner.TryFindBehaviour(NetworkedStructRef.NetworkBehaviourIdField, out var nb);
    Debug.LogWarning($"NBID: {(nb == null ? "Null NB" : nb.Id.ToString())}");
  }
}

INetworkStruct巢狀

由於實作INetworkStruct的結構是Blittable,因此它們可以用作其他INetworkStruct定義中的欄位。

C#

using Fusion;
using UnityEngine;

public class NetworkStructSampleCode : NetworkBehaviour
{
  public struct InnerStruct : INetworkStruct
  {
    public int IntField;
  }

  public struct OuterStruct: INetworkStruct
  {
    public InnerStruct Inner;
  }

  [Networked]
  public ref OuterStruct Outer => ref MakeRef<OuterStruct>();
}

OnChanged附有巢狀INetworkStructs

巢狀的INetworkStructsOnChanged回調檢測整個結構的任何更改,並且無法監測單一值的更改。如果您需要單一欄位/屬性的回調,請將該變數作為其自己的已連網屬性保留在NetworkBehaviour中。

C#

using Fusion;
using UnityEngine;

public class NetworkStructSampleCode : NetworkBehaviour
{

  public struct NetworkStructExample : INetworkStruct
  {
    public NetworkBool NetworkBool;
  }

  [Networked(OnChanged = nameof(OnNetworkStructChanged))]
  public ref NetworkStructExample NetworkedStructRef => ref MakeRef<NetworkStructExample>();

  // Note that OnChanged monitors any changes to the ENTIRE INetworkStruct,
  // so this callback will be triggered by ANY changes to the struct.
  public static void OnNetworkStructChanged(Changed<NetworkStructSampleCode> changed)
  {
    Debug.LogWarning($"Bool changed {changed.Behaviour.NetworkedStructRef.NetworkBool}");
  }

  public override unsafe void FixedUpdateNetwork()
  {
    // Toggle the nested bool value every tick, to trigger the OnChanged callback.
    NetworkedStructRef.PrimitiveBool = !NetworkedStructRef.NetworkBool;
  }
}

固定大小的緩衝區(不安全)

不安全的固定大小緩衝區是有效的,因為它們具有嚴格定義的記憶體使用量和對齊。

C#

public struct NetworkStructExample : INetworkStruct
{
  // Fixed is allowed, and can be used for advanced custom unsafe handling.
  public unsafe fixed byte FixedArray[32];
}
Back to top