NGO 에서는 INetworkSerializable 인터페이스를 network serialization를 위한 유저가 정의한 type을 실행시킬 수 있습니다! 유저가 정의한 type외에도 기본적으로 C#과 Unity Primitive을 지원합니다!
C# Primitives
Unity Primitives
Color, Color32, Vector2, Vector3, Vector4, Quaternion, Ray, Ray2D을 지원합니다!
유저가 정의한 Type
Enum Types
Arrays
int[] 같은 배열 형태를 처리하기 위해서는 Unity primitive type이나 Vector3 같이 사용하면 되지만,
string[]같은 배열 형태를 처리하기 위해서는 구조체나 함수같은 컨테이너가 필요합니다. 그 컨테이너에는 반드시 INetworkSerializable 를 상속받아야 합니다
[ClientRpc]
void SendMessagesClientRpc(StringContainer[] messages)
{
foreach (var stringContainer in stringContainers)
{
Debug.Log($"{stringContainer.SomeText}");
}
}
public class StringContainer : INetworkSerializable
{
public string SomeText;
public void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter
{
if (serializer.IsWriter)
{
serializer.GetFastBufferWriter().WriteValueSafe(SomeText);
}
else
{
serializer.GetFastBufferReader().ReadValueSafe(out SomeText);
}
}
}
Example: Move
public struct MyMoveStruct : INetworkSerializable
{
public Vector3 Position;
public Quaternion Rotation;
public bool SyncVelocity;
public Vector3 LinearVelocity;
public Vector3 AngularVelocity;
void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter
{
// Position & Rotation
serializer.SerializeValue(ref Position);
serializer.SerializeValue(ref Rotation);
// LinearVelocity & AngularVelocity
serializer.SerializeValue(ref SyncVelocity);
if (SyncVelocity)
{
serializer.SerializeValue(ref LinearVelocity);
serializer.SerializeValue(ref AngularVelocity);
}
}
}
NetworkObject & NetworkBehaviour
GameObjects, NetworkObjects, NetworkBehaviour은 직렬화될 수 없는 Type입니다, 그레서 기본적으로 RPC나 NetworkVariable을 사용할 순 없습니다!
위와 같은 Type을 사용하기 위해선 2가지 Wrapper가 있습니다
NetworkObjectReference
NetworkObjectReference 는 NetworkObject를 위해 사용될 수 있으며 NetworkObjects가 미리 Spawn되어 있는 상태에서만 가능합니다!
public class Weapon : NetworkBehaviour
{
public void ShootTarget(GameObject target)
{
var targetObject = target.GetComponent<NetworkObject>();
ShootTargetServerRpc(targetObject);
}
[ServerRpc]
public void ShootTargetServerRpc(NetworkObjectReference target)
{
if (target.TryGet(out NetworkObject targetObject))
{
// deal damage or something to target object.
}
else
{
// Target not found on server, likely because it already has been destroyed/despawned.
}
}
}
위 코드를 더 쉽게 사용하는 방법이 있습니다
public class Weapon : NetworkBehaviour
{
public void ShootTarget(GameObject target)
{
ShootTargetServerRpc(target);
}
[ServerRpc]
public void ShootTargetServerRpc(NetworkObjectReference target)
{
NetworkObject targetObject = target;
}
}
NetworkBehaviourReference
NetworkBehaviourReference 는 NetworkObjectReference 와 비슷하게 작동합니다!
하지만 생성된 NetworkObject에 구체적인 NetworkBehaviour 컴포넌트를 참조하는데 사용됩니다!
public class Health : NetworkBehaviour
{
public NetworkVariable<int> Health = new NetworkVariable<int>();
}
public class Weapon : NetworkBehaviour
{
public void ShootTarget(GameObject target)
{
var health = target.GetComponent<Health>();
ShootTargetServerRpc(health, 10);
}
[ServerRpc]
public void ShootTargetServerRpc(NetworkBehaviourReference health, int damage)
{
if (health.TryGet(out Health healthComponent))
{
healthComponent.Health.Value -= damage;
}
}
}