遊戲開發中,腳本語言(如Lua/Python)和底層語言(C/C++)的職責劃分是怎樣的?

2015-01-13補充:

之前問題描述得不夠清晰。我了解到,在遊戲開發中,C/C++和腳本語言配合。這裡面有一個主導關係:

有的遊戲由底層C++作為主導,腳本語言作為一些輔助的功能實現,或者數據格式引入。

有的遊戲由腳本語言作為主導,底層遊戲引擎用C來提供一些具體的API介面,如圖形,聲音,網路連接,供腳本語言進行調用。

我想問問,這兩種模式的優缺點在哪裡?是出於什麼樣的一種考慮?

我的理解是,如果底層庫是以函數形式提供服務的,可以用腳本語言作為主導,如果底層庫本身基於面向對象,腳本可以僅作為具體功能調用和配置數據來用。

參考雲風的 BLOG: Lua 不是 C++

另外推薦遊戲腳本高級編程 (豆瓣)這本書。


以我們的遊戲為例。

Client

我們使用的是 cocos2d-x,這是一個 C++ 寫的 2D 引擎,支持 lua 和 JS binding。我們選擇的是 lua binding(Cocos2d-x script language binding:Lua or Javascript?)。

大多數情況下,我們完全使用 lua 開發,這樣速度比較快,不需要所有人都掌握 C++語言。遇到這樣幾種情況,會使用 C++:

  1. 引擎中沒有提供的功能;
  2. 引擎的 bug;
  3. 性能考慮;
  4. 和底層結合緊密的功能。

這些 C++功能開發完畢之後,依然是導出給 lua 來調用。

Server

目前最新的一個遊戲,我們打算使用 OpenResty 來實現。這樣依然可以用 lua 來寫,我們希望提供一套通用的 client/server lua 庫,在開發上相對更容易點。

OpenResty 和其模塊都是 C 語言開發的。若有目前 OpenResty 沒有提供的功能,就需要動用 C 語言開發。

Tools

目前在開發過程中、程序同學和美術同學需要使用的工具,例如打包、編譯、加密、格式轉換等等,我們使用的是 Python 和 Bash 來實現。需要 GUI 的用 PyQt(Python+C++)。

策劃同學

因為 client 和 server 都完全使用了 lua,我們的策劃同學也可以直接使用 lua 來書寫配置文件和計算公式。


看到這個問題,作為一個在C++和Lua之間糾纏了許多年的人,忍不住想好好的來回答一番。

先回答題主的問題,兩種模式之間的優缺點和選擇的出發點:

1.以C++為主導,腳本只是處理一些配置文件外加一些輔助的功能,比如讀取策劃數據存在lua的表裡,利用協程在遊戲里驅動一下劇情對話,跑個機器人之類,而遊戲的主要邏輯全部放在C++層處理。這樣做的優點在於C++主宰全場,不用太考慮怎樣和腳本語言互相之間的調用,以及怎麼處理好它們之間的關係,自然也就沒有了題主引用的文章裡面可能出現的把Lua當作C++來用的問題了。

缺點也是C++主宰全場,如果是只有自己一個人寫還好,最多隔一段時間之後發現以前寫的代碼太爛,實在忍不了就推了重來。但是大部分時候還是需要與別人合作的,那麼不同的人之間對於程序設計,對於C++的理解程度的差異就會很鮮明的體現在代碼之中,沒有一個強制執行且無論任何人都必須遵守的C++代碼編寫規範的話,代碼寫亂還是小事,不可避免會有各種內存泄漏,寫越界,讀越界,指針不判斷導致程序崩潰,開發的時候處理起來頭大,而正是上線如果出了問題麻煩就大了。而且C++的語言複雜度在那裡擺著,開發效率就和程序的水平嚴重掛鉤了,伺服器純邏輯還好,客戶端加入了各種視圖的處理,一旦亂起來那就是天下大亂。

然後,以前端游的時候還無所謂,而在現在手游的時代,邏輯寫在C++之中,因為每次都要編譯後鏈接到可執行文件中,對於蘋果的AppStore就沒有辦法熱更新,這也是現在很大的一個缺點。

2.以腳本作為主導,C++層一般就提供一些引擎的介面和工具函數給Lua調用,比如cocos2d-x就是提供了一個自動生成的auto luabinding外加一些手寫的manual binding就把引擎的大部分介面都提供給了Lua調用。把遊戲的邏輯全部放在腳本里的優點在於,首先,腳本語言的複雜程度肯定遠遠不如C++,上手容易,定好基本的程序結構,新來的毛頭小伙看個一周照著寫寫也就上路了,平時也不用關心C++層是怎麼實現的,有興趣休息的時候自己研究去。抹平了語言層面的難度後,開發效率自然會高一些,而且Lua本身也是很精巧的語言,玩不出太多花樣來,table加上metatable包打天下,剩下的就是照著格式調用C++層的函數完事。

動態更新方便,編譯成位元組碼往文檔目錄里更新就行了,讀取的時候先讀文檔目錄再讀遊戲包本身,隨時有問題隨時改了隨時更,這可能是unity現在也有了ulua的原因,基本上由於蘋果的限制,腳本就成為了熱更新的不二法門,越獄和安卓倒是可以跑得掉,但都只是和尚蘋果才是廟。

缺點呢,其一就是要協調好C++和Lua之間的關係,這個其實問題不大,Lua並不複雜,以Lua為主導,就按照Lua的原則盡量讓程序簡單一些就行,一般還是很少有中二會將Lua用成C++的。其二就是我個人覺得對於程序的成長不利,雖然這事兒也分人,但是一個從C++真正開始接觸實際的遊戲項目的程序和一個從Lua開始接觸的程序,視野肯定多多少少會有不同。

然後對於題主的理解:「如果底層庫是以函數形式提供服務的,可以用腳本語言作為主導,如果底層庫本身基於面向對象,腳本可以僅作為具體功能調用和配置數據來用。」大概是錯誤理解了引用文章裡面雲風的意思。用不用腳本作為主導,和宿主語言是不是面向對象的語言沒有必然的關係,選擇與否的原因還是在於具體遊戲項目的需求,和做遊戲項目的程序對於宿主語言的共識程度。

我個人認為把主要的遊戲邏輯放在腳本裡面會是一個主流的選擇,因為符合現在這個時代遊戲,尤其是手游的開發需要猛糙快的節奏(當然這主要還是在國內)而像UE4這樣的引擎,即便已經算是把C++當腳本來用了,也還提供了另外一個貫穿始終的blueprint作為腳本的選擇,說明腳本主導流是大勢所趨。

最後,對於題主,如果是一個將要或者想要和C++/Lua糾纏的連青人,我的建議是不用有絲毫疑慮,好好學,更要多多學以致用,學好C++


簡單一點的話,劇情(往大了說就是原本屬於策劃負責結果讓程序員來無工資友情實現的那部分)用腳本,其他C++。


保證腳本語言盡量不要在性能要求比較高(比如比較費的演算法)的場合或者調用次數非常頻繁的場合(比如每幀的tick)使用的前提下。。。用它怎麼控制邏輯都好吧ˊ_&>ˋ。保證運行效率的前提下保證開發效率。

ˊ_&>ˋ現在好多遊戲都用腳本啊,包括一些獨立遊戲,如don"t starve之類,腳本不僅提供了遊戲玩法還提供了擴展遊戲玩法的方式。dota不也是編輯器+lua堆出來的么。

本答案沒什麼營養求摺疊。


遊戲腳本可理解為【為策劃人員提供的簡易編程方式

凡是策劃人員可能需要不斷修改的內容和功能都可以做成腳本形式。這樣就解放了程序員和編譯器。

貼一部分《軒轅劍外傳-漢之雲》的lua腳本給你們參考(亂碼部分為繁體編碼):

mainevent051 = function()
if isfon(1017) == 1 and isfon(1051) == 0 then
fon(1051)
lock_player(1)
dark_in()
chang_main_map(142, 0, 1, 0)
lock_on()
hide_role(1, 0)
chang_role_map(31, 142, -0.5, 1.7, -27)
chang_role_map(41, 142, -15, 0, -5)
chang_role_map(42, 142, -7, 0, 25)
chang_role_map(43, 142, -14, 0, 5)
chang_role_map(44, 142, -10, 0, 15)
chang_role_map(45, 142, 10, 0, 15)
chang_role_map(55, 142, 15, 0, -5)
chang_role_map(56, 142, 14, 0, 5)
chang_role_map(57, 142, 7, 0, 25)
chang_role_map(430, 142, 0, 0, 30)
set_motion(31, 266)
set_dir_torole(41, 31, 0)
set_motion(41, 239)
for i = 42, 45 do
set_dir_torole(i, 31, 0)
set_motion(i, 101)
end
for i = 55, 57 do
set_dir_torole(i, 31, 0)
set_motion(i, 102)
end
set_role_face_motion(31, 302)
set_role_face_motion(41, 302)
story_music_off(0, 0)
story_music(111, 1, 5, 1, 2, 0)
storyinfo(" " .. c(1) .. "丁肣瓁セ犁" .. c(0) .. "")
camerainfo(0, 0, 0, 3.3, 5.4, -18.1, 171, 18.6, 40.5)
dark_out()
role_goto(430, 0, 0, 0, 0)
wait_goto(430)
set_motion(430, 30)
story_music_off(0, 0)
story_music(60, 1, 60, 1, 2, 0)
motioninfo(430, 108, 100, "盠", "幣竅皚常服よΜ候瓁薄")
motioninfo(430, 201, 100, "盠", "и瓁癶隔ㄢ矪止躇砆婦盕丁倒ю防")
camerainfo(0, 0, 0, 3.3, 5.4, -18.1, 130, -19, 5.5)
intromsg(9029, 440, 150)
set_role_face_motion(31, 380)
motioninfo(31, 267, 100, "皚舤", "ぐ或")
set_role_face_motion(31, 325)


腳本語言主要負責遊戲中那些經常變化的部分,比如遊戲的運行邏輯,遊戲的界面。而底層語言則負責遊戲中那些基本不會發生變動的部分,例如核心的演算法以及遊戲中對性能要求較高,如果用腳本寫會大大影響遊戲運行效率的部分。

腳本語言的優勢有兩個,一是寫起來方便,二是更新遊戲的時候可以在遊戲運行過程中直接更新而不需要通過應用商店,減少玩家的遊戲阻礙。

底層語言的優勢則主要在於其優越的運行效率。

是它們不同的特性決定了它們在遊戲中的職責。


理論基礎:機制與策略分離


真相是大部分人C/C++寫的不夠好,你讓他用C/C++寫要花數倍的時間還bug百出,而用腳本可以很方便的寫出更少bug的程序,而另一部分C/C++寫的很好人發現,用腳本可以更快速的實現想法,甚至有的時候還可以交給別人來幫忙寫也不會有大問題。


去看ejoy2d這個引擎的源碼吧,雲風主導的作品。源碼中應該會有你想要的答案。


對於現在手游來說,特別是用cocos2dx開發的眾多遊戲,

基本上都會採取C++提供基本的引擎、網路、核心演算法這些很少會變動的或者要求效率的東西,

腳本做一些面向玩家的客戶端邏輯

這樣做的好處是,如果腳本和C++分割的很徹底,中間只有數據在傳遞,那麼可以很方便的做到

通過資源更新就能添加新功能,對於運營和策劃的同學來說,可以每周都出新版本新玩法新活動,這是他們最喜歡的。


在保證了性能的情況下,簡單就是美


前端被迫要用lua,後端開發其實沒有什麼必要用的,一個語言寫到黑,關鍵要水平都要可以


腳本語言做主要開發語言. 只在底層操作和效率要求極高的情況下用底層語言


腳本靈活,開發效率高,熱更新等,c++部分也就項目發布前在大改和加新功能,項目發布後基本不大變,要大改測試周期也比較長。腳本出個錯用戶基本感受不到或者對繼續遊戲影響較小,c++報個錯就中斷遊戲了。


腳本一般寫邏輯

c++等一般寫引擎

於是引發以下分工:

腳本程序和策劃扯皮

引擎程序和腳本程序扯皮


取決於要不要頻繁的熱更新了。

需要頻繁的熱更新,當然是Lua或者js主導的好。

由於app store的審核原因,大部分遊戲都採用了解釋類的語言來做bind。

這樣開發門檻變低,同時又兼顧到更新app的效率。

對於熱更新也不是萬能的,你調用的lua or js api如果沒有的話,

那麼就只能更新安裝包了。


我覺得這個lua能直接放在資源文件就ok。若經常更新的部分用c++寫,蘋果APP商店審核時間還偏長。等上一星期半個月的話,那一天可都是人民幣熬,老闆肯定不樂意,但放在資源目錄下後,就不存在修改二進位文件的問題了。我這樣想對么?


一般來說底層C++等主要用來實現:架構和引擎、遊戲底層基礎庫、腳本不支持的功能(如網路模塊等)、性能相關的功能;

而腳本語言lua等主要用來實現:複雜易變的遊戲邏輯、需要經常改動更新的功能、複雜的配置等;


推薦閱讀:

為什麼要強調Texture2DArray在地形上的應用?
女性在遊戲公司做程序、測試還是策劃比較適合啊?
為什麼遊戲引擎要渲染那麼多內容還是能到 60fps?
策劃反推案是什麼意思?

TAG:遊戲開發 | 腳本語言 | C | Lua |