10. WebGL: Interacting with browser scripting

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孵淘。

10

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末蒲障,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子瘫证,更是在濱河造成了極大的恐慌揉阎,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,194評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件背捌,死亡現(xiàn)場(chǎng)離奇詭異毙籽,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)毡庆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門(mén)坑赡,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人么抗,你說(shuō)我怎么就攤上這事毅否。” “怎么了蝇刀?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,780評(píng)論 0 346
  • 文/不壞的土叔 我叫張陵螟加,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng)仰迁,這世上最難降的妖魔是什么甸昏? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,388評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮徐许,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘卒蘸。我一直安慰自己雌隅,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,430評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布缸沃。 她就那樣靜靜地躺著恰起,像睡著了一般。 火紅的嫁衣襯著肌膚如雪趾牧。 梳的紋絲不亂的頭發(fā)上检盼,一...
    開(kāi)封第一講書(shū)人閱讀 49,764評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音翘单,去河邊找鬼吨枉。 笑死,一個(gè)胖子當(dāng)著我的面吹牛哄芜,可吹牛的內(nèi)容都是我干的貌亭。 我是一名探鬼主播,決...
    沈念sama閱讀 38,907評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼认臊,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼圃庭!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起失晴,我...
    開(kāi)封第一講書(shū)人閱讀 37,679評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤剧腻,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后涂屁,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體书在,經(jīng)...
    沈念sama閱讀 44,122評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,459評(píng)論 2 325
  • 正文 我和宋清朗相戀三年胯陋,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了蕊温。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,605評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡遏乔,死狀恐怖义矛,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情盟萨,我是刑警寧澤凉翻,帶...
    沈念sama閱讀 34,270評(píng)論 4 329
  • 正文 年R本政府宣布,位于F島的核電站捻激,受9級(jí)特大地震影響制轰,放射性物質(zhì)發(fā)生泄漏前计。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,867評(píng)論 3 312
  • 文/蒙蒙 一垃杖、第九天 我趴在偏房一處隱蔽的房頂上張望男杈。 院中可真熱鬧,春花似錦调俘、人聲如沸伶棒。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,734評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)肤无。三九已至,卻和暖如春骇钦,著一層夾襖步出監(jiān)牢的瞬間宛渐,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,961評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工眯搭, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留窥翩,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,297評(píng)論 2 360
  • 正文 我出身青樓坦仍,卻偏偏與公主長(zhǎng)得像鳍烁,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子繁扎,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,472評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容

  • 1.ios高性能編程 (1).內(nèi)層 最小的內(nèi)層平均值和峰值(2).耗電量 高效的算法和數(shù)據(jù)結(jié)構(gòu)(3).初始化時(shí)...
    歐辰_OSR閱讀 29,334評(píng)論 8 265
  • 第2章 基本語(yǔ)法 2.1 概述 基本句法和變量 語(yǔ)句 JavaScript程序的執(zhí)行單位為行(line)幔荒,也就是一...
    悟名先生閱讀 4,131評(píng)論 0 13
  • This article is a record of my journey to learn Game Deve...
    蔡子聰閱讀 3,762評(píng)論 0 9
  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)梳玫,斷路器爹梁,智...
    卡卡羅2017閱讀 134,629評(píng)論 18 139
  • 每周回家姚垃,總是聽(tīng)到媽媽抱怨,指責(zé)這個(gè)不好盼忌,那個(gè)不好积糯,心里煩,爸爸不愿意聽(tīng)她講谦纱,她就和我們講一件事可以講十遍看成,我實(shí)在...
    梁耀之閱讀 2,760評(píng)論 0 0