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数据