C# 在光子单位中序列化Vector3d数据类型

C# 在光子单位中序列化Vector3d数据类型,c#,unity3d,serialization,photon,C#,Unity3d,Serialization,Photon,我想在PUN RPC参数中使用vector3d数据类型,但光子不接受vector3d。我们需要注册并序列化它,以便在RPC方法中使用。我对序列化代码有一些问题 namespace VoxelPlay { internal static class MyCustomDataType { internal static void Register() { PhotonPeer.RegisterType(typ

我想在PUN RPC参数中使用vector3d数据类型,但光子不接受vector3d。我们需要注册并序列化它,以便在RPC方法中使用。我对序列化代码有一些问题

namespace VoxelPlay
{
    internal static class MyCustomDataType
    {
        
        internal static void Register()
        {

            PhotonPeer.RegisterType(typeof(Vector3d), (byte)'V', SerializeVector3d, DeserializeVector3d);

        }

        public static readonly byte[] memVector3d = new byte[3 * 4];

        private static short SerializeVector3d(StreamBuffer outStream, object customobject)
        {
            Vector3d vo = (Vector3d)customobject;

            int index = 0;
            lock (memVector3d)
            {
                byte[] bytes = memVector3d;
                Protocol.Serialize(vo.x, bytes, ref index);      //Getting error: Cannot convert from double to short
                Protocol.Serialize(vo.y, bytes, ref index);
                Protocol.Serialize(vo.z, bytes, ref index);
                outStream.Write(bytes, 0, 3 * 4);
            }
            return 3 * 4;
        }

        private static object DeserializeVector3d(StreamBuffer inStream, short length)
        {
            Vector3d vo = new Vector3d();
            lock (memVector3d)
            {
                inStream.Read(memVector3d, 0, 3 * 4);
                int index = 0;
                Protocol.Deserialize(out vo.x, memVector3d, ref index);
                Protocol.Deserialize(out vo.y, memVector3d, ref index);
                Protocol.Deserialize(out vo.z, memVector3d, ref index);
            }

            return vo;
        }
    }
}
实际上,只(反)序列化
short
int
float

但是,您可以轻松定义自己的
双重
(反)序列化,例如使用和/或

请注意,您的数组无论如何都是错误的!A

我建议您使用
sizeof
进行此类操作;)


或者一种可能稍微有效的方法是直接使用
Buffer.BlockCopy
来转换如下值

internal static class MyCustomDataType
{
    internal static void Register()
    {
        PhotonPeer.RegisterType(typeof(Vector3d), (byte)'V', SerializeVector3d, DeserializeVector3d);
    }

    // Note: Your array had the wrong length anyway!
    // double is not 4 but 8 bytes!
    // Instead of magic numbers rather use sizeof in general
    public const short ByteSize = 3 * sizeof(double);
    public static readonly byte[] memVector3d = new byte[ByteSize];
    public static readonly double[] doubles = new double[3];

    private static short SerializeVector3d(StreamBuffer outStream, object customobject)
    {
        var vo = (Vector3d)customobject;

        lock (memVector3d)
        {
            // Fill the doubles array
            doubles[0] = vo.x;
            doubles[1] = vo.y;
            doubles[2] = vo.z;

            // directly copy that array on the bytes level
            Buffer.BlockCopy(floats, 0, memVector3d, 0, ByteSize);
            
            outStream.Write(memVector3d, 0, ByteSize);
        }
        return ByteSize;
    }

    private static object DeserializeVector3d(StreamBuffer inStream, short length)
    {
        var vo = new Vector3d();
        lock (memVector3d)
        {
            inStream.Read(memVector3d, 0, ByteSize);

            // Just the other way round directly copy into the doubles array on byte level
            Buffer.BlockCopy(memVector3d, 0, floats, 0, ByteSize);
            
            vo.x = doubles[0];
            vo.y = doubles[1];
            vo.z = doubles[2];
        }

        return vo;
    }
}

现在请允许我问一个问题:您真的需要具有双值的
Vector3d

基本上,Unity中的所有内容都使用
float
,因此在某些情况下,您将失去精度。那么,为什么同步时还没有失去精度呢

而且afaik在Photon中具有内置支持,因此无需编写/维护自定义代码


作为替代,如果同步时丢失精度是可以的,但您仍然希望使用
Vector3d
,您可能只需要使用

Protocol.Serialize((float)vo.x, bytes, ref index);
Protocol.Serialize((float)vo.y, bytes, ref index);
Protocol.Serialize((float)vo.z, bytes, ref index);
对于接收,只需确保它使用
float
版本

Protocol.Deserialize(out float x, memVector3d, ref index);
Protocol.Deserialize(out float y, memVector3d, ref index);
Protocol.Deserialize(out float z, memVector3d, ref index);

vo.x = x;
vo.y = y;
vo.z = z;
        

但是再说一遍,为什么不首先简单地使用
Vector3
,假设它像前面提到的那样直接受支持。

我建议您尝试转换vo.x,vo.y,为了消除注释错误,将vo.z加倍。好的,我将尝试this@JesúsNarváez如果错误已经说明给定的
double
无法转换为
short
(方法所期望的类型),那么将(已经!)
double
值转换为
double
不会有多大帮助;)我通过提取x、y和z坐标,将vector3d数据类型转换为vector3,解决了这个问题。谢谢你的帮助。谢谢你的帮助。我正在开发一个体素游戏,我希望体素中心的数据类型是vector3d,在RPC的参数中传递。
Protocol.Deserialize(out float x, memVector3d, ref index);
Protocol.Deserialize(out float y, memVector3d, ref index);
Protocol.Deserialize(out float z, memVector3d, ref index);

vo.x = x;
vo.y = y;
vo.z = z;