Version: 5.6
WebGLを対象とした場合に必要なメモリへの配慮
WebGL テンプレートの使用

WebGL: ブラウザースクリプトとの相互作用

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

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

プロジェクトでブラウザの JavaScript を使用する場合に推奨される方法は、JavaScript ソースをプロジェクトに加えてから、スクリプトから関数を直接呼び出すことです。 これを行うには、Assets フォルダーの Plugins サブフォルダーの下に .jslib 拡張子をつけて (通常の .js は UnityScript コンパイラーによって処理されてしまいます) JavaScript のファイルを配置します。プラグインファイルには以下のような構文が必要です。

Assets/Plugins/WebGL/MyPlugin.jslib
mergeInto(LibraryManager.library, {

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

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

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

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

  StringReturnValueFunction: function () {
    var returnStr = "bla";
    var buffer = _malloc(lengthBytesUTF8(returnStr) + 1);
    writeStringToMemory(returnStr, buffer);
    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.GetNativeTextureID());
    }
}

Simple numeric types can be passed to JavaScript in function parameters without requiring any conversion. Other data types will be passed as a pointer in the emscripten heap (which is really just a big array in JavaScript). For strings, you can use the Pointer_stringify helper function to convert to a JavaScript string. To return a string value you need to call _malloc_ to allocate some memory and the writeStringToMemory 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 コードを Unity から呼び出す古い方法

注意: Unity 5.6 以降では、Unity から JavaScript コードを呼び出すには .jslib プラグインの使用が推奨されます。以下に説明する方法は、互換性の理由でサポートされており、新しいバージョンの Unity ではサポートが廃止される場合があります。

Application.ExternalCall()Application.ExternalEval() 関数を使って、JavaScript コードが埋め込まれた Web ページでコードを呼び出すことができます。式はビルドのローカルスコープで処理されるということに注意してください。グローバルスコープで JavaScript コードを実行したい場合は、後述の コードの可視性 セクションを参照してください。

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

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

SendMessage(objectName, methodName, value);

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

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

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

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

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

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

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

Assets/Plugins/WebGL/MyPlugin.c
#include <stdio.h>
void Hello ()
{
    printf("Hello, world!\n");
}
int AddNumbers (int x, int y)
{
    return x + y;
}

コードの可視性

Unity 5.6 から、すべてのビルドコードはそれ自体のスコープで実行されます。このアプローチを使うと、ページに埋め込まれているコードと矛盾することなく、ページにゲームを埋め込むことが可能になります。また、1 つのページに複数のビルドを埋め込むことが可能になります。

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

ただし、埋め込みページのグローバルスコープから内部の JavaScript 関数を呼び出す場合は、常にページに複数のビルドが埋め込まれていると仮定する必要があります。そのため、どのビルドを参照しているかを明示的に特定する必要があります。以下は、ゲームがインスタンス化されている場合の例です。

var gameInstance = UnityLoader.instantiate("gameContainer", "Build/build.json", {onProgress: UnityProgress});

gameInstance.SendMessage() を使ってビルドにメッセージを送るか、 gameInstance.Module のようなビルドのモジュールオブジェクトにアクセスします。


WebGLを対象とした場合に必要なメモリへの配慮
WebGL テンプレートの使用