🐇 Boilerplate for Unity3D WebGL builds (on WebAssembly) using basic Create React App
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? :cake: :wine_glass:
Your package.json
should look something like this (no babel, no webpack config :see_no_evil:):
{
"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:
Gamma
to Linear
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 using Gamma
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} />;
}
}
$ yarn start
command in your console. Uploading to Heroku is just as easy usingWith 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
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
);
⚠️ This may only be a (single!) number or a string
this.props.unityContent.send("PlayArea", "SpawnCube", 10);
⚠️ You cannot directly use template literals when passing a string. Write it first to a variable, then pass it instead.
let mouseCoords = `${this.state.pageX} ${this.state.pageY}`;
if (this.state.isLoaded === true) {
this.unityContent.send(
"TextDisplayer",
"UpdateDoubleMousePosition",
mouseCoords
);
}
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 ⚠️ about template literals we passed two numeric coords inside 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:
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! 🐇