[翻譯]Godot創(chuàng)始人對從Unity遷移的答疑解惑

自從9月12日Unity公布了新的收費(fèi)模式后窘游,一部分開發(fā)者開始轉(zhuǎn)向免費(fèi)開源的Godot引擎针史。為了讓開發(fā)者少走一些彎路斩披,Godot創(chuàng)始人Juan Linietsky這幾天發(fā)布了一系列推文秋泳,針對引擎各方面做了一些答疑,很多東西是官方文檔沒有提到的乡革,更偏向于“在引擎作者眼中這個引擎應(yīng)該怎么用”,值得翻譯記錄一下摊腋。

包含以下內(nèi)容:

  • 概念上的對應(yīng)關(guān)系
  • 場景樹理念與Unity的區(qū)別
  • GDScript還是C#
  • 如何應(yīng)對高性能需求
  • Servers API的使用(繞過場景系統(tǒng)直接使用底層API以達(dá)到極致性能)

概念上的對應(yīng)關(guān)系

實(shí)體:節(jié)點(diǎn)
組件:節(jié)點(diǎn)
場景設(shè)置:節(jié)點(diǎn)
導(dǎo)航:節(jié)點(diǎn)
光照貼圖:節(jié)點(diǎn)
視口:節(jié)點(diǎn)
行為:節(jié)點(diǎn)+腳本
預(yù)制體:場景
場景組合:場景
ScriptableObject:資源

幾乎所有內(nèi)容都是節(jié)點(diǎn)沸版、場景或資源...Unity中很多非常復(fù)雜的子系統(tǒng),在Godot中它們表達(dá)得更加自然和直觀兴蒸。

因此视粮,我建議新用戶首先熟悉 Godot 的工作原理及其背后的價(jià)值是什么。我理解(想盡快遷移到Godot的)這種沖動橙凳,但僅僅是把Godot當(dāng)成Unity一樣來轉(zhuǎn)換游戲工程蕾殴,很可能會導(dǎo)致很多痛點(diǎn)笑撞。

原文

對于場景樹的建議

我能給那些從 Unity 轉(zhuǎn)向 Godot 的人的最好建議是:
你必須將Godot的“場景樹”想象為“一棵不包含任何實(shí)體的組件樹”。這有兩個特殊點(diǎn):

  • 場景一目了然钓觉,更加清晰
  • 組合更加靈活

你不需要在每個節(jié)點(diǎn)上掛多個腳本來實(shí)現(xiàn)某種行為茴肥,只需要添加更多子節(jié)點(diǎn),子節(jié)點(diǎn)上再掛腳本即可荡灾。
此外瓤狐,預(yù)制體或場景組合,在概念上是并不存在的批幌。你可以簡單地在其他地方實(shí)例化或繼承任何場景础锐。你還可以讓它們的實(shí)例變得可編輯并做一些本地更改。

譯注:Godot中荧缘,一個節(jié)點(diǎn)上只能掛一個腳本郁稍,相比Unity中腳本是作為組件掛載到物體上,Godot中的腳本更像是節(jié)點(diǎn)功能的擴(kuò)展

最后胜宇,要理解每個場景沒有“全局設(shè)置”的概念耀怜,場景只是節(jié)點(diǎn)。 Unity 中屬于場景的事物桐愉,例如光照貼圖财破、導(dǎo)航、環(huán)境等从诲,在Godot 中仍然只是節(jié)點(diǎn)左痢,允許根據(jù)需要混合和匹配任何內(nèi)容。

即使你在 Godot 中加載場景系洛,引擎也會將其放置在一個“根”節(jié)點(diǎn)下俊性。什么是根節(jié)點(diǎn)?一個窗口節(jié)點(diǎn)描扯!沒錯定页,如果你想在游戲中使用多個窗口,請實(shí)例化更多窗口并將子節(jié)點(diǎn)放入其中绽诚。

個人認(rèn)為這個是Godot非常有特色的地方典徊,甚至有人做出了可以在多個窗口之間跳躍的2D平臺類游戲

這些事情需要一些時(shí)間才能理解,但最終發(fā)生的事情是 Godot 讓你徹底顛覆游戲開發(fā)的過程:

  • 在 Unity 中恩够,你用代碼設(shè)計(jì)游戲卒落,并使用編輯器作為一個工具
  • 在 Godot 中,你在編輯器中設(shè)計(jì)游戲蜂桶,然后添加代碼..

由于 GDScript 實(shí)際上是編輯器緊密集成的一部分(并且該語言是深度集成的)儡毕,因此使用它進(jìn)行開發(fā)的體驗(yàn)甚至比使用在單獨(dú)的 IDE 中編輯代碼的引擎更加流暢。這就是大多數(shù) Godot 用戶更喜歡它的原因扑媚。

這些概念上的差異有助于大多數(shù) Godot 用戶提高工作效率腰湾。你很可能注意到一些 Godot 項(xiàng)目贾费,甚至是那些沒有太多使用該引擎經(jīng)驗(yàn)的用戶制作的項(xiàng)目,在今年過去的大型游戲大賽(GMTK檐盟、Ludum Dare 等)中取得了不錯的成績褂萧。

所以再次強(qiáng)調(diào),在嘗試從 Unity 1:1 轉(zhuǎn)換你的游戲之前葵萎,在移植項(xiàng)目之前导犹,請花點(diǎn)時(shí)間采取行動并充分理解 Godot 的設(shè)計(jì)哲學(xué)。我最不希望的是 Unity 用戶在嘗試過程中受到傷害并獲得糟糕的體驗(yàn)羡忘。

原文

關(guān)于腳本語言GDScript

為什么 GDScript 存在谎痢?在 Godot 的背景下,有兩個主要原因是用戶的首選:

  • 快速迭代
  • 深度融合

快速迭代: 當(dāng)你忙于開發(fā)游戲時(shí)卷雕,代碼部分不會妨礙你:

  • 無構(gòu)建時(shí)間节猿,即時(shí)運(yùn)行
  • 集成編輯器,快速打開附加到節(jié)點(diǎn)的腳本
  • 立即重新加載正在運(yùn)行的游戲中的更改(熱重載)
  • 同時(shí)調(diào)試游戲數(shù)據(jù)和代碼..
  • 沒有GC..

GDScript使用引用計(jì)數(shù)漫雕,而不是垃圾回收器:內(nèi)存管理 滨嘱。根據(jù)官方文檔介紹,是為了避免GC工作時(shí)引起的卡頓和不必要的大量內(nèi)存占用浸间。

深度集成:

  • 大量與引擎緊密相關(guān)的特性:節(jié)點(diǎn)路徑語法太雨、onready、IDE中的可視化連接魁蒜、預(yù)加載關(guān)鍵字等等
  • 與引擎共享數(shù)據(jù)模型囊扳,允許零消耗的查看變量、序列化兜看、網(wǎng)絡(luò)化等
  • 將變量暴露給編輯器無需膠水層

節(jié)點(diǎn)路徑語法:
例如有一個這樣的場景:

使用$加上路徑即可獲取子節(jié)點(diǎn)锥咸,也可以將節(jié)點(diǎn)拖入代碼編輯器中自動生成代碼:

var col = $CharacterBody2D/CollisionShape2D

集成甚至更加深入:

  • 代碼自動完成可以自動提示游戲數(shù)據(jù)(節(jié)點(diǎn)路徑,文件路徑细移,動畫名稱搏予,對象中的實(shí)時(shí)數(shù)據(jù)等)
  • 可以從編輯器拖入各種東西到代碼中,自動生成相關(guān)代碼(節(jié)點(diǎn)路徑葫哗、文件路徑缔刹、屬性等)
  • 內(nèi)置的代碼編輯器和檢查器

總而言之,Godot 用戶更喜歡使用 GDScript劣针,因?yàn)檫@種針對引擎量身定制的深層次集成。就像虛幻中的藍(lán)圖亿扁。 所以捺典,Godot 并不是打算讓 C# 成為二等公民,C# 已經(jīng)盡可能地集成了(但沒辦法達(dá)到GDScript的高集成度)从祝。

原文

個人看法和建議:

雖然個人更熟悉C#襟己,但在上手Godot的過程中依然是先使用了GDScript引谜,包括參加Game Jam、制作一些個人項(xiàng)目擎浴,都是使用GDScript员咽。如果你之前使用過Python或Lua,那么GDScript是非常容易上手的贮预,給它一些嘗試贝室,說不定它是你的菜。

正如上面所說仿吞,GDScript與引擎的集成度是最高的滑频,對開發(fā)效率有不錯的提升,相比C#在開發(fā)中沒法享受到高集成度帶來的便利(例如拖拽生成代碼唤冈、可視化信號連接等等)峡迷。

性能上根據(jù)社區(qū)做的測評,C#是比GDScript快的你虹,如果非常注重性能绘搞,C#是更好的選擇;如果想在GDScript中提升性能傅物,那么使用靜態(tài)類型看杭,避免使用動態(tài)類型。

如果對強(qiáng)類型有要求挟伙,或者希望代碼盡可能與引擎解耦楼雹,這種情況下GDScript可能不是好的選擇,雖然支持靜態(tài)類型尖阔,但它本質(zhì)上還是動態(tài)類型語言贮缅,不支持接口(只有鴨子類型),沒有很強(qiáng)的類型檢查介却;與引擎集成度高也導(dǎo)致它更難與引擎解耦谴供。

Godot 3.x LTS 版本下,C#支持全平臺打包齿坷,在目前最新版Godot 4.1中桂肌,C#不支持移動端和WebGL打包。這是由于3.x 使用的是Mono永淌,而現(xiàn)在Mono已廢棄崎场,4.x版本改用.Net,沒有IL2CPP那樣的魔法加持遂蛀,需要等待微軟官方做移動端和WebGL的支持谭跨,預(yù)計(jì)時(shí)間是今年底。

多種開發(fā)語言問題

我從 Unity 開發(fā)人員那里看到的一個持續(xù)的擔(dān)憂是,由于 Godot 設(shè)計(jì)為支持多種語言(不僅僅是 C#)螃宙,這將導(dǎo)致插件碎片化蛮瞄。 Godot 使用通用語言適配器 API,因此目標(biāo)是你可以使用任何語言的任何插件谆扎。

雖然這仍然不是 100% 完善(現(xiàn)在 GDScript 可以使用 C# 和 C++ 插件挂捅,C# 只能使用 C++ 插件,但兩者都不能使用 GDScript)堂湖,在架構(gòu)上已經(jīng)可以實(shí)現(xiàn)這一點(diǎn)闲先, Godot 中的所有語言都使用相同的引擎 API。

老實(shí)說苗缩,我希望大多數(shù)復(fù)雜的附加組件都用 GDExtension (C++/Rust) 或 C# 編寫饵蒂。 借助他們都已經(jīng)使用的通用 Godot 語言 API 適配器,應(yīng)該很容易實(shí)現(xiàn)互通酱讶。

好奇這是如何運(yùn)作的退盯?基本上,Godot 4 使用 C 中公開的 API 適配器:

https://github.com/godotengine/godot/blob/master/core/extension/gdextension_interface.h

C 非常高效泻肯,這個星球上的每種語言編程都可以與它交互渊迁。此外,C 是 ABI 穩(wěn)定的灶挟,確保當(dāng)前和未來的互操作琉朽。

順便說一下,在編寫或使用插件時(shí)稚铣,這對你來說是完全透明的箱叁,你將在文檔中看到 API,并且只需從你喜歡的語言中使用它即可惕医。

原文

性能問題

我從遷移到Godot的Unity用戶那里看到的另一個常見主題是耕漱,Godot是如何處理類似用Burst/ECS編寫的代碼的? 這是以不同的哲學(xué)方式處理的抬伺,節(jié)點(diǎn)沒問題螟够,但是如果處理數(shù)萬個節(jié)點(diǎn),性能就會受到影響峡钓,那么該怎么辦妓笙?

在 Godot 中,有兩種方法可以獲得“更快”的性能能岩,特別是對于大量實(shí)體:

  • 用底層語言重寫腳本(C++/Rust/等)
  • 使用Servers API

正如我之前提到的寞宫,Godot 使用通用語言適配器 API。這意味著捧灰,如果你有一個帶有腳本的節(jié)點(diǎn)并且需要對其進(jìn)行優(yōu)化淆九,你可以簡單地用更快的語言(C++统锤、Rust毛俏,甚至 C#)重寫它炭庙,并且對于其余代碼來說它將是透明的。

一般來說煌寇,需要優(yōu)化的部分很谢捞恪(比如永遠(yuǎn)不會超過整個游戲的 5%),其余部分 GDScript 可以很好地處理阀溶。 但如前所述腻脏,如果使用節(jié)點(diǎn),在處理數(shù)以萬計(jì)的實(shí)體時(shí)可能會遇到問題银锻,這種情況下應(yīng)該使用Servers API永品。

Godot 提供了兩個抽象層:場景層(Scene)和服務(wù)層(Servers)。場景及其節(jié)點(diǎn)是一個高級的击纬、非常靈活的抽象鼎姐。但Godot中所有的底層操作都是在服務(wù)層完成的。在Godot中更振,你可以輕松繞過場景層炕桨,直接使用服務(wù)層。

使用底層語言和Servers API肯腕,你可以獲得最大性能献宫,并且仍然保留使用 Godot 的所有可移植性和易用性優(yōu)勢,同時(shí)該代碼可以與游戲的所有高級代碼順利交互实撒。

原文

Godot 4.x支持Compute Shader姊途,但這里沒有提到太多

下面是對Servers API文檔的部分翻譯

使用Servers優(yōu)化性能

官方文檔-使用Servers優(yōu)化性能

就像大多數(shù)引擎那樣,Godot的場景系統(tǒng)使用節(jié)點(diǎn)與資源來簡化項(xiàng)目內(nèi)容的組織和資產(chǎn)的管理知态,以此制作復(fù)雜的游戲捷兰。但是顯然,這樣做有以下缺點(diǎn):

  • 這又會導(dǎo)致一層額外的復(fù)雜性
  • 性能比直接使用簡單 API 時(shí)要低
  • 不可能使用多個線程來控制它們
  • 需要更多的內(nèi)存

大部分情況下肴甸,這并不是問題(Godot 進(jìn)行了非常多的優(yōu)化哆姻,大多數(shù)操作都使用信號處理晦款,因此不需要做輪詢)。盡管如此,有些情況還是不能滿足要求颖榜,例如,每幀需要處理數(shù)以萬計(jì)的實(shí)體可能會達(dá)到性能瓶頸看铆。

Godot最有趣的設(shè)計(jì)決策之一是整個場景系統(tǒng)是可選的法瑟。雖然目前還不能將其單獨(dú)提出來,但是在運(yùn)行時(shí)可以完全繞過它浮庐。

與Unity類比甚负,就像是繞過Renderer組件柬焕,直接調(diào)用底層API渲染

在核心部分,Godot 使用了服務(wù)層的概念梭域。它們是用于控制渲染斑举、物理、聲音等的非常底層的 API病涨。場景系統(tǒng)是建立在他們之上富玷,并直接使用他們。最常見的服務(wù)層有:

查看它們的API可以發(fā)現(xiàn)既穆,提供的函數(shù)都是Godot允許你做的所有事情的底層實(shí)現(xiàn)赎懦。

使用服務(wù)層的關(guān)鍵是理解資源 ID (RID)對象。這些是服務(wù)器實(shí)現(xiàn)的不透明句柄幻工。它們是手動分配和釋放的励两。服務(wù)器中的幾乎每個函數(shù)都需要 RID 來訪問實(shí)際資源。

大多數(shù) Godot 節(jié)點(diǎn)和資源都在內(nèi)部包含了來自服務(wù)層的這些 RID囊颅,可以通過不同的函數(shù)獲得它們当悔。事實(shí)上,繼承 Resource 的任何內(nèi)容都可以直接強(qiáng)制轉(zhuǎn)換為 RID迁酸,然后可以將資源作為 RID 傳遞給服務(wù)層 API先鱼。但是,并非所有資源都包含 RID(在這種情況下奸鬓,RID 將是空的)焙畔。

下面是一些使用Servers API的示例:

創(chuàng)建Sprite

extends Node2D

# RenderingServer需要維持一個紋理引用
var texture

func _ready():
    # 創(chuàng)建一個CanvasItem
    var ci_rid = RenderingServer.canvas_item_create()
    # 設(shè)置當(dāng)前節(jié)點(diǎn)為父節(jié)點(diǎn)
    RenderingServer.canvas_item_set_parent(ci_rid, get_canvas_item())
    # 將紋理畫在CanvasItem上
    texture = load("res://my_texture.png")
    # 使用RenderingServer添加到渲染
    RenderingServer.canvas_item_add_texture_rect(ci_rid, Rect2(texture.get_size() / 2, texture.get_size()), texture)
    # 旋轉(zhuǎn)45°,變換位置
    var xform = Transform2D().rotated(deg_to_rad(45)).translated(Vector2(20, 30))
    RenderingServer.canvas_item_set_transform(ci_rid, xform)

Canvas Item API允許你往Canvas上畫東西串远,一旦添加宏多,它們便無法修改,需要清除然后再次添加(變換位置澡罚、旋轉(zhuǎn)不需要清除)伸但。

通過這個函數(shù)來清除:

RenderingServer.canvas_item_clear(ci_rid)

用過SFML可能會對這種方式比較熟悉(但又有一些不同),SFML中幾乎每幀都需要調(diào)用draw和clear

創(chuàng)建Mesh

extends Node3D

# RenderingServer需要維持一個網(wǎng)格引用
var mesh

func _ready():
    # 創(chuàng)建一個3D實(shí)例.
    var instance = RenderingServer.instance_create()
    # 設(shè)置scenario留搔,這樣這個實(shí)例才會出現(xiàn)當(dāng)前世界中
    var scenario = get_world_3d().scenario
    RenderingServer.instance_set_scenario(instance, scenario)
    # 添加網(wǎng)格
    mesh = load("res://mymesh.obj")
    RenderingServer.instance_set_base(instance, mesh)
    # 移動網(wǎng)格
    var xform = Transform3D(Basis(), Vector3(20, 100, 0))
    RenderingServer.instance_set_transform(instance, xform)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末更胖,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子隔显,更是在濱河造成了極大的恐慌却妨,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件括眠,死亡現(xiàn)場離奇詭異彪标,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)掷豺,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進(jìn)店門捞烟,熙熙樓的掌柜王于貴愁眉苦臉地迎上來薄声,“玉大人,你說我怎么就攤上這事题画∧妫” “怎么了?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵婴程,是天一觀的道長廓奕。 經(jīng)常有香客問我抱婉,道長档叔,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任蒸绩,我火速辦了婚禮衙四,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘患亿。我一直安慰自己传蹈,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布步藕。 她就那樣靜靜地躺著惦界,像睡著了一般。 火紅的嫁衣襯著肌膚如雪咙冗。 梳的紋絲不亂的頭發(fā)上沾歪,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天,我揣著相機(jī)與錄音雾消,去河邊找鬼灾搏。 笑死,一個胖子當(dāng)著我的面吹牛立润,可吹牛的內(nèi)容都是我干的狂窑。 我是一名探鬼主播,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼桑腮,長吁一口氣:“原來是場噩夢啊……” “哼泉哈!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起破讨,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤丛晦,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后添忘,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體采呐,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年搁骑,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了斧吐。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片又固。...
    茶點(diǎn)故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖煤率,靈堂內(nèi)的尸體忽然破棺而出仰冠,到底是詐尸還是另有隱情,我是刑警寧澤蝶糯,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布洋只,位于F島的核電站,受9級特大地震影響昼捍,放射性物質(zhì)發(fā)生泄漏识虚。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一妒茬、第九天 我趴在偏房一處隱蔽的房頂上張望担锤。 院中可真熱鬧,春花似錦乍钻、人聲如沸肛循。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽多糠。三九已至,卻和暖如春浩考,著一層夾襖步出監(jiān)牢的瞬間夹孔,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工怀挠, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留析蝴,地道東北人。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓绿淋,卻偏偏與公主長得像闷畸,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子吞滞,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評論 2 344

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