Version: 2023.1
言語: 日本語
WebGL の Player 設定
Emscripten 用 WebGL ネイティブプラグイン

WebGL: ブラウザースクリプトとの対話

When building content for the web, you might need to communicate with other elements on your web page. Or you might want to implement functionality using Web APIs which Unity doesn’t expose by default. In both cases, you need to directly interface with the browser’s JavaScript engine. Unity WebGL provides different methods to do this.

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

The recommended way of using browser JavaScript in your project is to add your JavaScript sources to your project, and then call those functions directly from your script code. To do so, place files with JavaScript code using the .jslib extension in the Assets folder > Plugins subfolder. The plugin file needs to have a syntax like this:

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

});

Then, you can call these functions from your C# scripts as follows:

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(1, 1, TextureFormat.ARGB32, false);
        BindWebGLTexture(texture.GetNativeTexturePtr());
    }
}

More Details:

  • 単純な数値型は変換することなく関数のパラメーターとして JavaScript に渡すことができます。その他のデータ型は、emscripten ヒープ (Javascript の大きな配列) 内のポインターとして渡すことができます。
  • 文字列の場合は、UTF8ToString ヘルパー関数を使用して JavaScript 文字列に変換できます。
  • 文字列値を返すには、_malloc を呼び出してメモリを割り当て、stringToUTF8 ヘルパー関数を呼び出して、JavaScript 文字列を書き込みます。文字列が戻り値の場合は、IL2CPP ランタイムは自動的にメモリを解放します。
  • プリミティブ型の配列について、emscripten は、メモリのさまざまなサイズの整数、符号なし整数、浮動小数点数に対して、次のようなさまざまな ArrayBufferView をヒープに提供します。heap8、heapu8、heap16、heapu16、heap32、heapu32、heapf32、heapf64。
  • WebGL のテクスチャにアクセスするために、emscripten は Unity から WebGL テクスチャ オブジェクトにネイティブテクスチャ ID をマップする GL.textures 配列を提供します。emscripten の WebGL コンテキスト GLctx で WebGL 関数を呼び出すことができます。

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

In addition, there are several plugins in the Unity installation folder that you can use as reference: PlaybackEngines/WebGLSupport/BuildTools/lib and PlaybackEngines/WebGLSupport/BuildTools/Emscripten/src/library*.

コードの可視性

すべてのビルドコードを独自のスコープで実行することが推奨されます。これにより、埋め込みページのコードと衝突することなく、任意のページにコンテンツを埋め込むことができ、同じページに複数のビルドを埋め込むことができます。

プロジェクト内の JavaScript コードがすべて .jslib プラグインの形式である場合、この JavaScript コードはコンパイルされたビルドと同じスコープ内で実行され、コードは以前のバージョンの Unity と同じように動作します。例えば、Module、SendMessage、HEAP8、ccall など のオブジェクトと関数は、JavaScript プラグインコードから直接見ることができます。

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 から 呼び出す

The recommended way of sending data or notification to the Unity script from the browser’s JavaScript is to call methods on GameObjects in your content. If you are making the call from a JavaScript plugin, embedded in your project, you can use the following code:

MyGameInstance.SendMessage(objectName, methodName, value);

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

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

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

If you would like to make a call from the global scope of the embedding page, see the Code Visibility section.

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

Unity compiles your sources into JavaScript from C/C++ code using emscripten, so you can also write plugins in C/C++ code, and call these functions from C#. Therefore, instead of the .jslib file in the example above, you could have a C/C++ file in your project, which is automatically get compiled with your scripts, and you can call functions from it, just like in the JavaScript example above.

If you are using C++ (.cpp) to implement the plugin, then you must ensure the functions are declared with C linkage to avoid name mangling issues:

# include <stdio.h>

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

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

ノート: Unity は Emscripten バージョン 2.0.19 ツールチェーンを使用しています。


  • 2021.2 以降で Pointer__stringify() を UTF8ToString に置き換えました。

  • 2020.1 で unity.Instance が createUnityInstance に変更されました。

  • コード例の誤りを修正

  • 2019.1 で WebGL インスタンスの名称が gameInstance から unityInstance に変更されました。

WebGL の Player 設定
Emscripten 用 WebGL ネイティブプラグイン