com.unity.netcode.gameobjects
com.unity.netcode.gameobjects copied to clipboard
Add built-in serialization for `UnityEngine.Pose`
Is your feature request related to a problem? Please describe.
Unity provide a primitive struct called Pose, which is a composition of a Vector3 and a Quaternion. This type is not very known, but very usefull, for instance in a single list of waypoints that also need to store their rotation.
This type is not listed in the documentation: https://docs-multiplayer.unity3d.com/netcode/current/advanced-topics/serialization/unity-primitives/, and doesn't work if used in an Rpc or NetworkVariable.
[ServerRpc()]
private void TestServerRpc(Pose p)
{
Debug.Log(p);
}
Assets\Scripts\Test.cs(32,13): error - TestServerRpc - Don't know how to deserialize UnityEngine.Pose. RPC parameter types must either implement INetworkSerializeByMemcpy or INetworkSerializable. If this type is external and you are sure its memory layout makes it serializable by memcpy, you can replace UnityEngine.Pose with ForceNetworkSerializeByMemcpy`1<UnityEngine.Pose>, or you can create extension methods for FastBufferReader.ReadValueSafe(this FastBufferReader, out UnityEngine.Pose) and FastBufferWriter.WriteValueSafe(this FastBufferWriter, in UnityEngine.Pose) to define serialization for this type.
private NetworkList<Pose> poseList = new NetworkList<Pose>();
private void AddAnItem() {
poseList.Add(new Pose(transform.position, transform.rotation));
}
ArgumentException: Type UnityEngine.Pose is not supported by NetworkVariable`1. If this is a type you can change, then either implement INetworkSerializable or mark it as serializable by memcpy by adding INetworkSerializeByMemcpy to its interface list. If not, assign serialization code to UserNetworkVariableSerialization.WriteValue, UserNetworkVariableSerialization.ReadValue, and UserNetworkVariableSerialization.DuplicateValue, or if it's serializable by memcpy (contains no pointers), wrap it in ForceNetworkSerializeByMemcpy`1.
Describe the solution you'd like
Add a default serializer for UnityEngine.Pose.
Describe alternatives you've considered Today, users have to implement their own serializer or send Vector3 and Quaterion separately.
@michalChrobot Hi, I have updated my PR. Please see #2677
Hi, thanks for pinging. We will try to find some time to check it out next week
Hi @PitouGames ,
We will look into the possibility of making this a default type. However, you can always create your own Custom Serializers for various types that will work for RPCs, INetworkSerializable, and NetworkVariables.
As an example, adding Pose would look something like this:
/// <summary>
/// Custom Serialization Types
/// Includes <see cref="Pose"/> example.
/// </summary>
public static class SerializationExtensions
{
public static void InitializePoseNetworkVariable()
{
UserNetworkVariableSerialization<Pose>.WriteValue = SerializationExtensions.WriteValueSafe;
UserNetworkVariableSerialization<Pose>.ReadValue = SerializationExtensions.ReadValueSafe;
}
public static void ReadValueSafe(this FastBufferReader reader, out Pose pose)
{
reader.ReadValueSafe(out Vector3 position);
reader.ReadValueSafe(out Quaternion rotation);
pose = new Pose(position, rotation);
}
public static void WriteValueSafe(this FastBufferWriter writer, in Pose pose)
{
writer.WriteValueSafe(pose.position);
writer.WriteValueSafe(pose.rotation);
}
public static void SerializeValue<TReaderWriter>(this BufferSerializer<TReaderWriter> serializer, ref Pose pose) where TReaderWriter : IReaderWriter
{
if (serializer.IsReader)
{
pose = new Pose();
}
serializer.SerializeValue(ref pose);
}
}
You would just need to invoke SerializationExtensions.InitializePoseNetworkVariable when your application starts (i.e. before any NetworkVariable is serialized) in order to add the NetworkVariable support.
Thank you to both of you for the reply.
Yes Noel, that is what I meant when I wrote:
Describe alternatives you've considered Today, users have to implement their own serializer or send Vector3 and Quaterion separately.
Thank you for the "official" sample code.
But it's developer work that can be avoided since Pose is an Engine type, just as Vector3 or Quaternion 😉