facebook twitter hatena line email

Unity/WebGL/js連携

提供: 初心者エンジニアの簡易メモ
2021年4月6日 (火) 17:46時点におけるAdmin (トーク | 投稿記録)による版

移動: 案内検索

サンプル

unity-2020.1.2f1のWebGLで動作確認

  • Assets/Plugins/jsconnect.jslib
mergeInto(LibraryManager.library, {
  Hello: function () {
    window.alert("Hello, world!");
  },
  AddNumbers: function (x, y) {
    return x + y;
  },
  PrintFloatArray: function (array, size) {
    for(var i = 0; i < size; i++)
      console.log(HEAPF32[(array >> 2) + i]);
  },
  HelloString: function (str) {
    window.alert(Pointer_stringify(str));
  },
  StringReturnValueFunction: function () {
    var returnStr = "bla";
    var bufferSize = lengthBytesUTF8(returnStr) + 1;
    var buffer = _malloc(bufferSize);
    stringToUTF8(returnStr, buffer, bufferSize);
    return buffer;
  },
  BindWebGLTexture: function (texture) {
    GLctx.bindTexture(GLctx.TEXTURE_2D, GL.textures[texture]);
  },
});
  • Assets/Scripts/JsConnect.cs
using UnityEngine;
using UnityEngine.UI;
using System.Runtime.InteropServices;

public class JsConnect : MonoBehaviour
{
    [DllImport("__Internal")]
    private static extern void Hello();

    [DllImport("__Internal")]
    private static extern void HelloString(string str);

    [DllImport("__Internal")]
    private static extern void PrintFloatArray(float[] array, int size);

    [DllImport("__Internal")]
    private static extern int AddNumbers(int x, int y);

    [DllImport("__Internal")]
    private static extern string StringReturnValueFunction();

    [DllImport("__Internal")]
    private static extern void BindWebGLTexture(int texture);

    void Start()
    {
        Hello();

        int result = AddNumbers(5, 7);
        Debug.Log(result);

        float[] myArray = new float[10];
        PrintFloatArray(myArray, myArray.Length);

        HelloString("This is a string.");

        Debug.Log(StringReturnValueFunction());

        var texture = new Texture2D(0, 0, TextureFormat.ARGB32, false);
        BindWebGLTexture(texture.GetNativeTextureID());
    }
    public Text label;
    public void SetText(string text)
    {
        label.text = text;
    }
}
  1. GameObjectを作成し、名前をJsConnectObjに変更
  2. JsConnectのクラスをJsConnectObjにAddComponentで追加
  3. WebGLでビルド時にHello()のエラーが出るが問題ない。
  • WebGLで出力したindex.htmlにSendMessage()を追加
<!DOCTYPE html>
<html lang="en-us">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>Unity WebGL Player | unsi</title>
    <link rel="shortcut icon" href="TemplateData/favicon.ico">
    <link rel="stylesheet" href="TemplateData/style.css">
  </head>
  <body>
    <div id="unity-container" class="unity-desktop">
      <canvas id="unity-canvas"></canvas>
      <div id="unity-loading-bar">
        <div id="unity-logo"></div>
        <div id="unity-progress-bar-empty">
          <div id="unity-progress-bar-full"></div>
        </div>
      </div>
      <div id="unity-footer">
        <div id="unity-webgl-logo"></div>
        <div id="unity-fullscreen-button"></div>
        <div id="unity-build-title">unsi</div>
      </div>
    </div>
    <script>
      var buildUrl = "Build";
      var loaderUrl = buildUrl + "/write.loader.js";
      var config = {
        dataUrl: buildUrl + "/write.data.br",
        frameworkUrl: buildUrl + "/write.framework.js.br",
        codeUrl: buildUrl + "/write.wasm.br",
        streamingAssetsUrl: "StreamingAssets",
        companyName: "DefaultCompany",
        productName: "unsi",
        productVersion: "1.0",
      };
      var container = document.querySelector("#unity-container");
      var canvas = document.querySelector("#unity-canvas");
      var loadingBar = document.querySelector("#unity-loading-bar");
      var progressBarFull = document.querySelector("#unity-progress-bar-full");
      var fullscreenButton = document.querySelector("#unity-fullscreen-button");

      if (/iPhone|iPad|iPod|Android/i.test(navigator.userAgent)) {
        container.className = "unity-mobile";
        config.devicePixelRatio = 1;
      } else {
        canvas.style.width = "626px";
        canvas.style.height = "500px";
      }
      loadingBar.style.display = "block";

      var script = document.createElement("script");
      script.src = loaderUrl;
      script.onload = () => {
        createUnityInstance(canvas, config, (progress) => {
          progressBarFull.style.width = 100 * progress + "%";
        }).then((unityInstance) => {
          loadingBar.style.display = "none";
          fullscreenButton.onclick = () => {
            unityInstance.SetFullscreen(1);
          };
          unityInstance.SendMessage('JsConnectObj', 'SetText', 'HelloJavascript!!!'); // add
        }).catch((message) => {
          alert(message);
        });
      };
      document.body.appendChild(script);
    </script>
  </body>
</html>

参考:https://note.com/npaka/n/nca1e35a649e3

unity2020以外のとき

上記ではunity2019-2017まで動作しなかった。(unity5未満は未確認) unityInstanceの直下では、unityが起動してないときに、実行されてしまうようで、ボタンなどからクリックすることで呼び出せた。

<script>
      var unityInstance = UnityLoader.instantiate("unityContainer", "Build/jstest.json", {onProgress: UnityProgress});
</script>
<input type="button" value="クリック" onclick="func1()">
<script>
    var func1 = function () {
unityInstance.SendMessage('JsTest', 'SetText', 'This is a text.');
     }
</script>

unity2020の時のwebglの表示ロード

以下の通りエラーが出る・・

Uncaught ReferenceError: unityFramework is not defined
   at HTMLScriptElement.r.onload (webgl_unsiread.loader.js:1)

ブラウザのconsole.logで"Uncaught TypeError: Cannot read property 'apply' of undefined"エラーが出るとき

Invoking error handler due to
Uncaught TypeError: Cannot read property 'apply' of undefined
20149427-27f7-4cca-ba13-66d3b3d96c55:8 Uncaught TypeError: Cannot read property 'apply' of undefined
    at 20149427-27f7-4cca-ba13-66d3b3d96c55:8
    at Object.ccall (20149427-27f7-4cca-ba13-66d3b3d96c55:8)
    at Object.SendMessage (20149427-27f7-4cca-ba13-66d3b3d96c55:8)
    at Object.SendMessage (UnityLoader.js:4)
    at func1 (645:127)
    at <anonymous>:1:1

起動前にjsが読み込まれてると思われる。

あとは、

ロード画面を用意して、jsをロードが完了したときに、sceneを移動するなどを、やったほうが良い。