Basic Client-Server Communication using Unity & gRPC

Shadab Ambat
7 min readDec 2, 2019

Overview

gRPC has a lot benefits including native support for HTTP/2 which in turn allows for multiplexed bidirectional streams. However it does come with the cost of some complexity and it’s still not as mature as say REST. So there are still several scenarios where REST might be the better choice.

For areas such as gaming however, where latency can be really critical, gRPC can really shine through so it‘s definitely worth taking a look!

This article was written as part of Akatsuki’s 2019 Advent Calendar

What we’ll do

In this post we’ll create a simple bi-directional communication channel between a Unity client (C#) and a gRPC server (Golang).

  • We’ll have a single scene in Unity that renders a 3D object on a basic plane
  • The client will request a random color from the server and will use the result to change the 3D object’s color

In order to keep things simple we won’t be covering gRPC streams in this post but will do so in the near future so stay tuned!

Prerequisites

Before we start here are some prerequisites for this post

Knowledge

  • Basic knowledge of Unity or another game engine would be helpful
  • Basic to Intermediate programming experience (C# and/or Go would be nice but not mandatory)
  • Basic understanding of gRPC (this should be good enough)
  • Familiarity with command-line tools
  • An open mind :)

Tools

  • Unity 2019.3.x or later (I’m using 2019.3.0f1)
  • Go 1.13.x or later (I’m using 1.13.4)
  • Your favourite IDE(s) or a Text Editor

Also a few things to note

  • gRPC for Unity is still experimental so it might not be suitable to deploy it for production (yet)
  • I’ll be using OSX (Mac) for this post so while the commands might be slightly different for Windows users it should be similar enough to follow along

With that out of the way let’s start! :)

Basic Unity Setup

We’re going to first create a basic plane with a cube and a UI button that will be the trigger to change the cube color. If you’re quite familiar with Unity you can skip to where we start writing the script for the button

Let’s create a basic Unity client first

  • Create a new 3D project in Unity which should come with a default SampleScene that includes a Main Camera and a Directional Light
  • Rename the default SampleScene to Main from the Project Hierarchy
  • Under the scene add a 3D Plane (from the GameObject menu). It might be a good idea to reset the Position and Rotation to 0 in the Transform section and set the Scale to 1 on all axes. Also set the color of the Plane to white (in case it’s a different color). This is just so our colored object will be easier to see with the white contrast
  • Also set the Main Camera (X, Y, Z) Position to (0, 1, -5) so we can see the center of the plane as seen in the Camera Preview section
  • Next add a 3D Cube GameObject to the Scene from the Hierarchy. As before reset the Transforms and set the (X, Y, Z) Position to (0, 0.5, 0)
  • Also create a new material CubeMat for the Cube and apply it as the new Cube Material (under Mesh Renderer)
  • At this point you should have something like this

Next let’s add a UI Button

We’ll use this later to request a random color from the gRPC server and assign it to the Cube

  • From the Hierarchy create a new Button —> TextMeshPro UI element. The reason we want to choose this instead of a regular Button is that Unity’s default Text component has scaling issues and doesn’t render properly for different resolutions. You can read more about it here. TextMesh Pro is now free and integrated by default in Unity! So I’d recommended to use it whenever possible
  • If you see a dialog box about Import TMP Essentials just go ahead and click it
  • Set the button anchors to top-centre and the (Width, Height) to (200, 50). Also under the Button element set the Text (TMP) anchors to stretch and change the text to Randomize! You can also play around with the size so it’s fits the button (a size of 25 seems to work)

Phew… finally we can start writing code!

  • Create a new Scripts directory under Assets and create an Empty GameObject and add a new C# script called ColorRandomizer.cs to it
  • The script will need a reference to the Material that we created earlier and a public method for changing the color that we’ll link with the Randomize Button’s OnClick handler
  • Add the code below to the ColorRandomizer.cs you just created above
  • In the code above you’ll notice that all we’re doing in GetColor() outputting a message to Debug.Log() and setting the colour to Red. Don’t worry we’ll add the call to the server later
  • Now save ColorRandomizer.cs and you should see a field in the Inspector to add the Material. Let’s add the CubeMat to that field
  • At this point let’s test! Click Play on the Game tab and click the Randomize button to make sure the color changes
  • Next let’s create the server

Create the server

Proto File Definition

In order to create the server we first need to create the gRPC Service Definition Proto file

This is basically an interface defining the messages and services we’ll be using for our project

In our case the client & server need to communicate on a single message

When the player clicks the button on the client we want to send the current object color to the server and get a random color as a response

So let’s see what the proto file for this would look like

Save the proto file as say color.proto in your home directory and let’s generate the server code

Protobuf and gRPC

  • First let’s install protobuf using brew for OSX (Windows users should be able to grab a release here)
brew install protobuf
  • Then let’s install gRPC
go get -u google.golang.org/grpc
  • And finally the protoc generators for Go
go get -u github.com/golang/protobuf/protoc-gen-go
  • To keep things tidy lets first create the necessary directories. Assuming your proto file is at ~/color.proto let’s move that over as well
mkdir -p ~/unity-grpc-colorgen/grpc/{client,server}mv ~/color.proto ~/unity-grpc-colorgen/grpc/
  • Now we let’s start generating!
cd ~/unity-grpc-colorgenprotoc -I grpc/ --go_out=plugins=grpc:grpc/server color.proto
  • This should create a color.pb.go file under ~/unity-grpc-colorgen/grpc/server which contains all the code we need to use protobuf in our project
  • Let’s copy this file and use it to create a new Go project
  • Create a main.go file in there which will contain the main connection logic for the server
  • Once that is done lets start the server!

Update the Client to use gRPC

  • Now lets generate the client side files from the color.proto file
cd ~/unity-grpc-colorgenprotoc -I grpc/ --csharp_out=grpc/client --grpc_out=grpc/client --plugin=protoc-gen-grpc=/usr/local/bin/grpc_csharp_plugin color.proto

Note: If you’re using Windows and having problems compiling at this point please check this comment

  • This should create 2 files — Color.cs and ColorGrpc.cs file under ~/unity-grpc-colorgen/grpc/client
  • Copy both files to the Unity Assets/Scripts directory
  • Now let’s use the client gRPC files and update our client side scripts!
  • First create a ColorClient.cs file in the Unity Assets/Scripts directory and add the code below
  • Let’s also update the ColorRandomizer.cs script (below)
  • The ColorClient.cs script is responsible for the gRPC logic while ColorRandomizer.cs manages the Color payload translation

Finally it’s time to try it out!

  • Start the gRPC server from your Go project dir
go run main.go
  • Run your client on Unity and hit that Randomize button!
  • The server logs also show messages coming from the client

Yay it works!!! :)

Summary

We established a basic gRPC bidirectional communication between a Go server and a Unity client

The entire source used for this project can be found here.

Thanks for reading along! See you again for the next adventure :)

--

--