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 currently 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.
プロジェクトでブラウザーの 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());
}
}
UTF8ToString
helper function to convert to a JavaScript string._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 automatically frees up the memory for you.emscripten
provides different ArrayBufferViews
into its heap for different sizes of integer, unsigned integer or floating point representations of memory: HEAP8, HEAPU8, HEAP16, HEAPU16, HEAP32, HEAPU32, HEAPF32, HEAPF64.GL.textures
array which maps native texture IDs from Unity to WebGL texture objects. You can call WebGL functions on emscripten’s WebGL context, GLctx
.JavaScript と相互作用する方法に関して詳しくは、emscripten ドキュメント を参照してください。
さらに、Unity のインストールフォルダーの以下の場所に、参照して使用できるプラグインがいくつかあります。 PlaybackEngines/WebGLSupport/BuildTools/lib
と PlaybackEngines/WebGLSupport/BuildTools/Emscripten/src/library*
The recommended approach is to execute all the build code in its own scope. This allows you to embed your content on an arbitrary page without causing conflicts with the embedding page code, and lets you 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..
ただし、埋め込みページのグローバルスコープから内部の JavaScript 関数を呼び出そうと考えている場合は、WebGL テンプレートの index.html で unityInstance
変数を使用する必要があります。これは、Unity エンジンのインスタンス化が成功した後に行います。以下はその例です。
var myGameInstance = null;
script.onload = () => {
createUnityInstance(canvas, config, (progress) => {...}).then((unityInstance) => {
myGameInstance = unityInstance;
…
その後、myGameInstance.SendMessage()
を使ってビルドにメッセージを送るか、myGameInstance.Module
を使ってビルドのモジュールオブジェクトにアクセスします。
Sometimes you need to send some data or notification to the Unity script from the browser’s JavaScript. The recommended way of doing it’s 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');
埋め込みページのグローバルスコープから呼び出しをしたい場合は、後述の コードの可視性 セクションを参照してください。
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;
}
Note: Unity is using the Emscripten version 2.0.19 toolchain.
replaced Pointer__stringify() with UTF8ToString in 2021.2 onwards
2020.1 で unity.Instance が createUnityInstance に変更されました。
コード例の誤りを修正
2019.1 で WebGL インスタンスの名称が gameInstance から unityInstance に変更されました。