Protobuf Contracts for Multiple Language Consumers

Aaron Chapin
2 min readApr 19, 2023

--

Some of our game services are written in GoLang. Our game servers and game client are Unity/C# based, and use the same repo. The services, and their consumers communicate via gRPC connections, using protobuf contracts. This is how we make that work!

We decided early on that the protobuf repo should contain all of the contracts for all of the services, so that we wouldn’t need to have separate repos for each service’s contracts.

On the C# side, we can’t use the .proto files directly, we need to have them compiled out to usable C# code. To do that, we have a script in the proto repo which compiles the proto files to their C# implementations. That script is fairly simple:

It requires that you have the protobuf compiler and grpc_csharp_plugin installed, of course.

Github Action which runs whenever a push to the proto repo is made. It compiles the proto contracts into C# code, and then commits that change to a matching branch in a different repo. This repo only holds the compiled C# code.

Two git repos are being checked out at the same time: the source proto repo, but then also the destination C# repo. We run all the proto files through the compilation script, and the destination of the generated C# code just so happens to be inside the destination repo folder. That code is then committed and pushed to a branch named after the current branch in the proto repo. This way master is kept up to date once merges are completed, but developers can also test feature branches using contract changes which are still in development.

With this development, on the Unity side of things, we can add the URL of the generated repository to our packages manifest, and import the generated code that way instead of having to update it manually.

The rest of our packages have been purposely obfuscated

Experienced Unity devs might note that the C# code alone is not enough to properly load code into a Unity project. In addition, the package must have a package definition and included .meta files. The package file was already placed in the proto repo, ready to copy over. The meta files are handled by another script:

This step is also executed in the github action which pushes the changes to the generated code repo, to make sure that all of the new C# files can be utilized properly by that engine.

--

--