This document is about: FUSION 2
SWITCH TO

INetworkStruct

概要

INetworkStructは、Fusionが ネットワークプロパティRPCメソッドに使用する構造体を定義します。

ユーザー定義のINetworkStructは以下の条件を満たす必要があります:

  • 構造体型である点
  • INetworkStructインターフェースを実装している点
  • [blittable]である点(https://learn.microsoft.com/en-us/dotnet/framework/interop/blittable-and-non-blittable-types)

これらの構造体は、他のINetworkStructs内のフィールドとしてネストできます。

blittableの要件

INetworkStructはblittableである必要があります。つまり、これは管理されたコンテキストと管理されていないコンテキストの両方で絶対的なメモリフットプリントを持つことを意味します。このため、フィールド メンバーは以下に該当しません:

  • すべての参照型
  • stringまたはchar (代わりにNetworkStringを使用します)
  • bool (代わりにNetworkBoolまたはintを使用します)。

注: ほとんどのユースケースで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
  • Enums
  • システム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)
  • ネットワークコレクション
  • 固定サイズバッファ (unsafe: such as fixed int MyArray[32])

使用

ネットワークプロパティとしてのINetworkStruct

構造体はvalue型である点に留意してください。 利便性のためネットワークプロパティは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 Value型

非浮動小数点数のblittableなプリミティブは、基本フィールドとして宣言するだけで十分です。追加のコーディングや属性は必要ありません。浮動小数点数の型、またはFloatベースの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のfloatベースの型)はフィールドとして使用することができます。ただし、フィールドとして使用される場合にはFusion ILWeaverによる圧縮処理は生成されません。

これらの浮動小数点型を圧縮するには、デフォルトの実装でプロパティに[ネットワーク]属性を使用します。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;
}

Bool

Boolはblittableではないため、bool型をフィールドとして安全に使用することはできません。Fusionはboolと交換して使用できるNetworkBool型を提供しています。この型は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型は、自動実装でない限りプロパティに使用できます。

文字列

String型とChar型はblittableではありません。このため、string型はフィールドとして安全に使用することができません。ただし、自動実装でないプロパティには使用できます。 Fusionはstringと交換可能なNetworkString<_size>型を提供します。この型はより少ない割り当てを生成し、パフォーマンス性が高いです。また、実装に必要なコードは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で解決することはできません(関連するNetworkRunnerについては把握されていません)。ただし、それらのIDを保存することは可能です。参照を見つける必要がある場合は、NetworkBehaviour内で行う必要があります。なぜなら、これらの検索の解決にはNetworkRunnerインスタンスが必要なためです。

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>();
}

ネストされたINetworkStructをともなうOnChanged

ネストされたINetworkStructsOnChangedコールバックは構造体全体の変更を検出し、個々の値の変更を監視することはできません。個々のフィールドやプロパティへのコールバックが必要な場合は、その変数を独自のネットワークプロパティとしてNetworkBehaviourrに保持してください。

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;
  }
}

固定サイズのバッファ (Unsafe)

安全でない固定サイズのバッファは厳密に定義されたメモリフットプリントと整列を持っているため有効です。

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