𦧠please note i haven't been using neither react nor react-unity-webgl in a while so this thing is definitely heavily outdated, good luck!
TLDR; see result here π
- Example project / tutorial for hosting Unity3D WebGL build as a static webpage on Heroku (using create-react-app).
- Using a super cool repo react-unity-webgl by @El Raccoone
- Targetted especially for unity3d people who haven't hosted a webapp before.
- How to run
- Initial project setup
- Build Unity project for WebGL
- Integrate Unity build into your react webapp
- Two-way communication
You will need to have yarn installed on your pc
$ git clone https://github.com/mariaheine/unity3d-react-boilerplate.git
$ yarn install
$ yarn start
This will let you locally run example project.
π Follow the Quick Start on this repo: Heroku Buildpack for create-react-app With just a few easy steps you end with a static, frontend-only web site hosted on Heroku.
To update the site by pushing changes to heroku remote:
$ git commit -m "wow :o"
$ yarn build
$ git push heroku master
To open it:
`$ heroku open`
Wait what?? And just like that I have hosted a webpage? π° π·
Your package.json
should look something like this (no babel, no webpack config π):
{
"name": "unity3d-react-boilerplate",
"version": "0.1.0",
"private": true,
"dependencies": {
"react": "^16.4.1",
"react-dom": "^16.4.1",
"react-scripts": "1.1.4"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
}
}
π Unity documentation concerning WebGL development
π§ Your build settings should look something like on the picture below, please pay special attention to:
- Setting build platform for WebGL
- File -> Build Settings -> Platfrom -> WebGL
- ColorSpace
- Changing it from
Gamma
toLinear
will force you to use WebGL 2.0 which will unfortunately break compatibility with Safari browsers (as of 16/08/2020 for Safari 12.1), so you should probably keep usingGamma
- Changing it from
- π Once building is finished, you should be most interested with a directory containing those files:
-
Add react-unity-webgl into your project, it's just so cool.
-
Copy entire Unity build folder (mentioned above) into your
public
webapp folder. -
Replace your
App.js
with quick start code from react-unity-webgl
In case of this example project it would be just:
import React from "react";
import Unity, { UnityContent } from "react-unity-webgl";
export class App extends React.Component {
constructor(props) {
super(props);
this.unityContent = new UnityContent(
"CookieEater/Build/CookieEater.json.json",
"CookieEater/Build/UnityLoader.js"
);
}
render() {
return <Unity unityContent={this.unityContent} />;
}
}
- πΌ After these easy steps you should be ready to test your Unity webapp by simply running
$ yarn start
command in your console. Uploading to Heroku is just as easy using
With barely 5 lines of code your Unity build is imported and served in your React app. Isn't that cool? :o
For more info about <UnityContent/>
component check out Mr. Lanters' github wiki
- π± Calling Unity method with no parameters
You can now evoke any public method in your Unity project by sending a message to unityContent
specifying:
a. A GameObject name
that has a MonoBehaviour
attached
b. A name
of a public method
within one of the attached MonoBehaviours
this.unityContent.send(
"FlyCube", // GameObject name
"Randomize" // Public method name
);
- πΏ Calling Unity method with a single parameter
this.props.unityContent.send("PlayArea", "SpawnCube", 10);
let mouseCoords = `${this.state.pageX} ${this.state.pageY}`;
if (this.state.isLoaded === true) {
this.unityContent.send(
"TextDisplayer",
"UpdateDoubleMousePosition",
mouseCoords
);
}
- π΄ Calling a method with more than one parameter - possible workaround.
As mentioned above GameObject.SendMessage(), here as this.unityContent.send(...)
, may only pass as value one argument that can be either a number or a string.
One possible workaround is passing multiple values in a string and then parsing it inside Unity method.
In above mouseCoords
string variable to a method UpdateDoubleMousePosition
inside TextDisplayer
GameObject. To interpret that string as two separate numbers in C#:
public void UpdateDoubleMousePosition(string mouseCoords)
{
string[] coords = mouseCoords.Split(' ');
int[] coordsNumerical = new int[2];
for(int i = 0; i < coords.Length; i++)
{
coordsNumerical[i] = Int32.Parse(coords[i]);
}
TextY.text = coords[0];
TextX.text = coords[1];
}
3 steps for every single call:
- pre: creating .jslib plugin
- Creating javascript event handler
- Adding the method binding to the .jslib script
- Importing and using the method binding in a unity c# script
Create a text file in Plugins
folder in your Unity project (the folder has to be named this way) and rename it to howeveryouwant.jslib
,
The empty base of that script should look like this:
|
An example of Score.js
from example project:
props.unityContent.on("CookieEatenEvent", () => {
this.setState((prevState) => ({
cookiesEaten: prevState.cookiesEaten + 1,
}));
});
mergeInto(LibraryManager.library, {
CookieEatenEvent: function() {
ReactUnityWebGL.CookieEatenEvent();
}
});
From example project:
Read more about Native plugins
public class CookieEaten : MonoBehaviour {
[DllImport("__Internal")]
private static extern void CookieEatenEvent();
void OnTriggerEnter(Collider col)
{
// -------------
#if !UNITY_EDITOR && UNITY_WEBGL
CookieEatenEvent();
#endif
Destroy(gameObject);
// -------------
}
}
Thats all, have fun! π