Version: 2022.3
言語: 日本語
WebGLのキャッシュ動作
WebGL の入力

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

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());
    }
}
  • 単純な数値型は変換することなく関数のパラメーターとして 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 ドキュメント を参照してください。

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

コードの可視性

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

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

ただし、埋め込みページのグローバルスコープから内部の JavaScript 関数を呼び出そうと考えている場合は、WebGL テンプレートの index.html で unityInstance 変数を使用する必要があります。これは、Unity エンジンのインスタンス化が成功した後に行います。以下はその例です。

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

その後、myGameInstance.SendMessage() を使ってビルドにメッセージを送るか、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;
}

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


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

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

  • コード例の誤りを修正

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

WebGLのキャッシュ動作
WebGL の入力