Running Unity WebGL Inside a React App
In this tutorial, I walk you through running a Unity game (built with WebGL) inside a React app. This will allow you run a browser game and surround it with React.
At the start of 2021, I wanted to very much this. I want to build a game in Unity but have all additional screens (settings, help screens, setup screens) all built using React. I want the game to work on most web browser. I believe internet speeds are getting faster, and most computers are moving to browser being the platform.
I found this library called unity-react-webgl. It is very well maintain and works. Please star it if you use it. This will help the creator know it's value (At least one of the ways).
In this tutorial we will follow a few steps:
- Setup a new Unity Game
- Build the Unity Game via command line
- Setup the React app
- Trigger functions in Unity from the React app
- Trigger functions in React from the Unity game
I will try to keep this up to date but if things change let me know. I'm using Unity
2019.4.17f1. I'm going to do this project on a Mac OSx computer.
Setup a New Unity Game
Let's start by opening up Unity and building a basic game. It doesn't have to do anything, other than render a plane. I'm going to create a new game.
I'm using no spaces in my name or file path because it often just causes issues.
Add a plane object to provide our scene with a focal point.
In the inspector on the right, adjust some of the values. Take a look at my position
0, 0, 0.
On the left side under the scene name, select
Main Camera. In the inspector on the left, set the position to be
0, 0, -7. Set the rotation to be
20, 0, 0.
We should be all setup now. Let's make sure this runs inside of Unity. Hit the play button in the centre at the top.
We are going to add a new C# file called
Assets/Editor/WebGLBuilder.cs. Your bottom folder structure starts in
Assets. You may need to create
Editor. You just need to right click to add a new
Now that the file is created, open it in an editor. I've configured my Unity app to default to VSCode.
Put this code in the script:
Don't know what your scenes are? You can go back in your
Assets folder and click on the scene. It will show you the path.
It is an array of scenes, you can add multiple. Everything you want to be included in the build. For me, I have just the one. Save that file. Save your scene. Let's run it. This is the slightly annoying part, you can't run two instances of Unity at the same time. To compile it, you will be running it without a UI and in the background. This will stop you from keeping your editor open.
You will have to find the path to your Unity app on your local machine. For me, mine is:
My folder structure is as follows:
I'm running this command from inside
unity-bash-demo. You will have to update
$pwd/DemoGame/ to be your game folder. You will also have to update the additional arguments if you are not using WebGL. With Unity closed, I run:
I'm currently mid-development on another game and this takes me about 5 minutes to run. Building the game is not the fast command, so please be patient. If you want to see what is going on in the build process, in another terminal window you can run:
This will let you watch the logs file. Just do
CTRL + C to exit it.
You should now see a
builds folder in the your game folder. For me:
You will see the output of the build and a runnable WebGL game.
Setup React app
We have the game setup, now it's time to set up the React app.
Create React App
We will use the Create React app as a starting point. I'm going to create it using
For me, I'm running:
Once it's done installing, I'm going to switch into the directory and run it.
I'm going to add React Router because I want a multi-page app. I'm going to have a home page, and a page with the game on it. I need to install React Router with:
I'm going to reorganize the files. It will be in this structure:
The contents of
We are setting up two routes:
App wraps the whole application. The
App.js file is:
Let's test this all out. Run
npm run start. Open http://localhost:3000. You should see:
Then go to http://localhost:3000/game/ and you should see:
Setup Unity WebGL
With our game now running, it's time to setup React Unity WebGL library. Once again, show your support to the creator if you use it.
I am using a Unity version that starts with
2019. You can find this information in your Unity Hub.
Following the installation instructions on the README, install the corresponding version:
For me, its:
Once it's complete, we are going to move our build files from the game directory (Probably under Assets) into
public/ on the React project. I created a folder called
Copy all of the files, and do not rename any of them. I did this and it stopped it from working. The config file (For me,
WebGLversion.json) is referencing the other file names. It's just easier if you do not rename it.
Your Unity WebGL build files are now in the project. The README example from the repository wasn't perfect. I found I had to do some digging around Github for other examples. If it doesn't work for you, let me know.
We are going to update our
I've included all of the default React Unity WebGL library lifecycle methods (
loaded, etc.). The
DemoUnityToReact is method that we will create in Unity and trigger that method on the React side. If you run this, you should see:
If you open your console, you can see the lifecycle methods get trigger.
You can add your own loading screens and such.
Debug.Log will appear in the console which is very nice for debugging.
Communicating Between Unity & React
Let's setup some communication between Unity and React. I have used this to share player information or pass game specific information (Ex. Game id of the game they just joined).
Unity to React
We want to trigger a React function from Unity. We have already declared
DemoUnityToReact in our
unityContent.on("DemoUnityToReact". This is is method we will be triggering.
We will need to add a plugin. Open your game and in
Assets/Plugins/WebGL/MyPlugin.jslib. You probably will not have this file path or this file, create both. Unity didn't let me create a non-C# file, so I did. I just removed the extension of
Here are the contents:
The name needs to match the event listener. For me, it is
Pointer_stringify? The managed string gets modified as it gets compiled. If we didn't have this, we would receive an integer on the other side. I'm not the best person to be explaining this but I've linked out to the Unity Forums.
Why one argument? This was an interesting catch. I just assumed more arguments would work but they don't. You can see in the source of UnityContext model that it takes 0 or 1 arguments. If you want to pass more than one argument or an argument that is not a string, boolean or integer, you should JSON stringify it. This is why I call the variable
busStr. It's just acting as a shuttle bus. It isn't anything but the whole object of parameters.
The last step is actually triggering this method. I'm going to trigger this method when left click is used. The script will be in C# and attached to the main camera. Select your
Main Camera, scroll to the bottom of the insepctor, hit
Add Component, do a search for
New Script, and give it a name.
The new script will be in the root of the project. I'm going to create a
Scripts/ folder and move it in there.
We will need a second script. This will not be a Unity specific but more a class to stringify and send to React. It will be called
SendMessage.cs and should be in the scripts folder. It will NOT be attached to the
Main Camera or any other component.
The cotents of
We are passing through two fields:
secondField. The class needs to be serializable (for stringify). I don't believe you need to install anything but this isn't my first time using this package. If you have package issues, let me know and I can update the lesson.
We handle capture the input of the mouse in the update. We call left click, and if they are using the game within a React app then we pass the message through. This makes testing harder. We need to compile to a WebGL build, move the files into our React project and run it.
Let's test this out. I recommend checking your Unity editor for any syntax errors. It will say at the bottom. I have the one warning:
Save the scene and close unity.
We are going to write a build script that builds the Unity game and moves into the React folder. Reminder my folder structure is a mono-repo that looks like:
I'm going to add another folder called scripts to the root. Now it will be:
scripts, I'm going to add
build.sh. The script will be:
You will need to update the paths, Unity build path, and some of the naming. I added timestamps since the build can take 5 to 10 minutes. If you are having issues, run each step one at a time. Run this with:
Open http://localhost:3000/game/, and you should see the game render. If you left click after the game loads, you should see the Debug log and a print out of the parameters (
SendMessage instance) coming from Unity.
Just like that you are sending information from Unity to React. On the React side, you would
JSON.parse(params) and it would give you the object that you sent through.
React to Unity
Next, we are going to communicate React to Unity. We will add a button to the top of the page and when it is clicked, a method in Unity will print a Debug.Log.
I'm going to rename the camera from
Main Camera to
Add a new script. This will be used to catch the new input. It doesn't need to be in a new script, but this is how I'm handling it.
I'm going to move this new script into my
scripts/ folder. The contents of
In the React app,
src/containers/Game/InGame.js, and add (to the
For a brief explanation:
Close the your Unity editor and run the build script:
Now, open the game at http://localhost:3000/game/. Press the
If you open the console log, you should see the Debug log from the Unity method.
That's it for now! You now have a Unity Game running inside your React.js app.
Thanks for reading!