WebGL:與瀏覽器腳本進(jìn)行交互
在為網(wǎng)絡(luò)構(gòu)建內(nèi)容時(shí)芭析,您可能需要與網(wǎng)頁(yè)上的其他元素進(jìn)行通信窗悯∑刻樱或者您可能希望使用Unity默認(rèn)現(xiàn)在不公開(kāi)的Web API實(shí)現(xiàn)功能。在這兩種情況下丽已,您都需要直接與瀏覽器的JavaScript引擎進(jìn)行交互蚌堵。 Unity WebGL提供了不同的方法來(lái)執(zhí)行此操作。
Calling JavaScript functions from Unity scripts 從Unity腳本調(diào)用JavaScript函數(shù)
在項(xiàng)目中使用瀏覽器JavaScript的推薦方法是將JavaScript源添加到項(xiàng)目中沛婴,然后直接從腳本代碼中調(diào)用這些函數(shù)吼畏。為此,請(qǐng)?jiān)贏ssets文件夾中的“Plugins”子文件夾下使用.jslib擴(kuò)展名(如UnityScript編譯器的常規(guī).js文件)將JavaScript代碼放置到文件中嘁灯。插件文件需要這樣的語(yǔ)法:
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());
}
}
簡(jiǎn)單的數(shù)字類型可以通過(guò)函數(shù)參數(shù)傳遞給JavaScript,而不需要任何轉(zhuǎn)換丑婿。其他數(shù)據(jù)類型將作為emscripten堆中的指針傳遞(這實(shí)際上只是JavaScript中的一個(gè)大數(shù)組)性雄。對(duì)于字符串,您可以使用Pointer_stringify
幫助函數(shù)轉(zhuǎn)換為JavaScript字符串羹奉。為了返回一個(gè)字符串值毅贮,你需要調(diào)用_malloc
來(lái)分配一些內(nèi)存和stringToUTF8
輔助函數(shù)來(lái)為它寫(xiě)一個(gè)JavaScript字符串。如果字符串是一個(gè)返回值尘奏,那么il2cpp運(yùn)行時(shí)將負(fù)責(zé)為您釋放內(nèi)存。對(duì)于基本類型的數(shù)組病蛉,emscripten
將不同大小的整數(shù)炫加,無(wú)符號(hào)整數(shù)或浮點(diǎn)內(nèi)存表示形式的堆棧提供給它的堆堆:HEAP8瑰煎,HEAPU8,HEAP16俗孝,HEAPU16酒甸,HEAP32,HEAPU32赋铝,HEAPF32插勤,HEAPF64。要訪問(wèn)WebGL中的紋理革骨,emscripten提供了GL.textures
數(shù)組农尖,它將Unity中的原生紋理ID映射到WebGL紋理對(duì)象×颊埽可以在emscripten的WebGL上下文GLctx
上調(diào)用WebGL函數(shù)盛卡。
Legacy ways of calling JavaScript code from Unity 從Unity調(diào)用JavaScript代碼的傳統(tǒng)方式
注意:
從Unity 5.6開(kāi)始,從Unity調(diào)用JavaScript代碼的推薦方式是通過(guò).jslib插件筑凫。下面描述的方法僅出于兼容性原因而被支持滑沧,并且可能在Unity的未來(lái)版本中被棄用。
您可以使用Application.ExternalCall()和Application.ExternalEval()函數(shù)來(lái)調(diào)用嵌入網(wǎng)頁(yè)上的JavaScript代碼巍实。請(qǐng)注意滓技,表達(dá)式在構(gòu)建的本地范圍內(nèi)進(jìn)行評(píng)估。如果您想在全局范圍內(nèi)執(zhí)行JavaScript代碼棚潦,請(qǐng)參閱下面的代碼Code Visibility(可見(jiàn)性)部分令漂。
Calling Unity scripts functions from JavaScript 從JavaScript調(diào)用Unity腳本函數(shù)
有時(shí)您需要從瀏覽器的JavaScript中向Unity腳本發(fā)送一些數(shù)據(jù)或通知。推薦的方法是在你的內(nèi)容中調(diào)用GameObjects上的方法瓦盛。如果您正在使用嵌入到項(xiàng)目中的JavaScript插件進(jìn)行調(diào)用洗显,則可以使用以下代碼:
SendMessage(objectName, methodName, value);
其中objectName
是場(chǎng)景中對(duì)象的名稱; methodName
是腳本中當(dāng)前附加到該對(duì)象的方法的名稱;值可以是字符串,value
原环,也可以是空的挠唆。例如:
SendMessage('MyGameObject', 'MyFunction');
SendMessage('MyGameObject', 'MyFunction', 5);
SendMessage('MyGameObject', 'MyFunction', 'MyString');
如果您想從嵌入頁(yè)面的全局范圍撥打電話,請(qǐng)參閱下面的代碼可見(jiàn)性部分嘱吗。
Calling C++ functions from Unity scripts 從Unity腳本調(diào)用C++函數(shù)
由于Unity使用emscripten將C++源代碼編譯為JavaScript玄组,您還可以使用C或C++代碼編寫(xiě)插件,并從C#中調(diào)用這些函數(shù)谒麦。因此俄讹,與上例中的jslib文件不同,您可以在項(xiàng)目中使用如下所示的c文件 - 它將自動(dòng)使用腳本進(jìn)行編譯绕德,并且可以從中調(diào)用函數(shù)患膛,就像上面的JavaScript示例中一樣。
如果您使用C++(.cpp)實(shí)現(xiàn)插件耻蛇,那么您必須確保使用C鏈接聲明函數(shù)以避免名稱修改問(wèn)題踪蹬。
#include <stdio.h>
void Hello ()
{
printf("Hello, world!\n");
}
int AddNumbers (int x, int y)
{
return x + y;
}
Code visibility 代碼可見(jiàn)性
從Unity 5.6開(kāi)始胞此,所有構(gòu)建代碼都在其自己的范圍內(nèi)執(zhí)行。這種方法可以將游戲嵌入到任意頁(yè)面中跃捣,而不會(huì)與嵌入頁(yè)面代碼發(fā)生沖突漱牵,并且可以在同一頁(yè)面上嵌入多個(gè)構(gòu)建。
如果您的項(xiàng)目中包含.jslib插件形式的所有JavaScript代碼疚漆,那么此JavaScript代碼將與編譯的內(nèi)部版本在相同的范圍內(nèi)運(yùn)行酣胀,并且您的代碼的工作方式應(yīng)與以前版本的Unity中的方式幾乎相同(適用于例如,以下對(duì)象和函數(shù)應(yīng)該直接從JavaScript插件代碼中可見(jiàn):Module娶聘,SendMessage闻镶,HEAP8,ccall等)趴荸。
但是儒溉,如果打算從嵌入頁(yè)面的全局范圍調(diào)用內(nèi)部JavaScript函數(shù),則應(yīng)始終假定頁(yè)面上嵌入了多個(gè)構(gòu)建版本发钝,因此應(yīng)明確指定要引用的構(gòu)建版本顿涣。例如,如果你的游戲已經(jīng)被實(shí)例化為:
var gameInstance = UnityLoader.instantiate("gameContainer", "Build/build.json", {onProgress: UnityProgress});
然后酝豪,您可以使用gameInstance.SendMessage()
向構(gòu)建發(fā)送消息涛碑,或訪問(wèn)構(gòu)建模塊對(duì)象,如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