最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

雜談——從Godot遷移到Defold可能用得到的一些東西

2022-09-06 16:18 作者:Fuxfantx  | 我要投稿
  1. 運(yùn)行結(jié)構(gòu)、定位系統(tǒng)

    先從游戲世界說(shuō)起。在項(xiàng)目設(shè)置中規(guī)定一個(gè)啟動(dòng)集合,進(jìn)入游戲時(shí)這個(gè)“啟動(dòng)集合”會(huì)形成一個(gè)「主游戲世界」。運(yùn)行時(shí),通過(guò)集合代理創(chuàng)建各種各樣的子游戲世界。

    運(yùn)行時(shí),游戲世界下只有對(duì)象層級(jí)和組件層級(jí)。集合形成的嵌套只改變對(duì)象在定位系統(tǒng)的Path,集合內(nèi)的對(duì)象間嵌套僅僅形成了針對(duì)部分屬性的相對(duì)綁定關(guān)系,【因此,對(duì)象間嵌套后,父子對(duì)象URL實(shí)際上是同層級(jí)分立的】

    因此,忘掉SceneTree的自由嵌套和get_node(path)吧!在Defold中我們使用URL來(lái)進(jìn)行組件的定位,先從絕對(duì)地址講起,完整的絕對(duì)地址比較像這個(gè)樣子:

    a_world:/a_sub_collection/an_object#a_component

    有一點(diǎn)需要注意:一個(gè)集合可能被加載成一個(gè)新的游戲世界,也有可能只是用集合工廠產(chǎn)生的一般集合。因此,編輯器Properties面板內(nèi)顯示的URL是相對(duì)于你所編輯的根集合而言的,不包含根集合的名稱(chēng)。

    工廠和集合工廠產(chǎn)生的對(duì)象會(huì)直接放在當(dāng)前的游戲世界根部,它們的絕對(duì)地址會(huì)比較像這個(gè)格式:

    a_world:/my_game_object0

    a_world:/my_collection0/sth_game_object

    Defold定位系統(tǒng)還有個(gè)稱(chēng)作ID的概念,但I(xiàn)D的語(yǔ)境義比較多:

    - ?對(duì)象名稱(chēng),如Properties面板里給出的id

    - ?去除socket(游戲世界標(biāo)識(shí))的絕對(duì)地址。例如,把factory.create(sth_factory_url)的返回值打印出來(lái),會(huì)得到形如“hash: [/instance42]”這樣的輸出,而其中的“/instance42”就是去除socket的絕對(duì)地址。

    - ?消息/輸入動(dòng)作的哈希值

    有點(diǎn)混亂,因此個(gè)人的建議是API里看到id什么的要反應(yīng)過(guò)來(lái),平時(shí)就避開(kāi)這個(gè)說(shuō)法吧(

    接下來(lái)就是各種速記符了,先介紹最簡(jiǎn)單的兩種:

    “.” ?根據(jù)上下文評(píng)估,定位到當(dāng)前對(duì)象上

    “#” 根據(jù)上下文評(píng)估,定位到當(dāng)前腳本

    需要注意,這兩種速記符【不是通配符】,因此“.#a_component”這種寫(xiě)法是定位不上的。

    有時(shí)需要保證我們的腳本組件具有一定的泛用性。Defold用相對(duì)地址來(lái)解決這個(gè)問(wèn)題,相對(duì)地址也是兩種:

    - ?組件級(jí)的相對(duì)地址,如“#a_component”,用于控制同屬一個(gè)對(duì)象的其他組件。

    - ?對(duì)象級(jí)的相對(duì)地址,如“an_object”、“an_object#a_component”,可以控制同一集合層級(jí)的其他對(duì)象,以及它們的組件。

    相對(duì)地址沒(méi)有提供跨集合定位的能力,針對(duì)這種需求,使用絕對(duì)地址是比較穩(wěn)妥的選擇。

    最后,URL有三種形式:字符串urlstring、哈希值hash,以及msg.url()產(chǎn)生的URL包。調(diào)用需要使用URL的API時(shí),如果傳入的是urlstring和hash,Defold就會(huì)走一次將urlstring/hash轉(zhuǎn)換為URL包的流程,因此預(yù)存URL包也是一種行之有效的優(yōu)化手段。

  2. 消息系統(tǒng)、實(shí)現(xiàn)分組

    個(gè)人而言,在Godot4(GDScript2.0)引入了Signal Callable概念,支持“信號(hào)連接到函數(shù)”寫(xiě)法之前,在Godot里用信號(hào)來(lái)實(shí)現(xiàn)組件間溝通是比較痛苦的。

    而Defold的想法和Godot不太一樣。依托定位系統(tǒng)的“超能力”(不是),他們選擇了點(diǎn)對(duì)點(diǎn)“私聊”的方法解決問(wèn)題?—— URL能觸及到的地方就是消息的可達(dá)之地。

    一般通過(guò)msg.post()方法發(fā)消息,消息可以發(fā)到一個(gè)對(duì)象,也可以發(fā)到特定組件。

    這里特別講一下腳本接收消息:除開(kāi)一部分“引擎預(yù)先規(guī)定的消息”,發(fā)到對(duì)象的消息會(huì)引發(fā)對(duì)象下每個(gè)腳本組件的on_message()回調(diào)。

    接下來(lái)關(guān)注一下消息相關(guān)API:

    msg.post方法給出了三個(gè)參數(shù):receiver、message_id、[message]

    on_message回調(diào)中有四個(gè)參數(shù):self、message_id、message、sender。

    (這里的receiver其實(shí)就是URL,三種形式都可以)

    從這里可以窺見(jiàn)消息的組成:message_id和message。游戲內(nèi)相互作用情況繁雜,因此需要區(qū)分不同種類(lèi)的消息。在Defold中,用來(lái)區(qū)分消息種類(lèi)的手段就是message_id(消息的哈希值)。

    方便起見(jiàn),msg.post()允許直接輸入string充當(dāng)message_id的參數(shù)值,也可以用hash,但on_message()的message_id只可能是hash,這意味著如果msg.post的message_id傳入的是字符串,系統(tǒng)在幕后會(huì)進(jìn)行一次轉(zhuǎn)換。

    因此,務(wù)必養(yǎng)成用hash來(lái)表示消息id的習(xí)慣。一般使用hash()方法將字符串顯式轉(zhuǎn)換為符合條件的hash值,為了避免反復(fù)調(diào)用hash()方法,建議將hash的返回值預(yù)存下來(lái)。

    不過(guò),URL包優(yōu)于urlstring/hash,因此如果要轉(zhuǎn)換/預(yù)存URL,建議直接轉(zhuǎn)到URL包。

    那么message_id旁邊message又是什么呢?message就是消息夾帶的內(nèi)容了,Defold支持“夾帶”兩種內(nèi)容:Lua Table,還有nil——也就是不夾帶()

    最后,Godot中時(shí)不時(shí)會(huì)用到的call_group()又怎么實(shí)現(xiàn)呢?—— 比較遺憾,一般是腳本里把URL之類(lèi)的預(yù)存好,然后需要的時(shí)候遍歷表手搓。。。。。。

  3. 空間、視口

    Defold雖然劃分了不同的游戲世界,但各個(gè)游戲世界共用一套世界坐標(biāo)空間,內(nèi)容也是完全混放的。

    一般只要注意到不同游戲世界對(duì)應(yīng)不同的物理層,就不會(huì)有問(wèn)題。只是,如果有Camera放到不同的組件、不同的集合,甚至不同的游戲世界,應(yīng)該怎么處理呢?答案是給相機(jī)組件發(fā)“acquire_camera_focus”消息,相機(jī)就會(huì)成為當(dāng)前的主相機(jī)。

    (暫時(shí)還不確定Camera是可以拍到整個(gè)空間的對(duì)象,還是所在世界的對(duì)象。個(gè)人傾向于前者)

    還有一點(diǎn)需要注意:GUI組件為了強(qiáng)制置頂渲染,不會(huì)在游戲世界內(nèi),建議單獨(dú)研究一下屏幕坐標(biāo)系、屏幕布局文件等內(nèi)容。

  4. 屬性、腳本內(nèi)的self、全局變量與運(yùn)行時(shí)、各種局部變量

    有時(shí)候,游戲?qū)ο笮枰玫揭恍┳远x屬性。在Defold中,這些自定義屬性掛在腳本上。個(gè)人首推在腳本中直接用go.property()方法直接導(dǎo)出到檢查器內(nèi),可以確保各個(gè)腳本實(shí)例屬性的獨(dú)立性、可觸及性(API支持了用URL+屬性字段來(lái)遠(yuǎn)程修改屬性),并且易于編輯。

    這里需要穿插一些Lua在Defold的工作模式:

    對(duì)于Defold游戲,如果在項(xiàng)目設(shè)置啟用了Shared State,那么script腳本、render腳本和gui_script腳本三者會(huì)在同一個(gè)Lua運(yùn)行時(shí)工作。但關(guān)掉這個(gè)選項(xiàng)的情形也不是那么理想—— 三種腳本分別對(duì)應(yīng)三個(gè)Lua運(yùn)行時(shí)(

    然而,每個(gè)腳本實(shí)例都需要管理自己的一套參數(shù),到這里就引出了幾種方法:

    - ?如果只需要在幾個(gè)生命周期函數(shù)作更新的話,可以使用self,是專(zhuān)屬于腳本實(shí)例的userdata。

    - ?在腳本文件的根部定義local變量,如果是內(nèi)部參數(shù)的話個(gè)人比較推薦這個(gè)方法,可以把作用域控制在一個(gè)實(shí)例內(nèi)。

    - ?直接扔腳本屬性,推薦用于需要大量交互的情形,可以節(jié)約一些消息通信成本。此外,腳本屬性也會(huì)存入self,self能夠到的地方就用不著URL什么的了。

    - ?邪道手搓!?。。。。?/p>

    因?yàn)檎麄€(gè)游戲在一個(gè)(或者三個(gè))Lua運(yùn)行時(shí)玩大亂燉,所以如果要保存一些整個(gè)游戲都要用到的變量什么的,只需在聲明變量時(shí)不加local就行了,相當(dāng)之邪乎。。。作死的意義上遍歷下_G什么的倒也不是不可以(被打死)

    最后補(bǔ)充點(diǎn)常識(shí):文件根部local適用于整個(gè)文件,代碼塊內(nèi)的local適用于當(dāng)前代碼塊在聲明之后的部分(含子級(jí)),重名情形作用域小的遮蔽作用域大的。

  5. 認(rèn)識(shí)輸入棧

    之前一直說(shuō)(項(xiàng)目設(shè)置里配置的)啟動(dòng)集合會(huì)制造一個(gè)「主游戲世界」,但頂級(jí)集合構(gòu)造的游戲世界在URL上看不出區(qū)別,為什么需要分主次呢?

    這就要說(shuō)到輸入棧了。Defold的輸入信號(hào)沿著輸入棧進(jìn)行傳遞,這種傳遞是逐個(gè)游戲世界進(jìn)行的,而不是并行,他們的做法是:

    把集合代理壓入輸入棧,集合代理就能把傳給它的輸入消息“導(dǎo)向”另外一個(gè)游戲世界了。

    而啟動(dòng)集合對(duì)應(yīng)的輸入棧正好接管著整個(gè)輸入系統(tǒng)的“入口”——從這個(gè)意義上來(lái)說(shuō),游戲世界是有主次之分的,嗯。

    前面提到輸入信號(hào)沿輸入棧傳遞,那么怎樣讓腳本檢測(cè)到輸入呢?

    —— ?對(duì)腳本所在的游戲?qū)ο蟀l(fā)“acquire_input_focus”消息,對(duì)象的各個(gè)組件就會(huì)被壓入輸入棧了。和之前的消息機(jī)制同理,其后用戶的輸入操作會(huì)引起對(duì)象上每個(gè)腳本的on_input()回調(diào)。

    —— ?暫時(shí)不支持只把腳本壓入輸入棧。

    —— ?這里補(bǔ)充一下輸入棧的傳遞次序:“后來(lái)居上”,后“壓入”的對(duì)象先得到輸入信息。

    雖然順次接收輸入會(huì)極大增加(引擎)多線程優(yōu)化的難度,但這個(gè)機(jī)制也帶來(lái)了一個(gè)好處——輸入消耗:

    在on_input()回調(diào)返回一個(gè)真值(一般用true,作死可以用0什么的),輸入棧對(duì)應(yīng)的一環(huán)就會(huì)把這個(gè)輸入直接吞掉,而在Godot里改變輸入狀態(tài)需要手搓各種set_input,從這個(gè)角度上講也算是互有優(yōu)缺。

    至于各種輸入的具體實(shí)現(xiàn),可以查官方手冊(cè)這里就不展開(kāi)了()

  6. 雜項(xiàng)

    Q:Godot很強(qiáng)大很好用,為什么要遷移到Defold?

    A:Defold有非常多的優(yōu)點(diǎn),比如:

    -- ?編輯器+全平臺(tái)打包模版控制在了300MB這個(gè)量級(jí),而Godot4是編輯器60-70MB但打包模版600-700MB

    -- ?在安卓端支持了LuaJIT,比這玩更強(qiáng)的應(yīng)該就是AOT C#腳本或者用底層語(yǔ)言寫(xiě)的原生代碼了,比如il2cpp之類(lèi)的

    -- ?打包時(shí)不需要裝外部開(kāi)發(fā)環(huán)境(但iOS打包還是離不開(kāi)macOS),甚至可以在項(xiàng)目里直接配置manifestion文件,打包時(shí)再削減點(diǎn)體積

    -- ?面向整個(gè)游戲引入了最大項(xiàng)目數(shù)優(yōu)化,通過(guò)Factory?/ Collection Factory生成的實(shí)例有自動(dòng)的對(duì)象池優(yōu)化

    -- ?編輯器內(nèi)建了圖集(Atlas)支持,對(duì)強(qiáng)迫癥友善(不是)

    A:不過(guò)最關(guān)鍵的是個(gè)人更喜歡輕量而夠用的東西,他們的設(shè)計(jì)也是很不錯(cuò)的值得支持.

    Q:Defold有沒(méi)有一些很坑的點(diǎn)?

    A:暫時(shí)有這么一些:

    -- ?Sprite必須使用Tile Source或者圖集,不能導(dǎo)入單張圖片

    -- ?字體必須手動(dòng)轉(zhuǎn)為貼圖

    -- ?自帶的JSON庫(kù)效率不高,并且不支持Stringfy,想解決這個(gè)問(wèn)題要給項(xiàng)目單獨(dú)綁定cJSON,但cJSON素質(zhì)過(guò)硬,其實(shí)是非常值得的

    -- ?文本編輯器的自帶字體對(duì)空格的處理非常逆天,個(gè)人建議手動(dòng)換成JetBrains Mono Regular

    -- ?沒(méi)有用戶數(shù)據(jù)目錄,不引入第三方插件就只能讀寫(xiě)存檔。

    -- ?按鈕要手搓

    -- ?......

    Q:以后怎么辦?

    A:個(gè)人的目標(biāo)是做一系列畫(huà)面比較素的音游,這種情況下Defold是非常合適的;Godot有非常強(qiáng)的開(kāi)箱即用性、相對(duì)完善的3D支持,和對(duì)PC GUI的超強(qiáng)布局能力,拿來(lái)做小工具,或者對(duì)性能要求不是那么高的項(xiàng)目的話應(yīng)該是個(gè)不錯(cuò)的選擇。

    Q:為什么不用Unity?

    A:這種洪水猛獸更適合業(yè)內(nèi)人士,不適合我。(


雜談——從Godot遷移到Defold可能用得到的一些東西的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
博罗县| 通道| 平顺县| 克拉玛依市| 上杭县| 项城市| 五家渠市| 黄陵县| 金华市| 潢川县| 嵊州市| 扶余县| 芮城县| 光山县| 岱山县| 德保县| 库车县| 湘西| 南汇区| 南安市| 玛多县| 托里县| 漾濞| 大连市| 龙井市| 巴里| 英德市| 绍兴市| 三明市| 浦北县| 富川| 洛浦县| 锡林郭勒盟| 龙井市| 平湖市| 盐池县| 合作市| 清丰县| 康保县| 台中县| 安达市|