英文原文:
https://mirror-networking.gitbook.io/docs/guides/serialization
本页深入介绍了序列化,有关基础知识,请参阅 DataTypes。
Mirror 使用 Weaver 为类型创建序列化和反序列化函数。 Weaver 在Unity使用 Mono.Cecil 编译 dll 后编辑 dll。这允许Mirror具有许多复杂的功能,例如 SyncVar、ClientRpc 和消息序列化,而无需用户手动设置所有内容。
规则和提示
Weaver 可以做的事情有一些规则和限制。一些功能增加了复杂性并且难以维护,因此尚未实现。这些功能并非不可能实现,如果对它们有很高的需求,可以添加。
- 您应该能够为任何类型编写自定义读/写函数,并且 Weaver 将使用。
- 这意味着如果存在不支持的类型,例如 int[][],创建自定义读/写函数将允许您在 SyncVar/ClientRpc/etc 中同步 int[][]
- 如果您有一个类型的字段不该被序列化,您可以使用 [System.NonSerialized] 标记该字段,weaver 将忽略它
不支持的类型
如上所述,由于它们会增加复杂性,其中一些类型不受支持。
NOTE: 此列表中的类型可以具有自定义writers。
- 锯齿状和多维数组
- 从 UnityEngine.Component 继承的类型
- UnityEngine.Object
- UnityEngine.ScriptableObject
- 泛型类型,例如 MyData
- 自定义读/写必须声明 T,例如 MyData
- 接口
- 引用自身的类型
内置读写函数
Mirror 提供了一些内置的读/写功能。它们可以在 NetworkReaderExtensions 和 NetworkWriterExtensions 中找到。
这是具有内置功能的类型的非竞争列表,请查看上面的类以查看完整列表。
- 大多数 C# 原始类型
- 常见的 Unity 结构
- Vector3
- Quaternion
- Rect
- Ray
- Guid
- NetworkIdentity, GameObject, Transform
NetworkIdentity, GameObject, Transform
Object的netId通过网络发送,另一端返回具有相同netId的Object。如果 netId 为零或未找到对象,则将返回 null。
生成的读写函数
Weaver 将生成读写函数
- Classes or Structs
- Enums
- Arrays
- 例如 int[]
- ArraySegments
- 例如 ArraySegment
- Lists
- 例如 List
类和结构
Weaver 将读取/写入类型中的每个公共字段,除非该字段被标记为 [System.NonSerialized]。如果类或结构中有不受支持的类型,Weaver 将无法为其创建读/写函数。
注意:Weaver 不检查属性
枚举
Weaver 将使用枚举的底层类型来读取和写入它们。默认情况下,这是 int。
例如 Switch 将使用字节读/写函数进行序列化
public enum Switch : byte
{
Left,
Middle,
Right,
}
集合
Weaver 将为上面列出的集合生成写入。 Weaver 将使用元素的读/写功能。该元素必须具有读/写功能,因此必须是受支持的类型,或者具有自定义读/写功能。
例如:
- float[] 是受支持的类型,因为 Mirror 具有内置的浮点读/写函数。
- MyData[] 是受支持的类型,因为 Weaver 能够为 MyData 生成读/写函数
public struct MyData
{
public int someValue;
public float anotherValue;
}
添加自定义读写函数
读写函数是静态方法,形式如下:
public static void WriteMyType(this NetworkWriter writer, MyType value)
{
// write MyType data here
}
public static MyType ReadMyType(this NetworkReader reader)
{
// read MyType data here
}
最佳实践是制作读/写函数扩展方法,以便可以像 writer.WriteMyType(value) 一样调用它们。
将它们称为 ReadMyType 和 WriteMyType 是一个好主意,这样它们的类型就很明显了。不过函数名无所谓,weaver不管叫什么都应该能找到。
属性示例
Weaver 不会编写属性,但可以使用自定义编写器通过网络发送它们。
如果您想为您的属性设置私有集,这可能很有用
public struct MyData
{
public int someValue { get; private set; }
public float anotherValue { get; private set; }
public MyData(int someValue, float anotherValue)
{
this.someValue = someValue;
this.anotherValue = anotherValue;
}
}
public static class CustomReadWriteFunctions
{
public static void WriteMyType(this NetworkWriter writer, MyData value)
{
writer.WriteInt32(value.someValue);
writer.WriteSingle(value.anotherValue);
}
public static MyData ReadMyType(this NetworkReader reader)
{
return new MyData(reader.ReadInt32(), reader.ReadSingle());
}
}
不支持的类型示例
Rigidbody 是不受支持的类型,因为它继承自 Component。但是可以添加一个自定义writer,以便在附加的情况下使用 NetworkIdentity 进行同步。
public struct MyCollision
{
public Vector3 force;
public Rigidbody rigidbody;
}
public static class CustomReadWriteFunctions
{
public static void WriteMyCollision(this NetworkWriter writer, MyCollision value)
{
writer.WriteVector3(value.force);
NetworkIdentity networkIdentity = value.rigidbody.GetComponent<NetworkIdentity>();
writer.WriteNetworkIdentity(networkIdentity);
}
public static MyCollision ReadMyCollision(this NetworkReader reader)
{
Vector3 force = reader.ReadVector3();
NetworkIdentity networkIdentity = reader.ReadNetworkIdentity<NetworkIdentity>();
Rigidbody rigidBody = networkIdentity != null
? networkIdentity.GetComponent()
: null;
return new MyCollision
{
force = force,
rigidbody = rigidBody,
};
}
}
以上是 MyCollision 的函数,但您可以为 Rigidbody 添加函数,让 weaver 为 MyCollision 生成一个编写器。
public static class CustomReadWriteFunctions
{
public static void WriteRigidbody(this NetworkWriter writer, Rigidbody rigidbody)
{
NetworkIdentity networkIdentity = rigidbody.GetComponent<NetworkIdentity>();
writer.WriteNetworkIdentity(networkIdentity);
}
public static Rigidbody ReadRigidbody(this NetworkReader reader)
{
NetworkIdentity networkIdentity = reader.ReadNetworkIdentity();
Rigidbody rigidBody = networkIdentity != null
? networkIdentity.GetComponent<Rigidbody>()
: null;
return rigidBody;
}
}
调试
Weaver 修改后,您可以使用 ILSpy 和 dnSpy 等工具查看已编译的代码。这有助于理解和调试 Mirror 和 Weaver 的功能。