Unity Mirror 自定義序列化器傳輸資料
阿新 • • 發佈:2020-07-28
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資料