WebGL:與瀏覽器腳本進行交互
在為網(wǎng)絡(luò)構(gòu)建內(nèi)容時,您可能需要與網(wǎng)頁上的其他元素進行通信?;蛘吣赡芟M褂肬nity默認現(xiàn)在不公開的Web API實現(xiàn)功能。在這兩種情況下,您都需要直接與瀏覽器的JavaScript引擎進行交互。 Unity WebGL提供了不同的方法來執(zhí)行此操作。
Calling JavaScript functions from Unity scripts 從Unity腳本調(diào)用JavaScript函數(shù)
在項目中使用瀏覽器JavaScript的推薦方法是將JavaScript源添加到項目中,然后直接從腳本代碼中調(diào)用這些函數(shù)。為此,請在Assets文件夾中的“Plugins”子文件夾下使用.jslib擴展名(如UnityScript編譯器的常規(guī).js文件)將JavaScript代碼放置到文件中。插件文件需要這樣的語法:
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) + 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#腳本中調(diào)用這些函數(shù),如下所示:
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());
}
}
簡單的數(shù)字類型可以通過函數(shù)參數(shù)傳遞給JavaScript,而不需要任何轉(zhuǎn)換。其他數(shù)據(jù)類型將作為emscripten堆中的指針傳遞(這實際上只是JavaScript中的一個大數(shù)組)。對于字符串,您可以使用Pointer_stringify幫助函數(shù)轉(zhuǎn)換為JavaScript字符串。為了返回一個字符串值,你需要調(diào)用_malloc來分配一些內(nèi)存和stringToUTF8輔助函數(shù)來為它寫一個JavaScript字符串。如果字符串是一個返回值,那么il2cpp運行時將負責(zé)為您釋放內(nèi)存。對于基本類型的數(shù)組,emscripten將不同大小的整數(shù),無符號整數(shù)或浮點內(nèi)存表示形式的堆棧提供給它的堆堆:HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64。要訪問WebGL中的紋理,emscripten提供了GL.textures數(shù)組,它將Unity中的原生紋理ID映射到WebGL紋理對象。可以在emscripten的WebGL上下文GLctx上調(diào)用WebGL函數(shù)。
Legacy ways of calling JavaScript code from Unity 從Unity調(diào)用JavaScript代碼的傳統(tǒng)方式
注意:
從Unity 5.6開始,從Unity調(diào)用JavaScript代碼的推薦方式是通過.jslib插件。下面描述的方法僅出于兼容性原因而被支持,并且可能在Unity的未來版本中被棄用。
您可以使用Application.ExternalCall()和Application.ExternalEval()函數(shù)來調(diào)用嵌入網(wǎng)頁上的JavaScript代碼。請注意,表達式在構(gòu)建的本地范圍內(nèi)進行評估。如果您想在全局范圍內(nèi)執(zhí)行JavaScript代碼,請參閱下面的代碼Code Visibility(可見性)部分。
Calling Unity scripts functions from JavaScript 從JavaScript調(diào)用Unity腳本函數(shù)
有時您需要從瀏覽器的JavaScript中向Unity腳本發(fā)送一些數(shù)據(jù)或通知。推薦的方法是在你的內(nèi)容中調(diào)用GameObjects上的方法。如果您正在使用嵌入到項目中的JavaScript插件進行調(diào)用,則可以使用以下代碼:
SendMessage(objectName, methodName, value);
其中objectName是場景中對象的名稱; methodName是腳本中當(dāng)前附加到該對象的方法的名稱;值可以是字符串,value,也可以是空的。例如:
SendMessage('MyGameObject', 'MyFunction');
SendMessage('MyGameObject', 'MyFunction', 5);
SendMessage('MyGameObject', 'MyFunction', 'MyString');
如果您想從嵌入頁面的全局范圍撥打電話,請參閱下面的代碼可見性部分。
Calling C++ functions from Unity scripts 從Unity腳本調(diào)用C++函數(shù)
由于Unity使用emscripten將C++源代碼編譯為JavaScript,您還可以使用C或C++代碼編寫插件,并從C#中調(diào)用這些函數(shù)。因此,與上例中的jslib文件不同,您可以在項目中使用如下所示的c文件 - 它將自動使用腳本進行編譯,并且可以從中調(diào)用函數(shù),就像上面的JavaScript示例中一樣。
如果您使用C++(.cpp)實現(xiàn)插件,那么您必須確保使用C鏈接聲明函數(shù)以避免名稱修改問題。
#include <stdio.h>
void Hello ()
{
printf("Hello, world!\n");
}
int AddNumbers (int x, int y)
{
return x + y;
}
Code visibility 代碼可見性
從Unity 5.6開始,所有構(gòu)建代碼都在其自己的范圍內(nèi)執(zhí)行。這種方法可以將游戲嵌入到任意頁面中,而不會與嵌入頁面代碼發(fā)生沖突,并且可以在同一頁面上嵌入多個構(gòu)建。
如果您的項目中包含.jslib插件形式的所有JavaScript代碼,那么此JavaScript代碼將與編譯的內(nèi)部版本在相同的范圍內(nèi)運行,并且您的代碼的工作方式應(yīng)與以前版本的Unity中的方式幾乎相同(適用于例如,以下對象和函數(shù)應(yīng)該直接從JavaScript插件代碼中可見:Module,SendMessage,HEAP8,ccall等)。
但是,如果打算從嵌入頁面的全局范圍調(diào)用內(nèi)部JavaScript函數(shù),則應(yīng)始終假定頁面上嵌入了多個構(gòu)建版本,因此應(yīng)明確指定要引用的構(gòu)建版本。例如,如果你的游戲已經(jīng)被實例化為:
var gameInstance = UnityLoader.instantiate("gameContainer", "Build/build.json", {onProgress: UnityProgress});
然后,您可以使用gameInstance.SendMessage()向構(gòu)建發(fā)送消息,或訪問構(gòu)建模塊對象,如gameInstance.Module。

Unity WebGL 中文文檔 Unity 2018.1.b
1. WebGL
2. webGL Browser Compatibility
3. Building and running a WebGL project
4. WebGL: Deploying compressed builds
5. Debugging and trouble shooting WebGL builds
6. WebGL Graphics
7. WebGL Networking
8. Using Audio In WebGL
9. WebGL performance considerations
10. WebGL: Interacting with browser scripting
11. Using WebGL Templates
12. Cursor locking and full-screen mode in WebGL
13. Input in WebGL