Version: 2021.3
Memory in WebGL
WebGL performance considerations

Interaction with browser scripting

Web 用のコンテンツを構築するときは、Web ページ上の他の要素とやり取りする必要があります。また、Web API を使用して Unity が現在デフォルトで公開していない機能を実装したい場合もあるかもしれません。 いずれの場合も、ブラウザーの JavaScript エンジンと直接やり取りする必要があります。Unity WebGL はこれを行うためのさまざまな方法を提供します。

Unity スクリプトから JavaScript 関数を呼び出す

プロジェクトでブラウザーの JavaScript を使用で推奨される方法は、JavaScript ソースをプロジェクトに追加し、次にスクリプトコードからそれらの関数を直接呼び出すことです。そのためには、 .jslib 拡張子を使用して、Assets フォルダー内の “Plugins” サブフォルダーに JavaScript コードのあるファイルを配置します。プラグインファイルは以下のような構文を持つ必要があります。

mergeInto(LibraryManager.library, {

  Hello: function () {
    window.alert("Hello, world!");
  },

  HelloString: function (str) {
    window.alert(UTF8ToString(str));
  },

  PrintFloatArray: function (array, size) {
    for(var i = 0; i < size; i++)
    console.log(HEAPF32[(array >> 2) + i]);
  },

  AddNumbers: function (x, y) {
    return x + y;
  },

  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]);
  },

});

次に、上記の関数を以下のように C# スクリプトから呼び出します。

using UnityEngine;
using System.Runtime.InteropServices;

public class NewBehaviourScript : 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();
        
        HelloString("This is a string.");
        
        float[] myArray = new float[10];
        PrintFloatArray(myArray, myArray.Length);
        
        int result = AddNumbers(5, 7);
        Debug.Log(result);
        
        Debug.Log(StringReturnValueFunction());
        
        var texture = new Texture2D(0, 0, TextureFormat.ARGB32, false);
        BindWebGLTexture(texture.GetNativeTexturePtr());
    }
}

Simple numeric types can be passed to JavaScript in function parameters without requiring any conversion. Other data types is passed as a pointer in the emscripten heap (which is just a big array in JavaScript). For strings, you can use the UTF8ToString helper function to convert to a JavaScript string. To return a string value you need to call _malloc to allocate some memory and the stringToUTF8 helper function to write a JavaScript string to it. If the string is a return value, then the il2cpp runtime will take care of freeing the memory for you. For arrays of primitive types, emscripten provides different ArrayBufferViews into it’s heap for different sizes of integer, unsigned integer or floating point representations of memory: HEAP8, HEAPU8, HEAP16, HEAPU16, HEAP32, HEAPU32, HEAPF32, HEAPF64. To access a texture in WebGL, emscripten provides the GL.textures array which maps native texture IDs from Unity to WebGL texture objects. WebGL functions can be called on emscripten’s WebGL context, GLctx.

JavaScript と相互作用する方法に関して詳しくは、emscripten ドキュメント を参照してください。

さらに、Unity のインストールフォルダーの以下の場所に、参照して使用できるプラグインがいくつかあります。 PlaybackEngines/WebGLSupport/BuildTools/libPlaybackEngines/WebGLSupport/BuildTools/Emscripten/src/library*

コードの可視性

Starting from Unity 5.6 all the build code is executed in its own scope. This approach makes it possible to embed your content on an arbitrary page without causing conflicts with the embedding page code, and makes it possible to embed more than one build on the same page.

If you have all your JavaScript code in the form of .jslib plugins inside your project, then this JavaScript code will run inside the same scope as the compiled build and your code should work the same way as in previous versions of Unity. For example, the following objects and functions should be directly visible from the JavaScript plugin code: Module, SendMessage, HEAP8, ccall etc..

However, if you are planning to call the internal JavaScript functions from the global scope of the embedding page, you must use the unityInstance variable in your WebGL Template index.html. Do this after the Unity engine instantiation succeeds, for example:

  var myGameInstance = null;
    script.onload = () => {
      createUnityInstance(canvas, config, (progress) => {...}).then((unityInstance) => {
        myGameInstance = unityInstance;
        …

Then you can send a message to the build using myGameInstance.SendMessage(), or access the build Module object using myGameInstance.Module.

Unity スクリプト関数を JavaScript から 呼び出す

ブラウザーの JavaScript から Unity スクリプトにデータや通知の送信が必要な場合があります。推奨される方法は、コンテンツ内でゲームオブジェクトのメソッドを呼び出すことです。プロジェクトに埋め込まれた JavaScript プラグインから呼び出しを行う場合は、以下のコードを使用します。

MyGameInstance.SendMessage(objectName, methodName, value);

objectName はシーンのオブジェクトの名。 methodName は、現在オブジェクトにアタッチされているスクリプトのメソッド名です。value には文字列、数字などで、以下の例のように空にしておくことも可能です。

MyGameInstance.SendMessage('MyGameObject', 'MyFunction');
MyGameInstance.SendMessage('MyGameObject', 'MyFunction', 5);

MyGameInstance.SendMessage('MyGameObject', 'MyFunction', 'MyString');

埋め込みページのグローバルスコープから呼び出しをしたい場合は、後述の コードの可視性 セクションを参照してください。

C 関数を Unity スクリプトから呼び出す

Unity は emscripten を使用してソースコードをC または C++ から JavaScript へとコンパイルしているので、同じように C または C++ でプラグインを書きその関数を C# から呼び出すこともできます。ですから、上の例のような jslib の代わりに、プロジェクトで下のような C/C++ ファイルを使用することが可能です。このプラグインは自動でコンパイルされ、上の JavaScript の例のようにスクリプト側から呼び出すことが可能です。

プラグインを実装するのに C++ (.cpp) を使用する場合は、名前マングリング を避けるために、関数を C リンケージで宣言してください。

# include <stdio.h>

extern "C" void Hello ()
{
    printf("Hello, world!\n");
}

extern "C" int AddNumbers (int x, int y)
{
    return x + y;
}

  • replaced Pointer__stringify() with UTF8ToString in 2021.2 onwards

  • unity.Instance replaced with createUnityInstance in 2020.1

  • コード例の誤りを修正

  • WebGL instance renamed from gameInstance to unityInstance in 2019.1

Memory in WebGL
WebGL performance considerations