The purpose of this article is to show how to package Unity projects as WebGL resources into React projects and communicate with them

Unity2020.3 is used in this paper

React-unity-webgl can be used to create a react-app. The react-unity-webgl can be used to create a react-app. The react-unity-webgl can be used to create a react-app.

Unity packages as WebGL

  1. From Unity’s main menu, select File -> Build Settings… Open the package popover 👇

Unity does not install plug-ins packaged as WebGL by default. You need to install plug-ins yourself in Unity Hub as prompted

  1. Click on the Player Settings in the lower left corner of the 👆 popup… In this step, the most important thing is to change the Compression Format in the Publishing Settings configuration to Disabled. For other configurations, refer to the documentation or use the default conditions

  1. Click the Build/Build And Run button in the lower right corner of the Build Settings popup. The difference is that the Build And Run button not only packages but also automatically starts a local server running the packaged WebGl project. Note that after you click “Package”, you need to select the folder to save the package project. It must be placed in the root directory of the project, that is, the same as the Assets folder.
  2. The index. HTML entry file and Build and TemplateData folders are packaged together. Index. HTML is useless for subsequent import.

Introduction of the React Project

The project using the create – react – app to create a single page of the react project, the official document: zh-hans.reactjs.org/docs/create…

React-unity-webgl: react-Unity-webGL: react-Unity-webGL: react-Unity-webGL: react-Unity-webGL: React-Unity-webGL: React-Unity-WebGL

Plug-in installation

$ npm install [email protected]  # For Unity 2020 and 2021 (Current)
Copy the code

Install using NPM, since the Unity version used for this project is 2020, 8.x will be required

Module introduction and display

  1. Place the packed Build and TemplateData files in the React project’s public folder

  1. Example code for using a resource in a component:
// App.js

import React from "react";
import Unity, { UnityContext } from "react-unity-webgl";

const unityContext = new UnityContext({
  loaderUrl: "Build/beidou3Dweb.loader.js".// public Directory
  dataUrl: "Build/beidou3Dweb.data".frameworkUrl: "Build/beidou3Dweb.framework.js".codeUrl: "Build/beidou3Dweb.wasm"});function App() {
  // Be sure to set width and height to the Unity component, otherwise the Canvas will grow infinitely and the browser will freeze
  return <Unity style={{'width': '100% ', 'height': '100% '}}unityContext={unityContext} />;
}

export default App;
Copy the code

The page displays a Canvas, which is the Game page for the Unity project.

React to Unity communication

Communication is achieved by calling the Send method of the UnityContext instance, which specifies the name of the GameObject that needs to be called in the Unity project and the name of the function bound to that GameObject that needs to be executed. You can also pass a number/string/Boolean parameter. Note that only one (or none) can be passed. After React triggers send, the corresponding function in Unity executes to complete a communication.

  • React code:
// React App.js

import React, { useState, useEffect }  from "react";
import Unity, { UnityContext } from "react-unity-webgl";
import { Button } from 'antd';
import './index.less';

const unityContext = new UnityContext({
  loaderUrl: "Build/beidou3Dweb.loader.js".dataUrl: "Build/beidou3Dweb.data".frameworkUrl: "Build/beidou3Dweb.framework.js".codeUrl: "Build/beidou3Dweb.wasm"});function App() {
  function spawnEnemies() {
    unityContext.send("ConnectObject"."SpawnEnemies"."Some Message"); // Call send
    // ConnectObject is the gameobject name (globally unique)
    // SpawnEnemies is the callback function name on ConnectObject
    // "Some Message" is the parameter to be passed, which is of type string

  return (
    <div className="container">
      <Unity style={{'width': '100% ', 'height': '100% '}}unityContext={unityContext} />
      <Button type="primary" onClick={spawnEnemies}>To Unity</Button>
    </div>
  );
}

export default App;
Copy the code
  • Code in Unity:
// The cummunicatetest. cs file in Unity is stored in the Script folder
// Bind to a Panel gameobject named ConnectObject

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class CummunicateTest : MonoBehaviour
{
    public Text text; // Bind to a Text under Panel

    public void SpawnEnemies (string amount) { // The method must be public
      text.text = amount; // Change the Text of the Text according to the passtext}}Copy the code

Unity to React communication

The communication is achieved by introducing and calling the functions in the.jslib file in Unity to trigger events and carry the parameters to be passed, and then on the UnityContext instance in React to listen for the event and execute callback functions to get the parameters to be passed.

Jslib files must be placed in Assets/Plugins/WebGL, if they do not exist by default, build them yourself!

How to create.jslib? If you use MAC, change the suffix. If you use Windows, you can add Google

  • Files in Unity
// MyPlugin.jslib

mergeInto(LibraryManager.library, {
  GameOver: function (userName, score) { ReactUnityWebGL.GameOver(Pointer_stringify(userName), score); }});Copy the code
// The cummunicatetest. cs file in Unity is stored in the Script folder
// Bind to a Panel gameobject named ConnectObject

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System.Runtime.InteropServices;


public class CummunicateTest : MonoBehaviour
{
    public Button btn;
    public Text text;

    [DllImport("__Internal")] // Introduce and declare the GameOver function defined in.jslib
    private static extern void GameOver(string userName, int score);

    // Start is called before the first frame update
    void Start()
    {
        btn.onClick.AddListener(() => { // Call GameOver when the button is clicked
            GameOver("xinghui".100);
        });
    }

    public void SpawnEnemies (string amount){ text.text = amount; }}Copy the code
  • Files in React
import React, { useState, useEffect }  from "react";
import Unity, { UnityContext } from "react-unity-webgl";
import { Button } from 'antd';
import './index.less';
import fullScreenIconImage from '.. /.. /images/threeShow/fullScreenIcon.png';

const unityContext = new UnityContext({
  loaderUrl: "Build/beidou3Dweb.loader.js".dataUrl: "Build/beidou3Dweb.data".frameworkUrl: "Build/beidou3Dweb.framework.js".codeUrl: "Build/beidou3Dweb.wasm"});function App() {
  const [isGameOver, setIsGameOver] = useState(false);
  const [userName, setUserName] = useState("");
  const [score, setScore] = useState(0);

  useEffect(function () {
    unityContext.on("GameOver".function (userName, score) { // Listen for the GameOver event
      setIsGameOver(true); setUserName(userName); setScore(score); }); } []);function spawnEnemies() {
    unityContext.send("ConnectObject"."SpawnEnemies"."Some Message");
  }

  function setUnityFullScreen() {
    unityContext.setFullscreen(true); // Set Unity's Canvas to full screen display
  }

  return (
    <div className="three-show-container">
      <img className="full-screen-icon" src={fullScreenIconImage} alt="Full screen" onClick={setUnityFullScreen} />
      <Unity style={{'width': '100% ', 'height': '100% '}}unityContext={unityContext} />
      {isGameOver === true && <p>{`From Unity ${userName} ${score}`}</p>}
      <Button type="primary" onClick={spawnEnemies}>To Unity</Button>
    </div>
  );
}

export default App;
Copy the code

When you click the React button, the text in Unity changes to “Some Message”. Click the button in Unity. React displays “From Unity Xinghui 100”. Two-way communication is implemented.

For other plug-in functions, see the official documentation github.com/jeffreylant… To try.