Unity Mirror 自定义序列化器传输数据

Mirror支持许多内建类型的传输,具体可参考Mirror的NetworkWriter类的定义。

而一些自定义的类型,比如下面这个:

using Mirror;
using UnityEngine;

public class CustomDataTypes : NetworkBehaviour
{
    public class Item
    {
        public string name;
    }

    public class Armour : Item
    {
        public int protection;
        public int weight;
    }

    public class Potion : Item
    {
        public int health;
    }

    public override void OnStartAuthority()
    {
        base.OnStartAuthority();

        Potion potion = new Potion();
        potion.name = "Health Potion";
        potion.health = 5;

        CmdSendItem(potion);
    }

    [Command]
    private void CmdSendItem(Item item)
    {
        if(item is Item)
            Debug.Log("Item name is " + item.name);

        if (item is Potion potion)
            Debug.Log("Potion gives " + potion.health + " health.");
    }
}

  

其中存在继承关系,如果尝试直接传输,会发现CmdSendItem的第二条log没有输出:

下面提供一种自定义序列化器:

using Mirror;
using System;
using static CustomDataTypes;

public static class ItemSerializer
{
    private const byte ITEM_ID = 0;
    private const byte POTION_ID = 1;
    private const byte ARMOUR_ID = 2;

    public static void WriteItem(this NetworkWriter writer, Item item)
    {
        if(item is Potion potion)
        {
            writer.WriteByte(POTION_ID);
            writer.WriteString(potion.name);
            writer.WritePackedInt32(potion.health);
        }
        else if(item is Armour armour)
        {
            writer.WriteByte(ARMOUR_ID);
            writer.WriteString(armour.name);
            writer.WritePackedInt32(armour.protection);
            writer.WritePackedInt32(armour.weight);
        }
        else
        {
            writer.WriteByte(ITEM_ID);
            writer.WriteString(item.name);
        }
    }

    public static Item ReadItem(this NetworkReader reader)
    {
        byte id = reader.ReadByte();

        switch (id)
        {
            case POTION_ID:
                return new Potion
                {
                    name = reader.ReadString(),
                    health = reader.ReadPackedInt32()
                };
            case ARMOUR_ID:
                return new Armour
                {
                    name = reader.ReadString(),
                    protection = reader.ReadPackedInt32(),
                    weight = reader.ReadPackedInt32()
                };
            case ITEM_ID:
                return new Item
                {
                    name = reader.ReadString()
                };
            default:
                throw new Exception($"Unhandled item type for {id}.");
        }
    }
}

  

再次运行:

可以看到成功打印出Potion的health数据

原文地址:https://www.cnblogs.com/yl-xy/p/13389830.html