Unity Netcode自定义数据传输——结构体及其序列化
在 Unity Netcode 中,要实现自定义数据的网络传输,确实需要两个关键部分:
✅ 两个必需组件:
-
数据结构定义
public struct PlayerState : INetworkSerializable {public int id; // 字段1:玩家IDpublic bool isReady; // 字段2:准备状态// ...其他字段 }
- 作用:定义要传输的数据内容
- 本质:声明"要传输什么"
-
序列化方法实现
public void NetworkSerialize<T>(BufferSerializer<T> serializer) {serializer.SerializeValue(ref id); // 处理字段1serializer.SerializeValue(ref isReady); // 处理字段2// ...处理其他字段 }
- 作用:控制数据如何打包/解包
- 本质:定义"如何传输"
类比解释(快递包裹)
网络传输 | 快递包裹类比 |
---|---|
数据结构 | 要寄送的物品 |
NetworkSerialize 方法 | 打包/拆包的操作说明书 |
网络管道 | 快递运输通道 |
接收方 | 收件人 |
-
发送方:
- 按照说明书(
NetworkSerialize
)打包物品(数据) - 通过快递(网络)寄出
- 按照说明书(
-
接收方:
- 收到包裹
- 按照相同的说明书(
NetworkSerialize
)拆包 - 获得完全相同的物品(数据)
为什么必须两者结合?
-
没有数据结构 → 不知道传输什么内容
// 无效:不知道传输什么 public void NetworkSerialize<T>(...) {// 没有字段可序列化 }
-
没有序列化方法 → 不知道如何传输
// 编译错误:未实现接口 public struct PlayerState : INetworkSerializable {public int id;// 缺少NetworkSerialize方法 }
完整工作流程
特殊注意事项
-
字段顺序必须严格一致
发送端和接收端的序列化顺序必须完全相同:// ✅ 正确顺序 serializer.SerializeValue(ref id); serializer.SerializeValue(ref isReady);// ❌ 危险!顺序不一致会导致数据错乱 serializer.SerializeValue(ref isReady); serializer.SerializeValue(ref id);
-
新增字段的版本处理
如果后续增加字段,需要处理兼容性:public string name; // 新增字段public void NetworkSerialize<T>(...) {serializer.SerializeValue(ref id);serializer.SerializeValue(ref isReady);// V2新增字段if (serializer.IsReader) {// 处理旧版本数据缺失的情况name = "默认名称";}serializer.SerializeValue(ref name); }
-
值类型 vs 引用类型
- 结构体(值类型):直接使用 ✅
- 类(引用类型):需要特殊处理 ❗
public class Weapon // 引用类型 {public int damage; }// 在序列化方法中需要: if (serializer.IsWriter) {serializer.SerializeValue(ref weapon.damage); } else {weapon = new Weapon();serializer.SerializeValue(ref weapon.damage); }
最终总结
组件 | 必须存在 | 作用 |
---|---|---|
数据结构定义 | ✅ | 声明要传输的数据内容 |
NetworkSerialize 方法 | ✅ | 定义数据如何打包/解包 |
: INetworkSerializable 接口 | ✅ | 标记该类型支持网络序列化 |
三者缺一不可,共同实现 Unity Netcode 的自定义数据网络传输能力。