Skip to main content
GameDev.net gamedev.net

PRO Tired of ads? Read GameDev.net ad-free and help keep the community independent with GameDev Pro — $3/month.

Serverless Unity Game Hosting

Serverless Unity Game Hosting

Tom Larkworthy
Corepox · · 4 min read
2,178 0

You can run Unity in a serverless function, with graphics, in less than 70 lines of code! Full demo code is on github.
But why? Serverless is a new cloud trend, you place a snippet of application code in the cloud, and let the cloud providers spin up resources to execute them per execution. It completely eliminates idle serves saving money when you have low traffic, its stateless, its simple to use and it scales massively when you have high traffic bursts, yet scales to zero (i.e. free) when you have no traffic!
It sounds awesome (and it is), but there are some drawbacks, you need your application code to run in docker (implying linux). For corepox, I want to be able to render game replays which requires running the Unity binary. Despite the linux build options, I was unable to coax headless rendering into working on systems without GPUs. You can get GPUs with VMs, but gets real expensive fast (>$600 a month). Plus, I don’t want to manage a VM anyway, its a headache. I want serverless! But how to get rendering to work?
Here is the solution. 1. Chrome now ships with a WebGL software rendered called swift shader. 2, Unity can compile to a wasm WebGL application. 3, You can run headless Chrome within a function. So, putting it all together, you run Chrome in a function, which pulls your Unity WebGL build and runs it. At this point you have your game running in a function!
Its dynamic too, you can pass in arguments to your game binary via the URL query string, and you can read messages from the running game via console instrumentation! I use the latter to trigger when a screenshot is taken. Chrome can take a screenshot of a DOM element, and pass the image data to the function, then the function can return that to the requester as an image/png.

serverless_rendering.png

A http function becomes an ordinary web image link, whose content is dynamically generated by a unity binary that can read the URL query string.
Its a wobbly tower of technology, but the code required is trivial. I have a complete demo of a screenshot service on github. Its 70 lines of custom code (mostly URL parsing, :s)! I’ve included the full WebGL build too so you can test the idea on your own infrastructure without compiling anything. Here is the custom code:
The Unity scriptThe snapshotter.cs is a custom behavior inserted into the starting Unity scene. It reads the URL, to alter the color of a text component. It waits for a frame to render before emitting a special log message. Very trivial.

You then generate a WebGL binary, then upload it to a storage bucket to serve. You can do this in one action at console.cloud.google.com/storage/browser by using the upload folder option.

9410cd_3c1d2095f5ce44d98889eb69b7a5e194m

You do not need this to be world readable as functions can be given storage access. However, I uploaded the demo as world readable so you can see the binary in the flesh in your browser yourself now. Try changing the r, g, b params in the URL: https://storage.googleapis.com/public_website/examples/unity-serverless/build/index.html?r=0.5&g=0&b=0.4This is the link the Cloud Function will see in its own instance of Chrome. You can see the Unity log output in the DevTools console.
The Google Cloud FunctionThe GCF function copies its own URL params to a url passes to a Chrome instance. We then wait until we see the special console message and take a snapshot focused on the div hosting the game. That snapshot data is returned with an image content type.

To deploy the function you run:
gcloud beta functions deploy screenshot_example –trigger-http –runtime nodejs8 –memory 2048MB
We max the memory as that also maxes the CPU power too. Once its deployed you can visit the URL in your browser and get a simple an image back! (note its dog slow, like 30 seconds)
https://us-central1-corepox-staging.cloudfunctions.net/screenshot_example?r=0.1&g=0.9&g=0.3
Voila! Its works! That image was generated by dynamically running Unity, serverlessly, using Swift Shader to avoid a hardware GPU dependency!!!

Gotchas Unity throws OpenGL errors if anti-aliasing is on and fails to render. Switch it off in the Quality settings!

9410cd_b59018ec84e74cbb81c83ec7a5cdbcd7m

I am pretty sure the same idea would work in an AWS Lambda too.


Read the full article at corepox.net

Discussion

Loading comments...