1. 程式人生 > 實用技巧 >Unity Mirror 自定義序列化器傳輸資料

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資料