Skip to content

t1k:unity:dots-core:google-protobuf

FieldValue
Moduledots-core
Version2.3.2
Efforthigh
Tools

Keywords: networking, protobuf, protocol buffers, serialization

/t1k:unity:dots-core:google-protobuf

Two C# approaches: Google.Protobuf (official, .proto files + protoc) and protobuf-net (attribute-based, no toolchain).

Related skills: memorypack (faster for C#-only, no cross-language) · zstring (zero-alloc string formatting) · dots-ecs (ECS patterns)


  • Using [ProtoContract], [ProtoMember] attributes (protobuf-net)
  • Using Google.Protobuf, MessageParser, .proto files
  • Cross-language serialization (C# ↔ TypeScript/Go/Python)
  • Network RPC/command serialization requiring schema contracts
  • Comparing Protobuf vs MemoryPack vs MessagePack vs JSON

Section titled “Option A: protobuf-net (Recommended for Unity)”

Why: No .proto files, no protoc toolchain, C# attributes only, Stream-based API.

Terminal window
# Via NuGetForUnity (recommended)
Window NuGet Search "protobuf-net" Install

Package: protobuf-net (full) or protobuf-net.Core (AOT-only, no reflection — better for IL2CPP).

using ProtoBuf;
using System.IO;
[ProtoContract]
public class GameSave
{
[ProtoMember(1)] public int Level { get; set; }
[ProtoMember(2)] public string PlayerName { get; set; }
[ProtoMember(3)] public float PlayTime { get; set; }
[ProtoMember(4)] public List<ItemData> Inventory { get; set; }
}
// Serialize
using var stream = File.Create("save.bin");
Serializer.Serialize(stream, data);
// Deserialize
using var stream = File.OpenRead("save.bin");
var loaded = Serializer.Deserialize<GameSave>(stream);
  • [ProtoMember(N)] — N must be unique positive integer per type
  • Never reuse or change member numbers after release (breaks compatibility)
  • Add new fields with new numbers — old data ignores unknown fields
  • Use [ProtoContract(SkipConstructor = true)] for types without parameterless ctor

Why: Cross-language (C# ↔ Go/Python/TS), .proto schema contracts, gRPC support.

Terminal window
# NuGet packages: Google.Protobuf + Google.Protobuf.Tools (contains protoc)
protoc --csharp_out=Assets/Generated/ --proto_path=Proto/ Proto/game.proto
syntax = "proto3";
message UnitState {
int32 entity_id = 1;
float health = 2;
float pos_x = 3;
float pos_z = 4;
}
byte[] bytes = unit.ToByteArray();
var loaded = UnitState.Parser.ParseFrom(bytes);

→ See decision-matrix-guide.md for full comparison table and DOTS integration pattern.

Quick rule: MemoryPack for C#-only speed, Protobuf for cross-language or bandwidth constraints.


→ See gotchas-guide.md for full details with code fixes.

  1. IL2CPP code stripping — Add link.xml to preserve protobuf types.
  2. protobuf-net reflection mode fails on IL2CPP — Use protobuf-net.Core or source generator.
  3. Proto field number reuse — Breaks backward compat silently. Never reuse/change numbers.
  4. Default values not serialized — Proto3: 0, "", false are not written to wire.
  5. DateTime/TimeSpan — Not natively supported. Use Timestamp/Duration or long ticks.

FileContents
gotchas-guide.mdIL2CPP stripping, reflection, field numbers, default values, DateTime, thread safety
decision-matrix-guide.mdProtobuf vs MemoryPack comparison, DOTS integration pattern, batch serialization