Web 用のコンテンツを構築するときは、Web ページ上の他の要素とやり取りする必要があります。また、Web API を使用して Unity が現在デフォルトで公開していない機能を実装したい場合もあるかもしれません。 いずれの場合も、ブラウザーの JavaScript エンジンと直接やり取りする必要があります。Unity WebGL はこれを行うためのさまざまな方法を提供します。
プロジェクトでブラウザーの 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/lib
と PlaybackEngines/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.
プロジェクト内の 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
を使ってビルドのモジュールオブジェクトにアクセスします。
ブラウザーの 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');
埋め込みページのグローバルスコープから呼び出しをしたい場合は、後述の コードの可視性 セクションを参照してください。
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;
}
2021.2 以降で Pointer__stringify() を UTF8ToString に置き換えました。
2020.1 で unity.Instance が createUnityInstance に変更されました。
コード例の誤りを修正
2019.1 で WebGL インスタンスの名称が gameInstance から unityInstance に変更されました。