Lua 為什麼在遊戲編程領域被廣泛運用?

想聽聽歷史和技術原因.


歷史方面:

《大話西遊》用的腳本語言是微軟的JScript(JavaScript的一種方言),維護不便bug多,受系統IE版本的影響兼容性差。所以2002年網易開發《大話西遊II》時,決定在客戶端內嵌別的腳本語言。當時該項目技術負責人云風認為要挑不出名的語言,讓做外掛的人搞不懂(《大話西遊》一代被外掛《月光寶盒》搞死了),於是就選擇了Lua 4.0。

雲風在九十年代就開發遊戲引擎並建設個人網站(雲風工作室),在遊戲開發領域聲望高。網易《大話西遊II》是首個在市場上取得成功的國產網路遊戲。所以後來國內遊戲開發行業紛紛受此影響採用Lua.

技術方面:

現在,2013年,Lua和其他流行腳本語言Python、JavaScript各分秋色:

  • 語言規範精簡、運行時庫小。其創始人稱Lua是穿過針孔的語言(Passing a Language through the Eye of a Needle),他加入的任何語言特性都能用C API簡單的調用。
  • 易於創建受限環境,C語言一端可以控制暴露給Lua腳本的任何功能。我猜這也是《魔獸世界》的插件語言選用Lua的原因。
  • 性能方面,雖然仍然比Python快,但不如V8(谷歌的JavaScript實現)。
  • 協程對於編寫並行邏輯,非常有用。而Python、JavaScript都不支持協程,只有StacklessPython、call/cc等方言支持類似功能。
  • Lua的元表很有用。不過我聽說Python也支持類似的功能。JavaScript的原型鏈則只是元表功能的十分之一左右吧。
  • Lua支持弱引用。對於上層邏輯用處不大。但對於底層引擎管理資源,超級有用。JavaScript不支持弱引用;Python支持。
  • Lua有個非官方實現,Luajit,性能不錯。

但是回到2002年,Lua和JScript相比,優勢很大。

  • 與C/C++交互方便。Lua的C API簡潔正交,而JScript的COM介面臃腫繁雜。
  • 高性能。Lua虛擬機實現簡單高效,比起JScript,又快又省內存。
  • 開源。雲風為了防外掛,後來修改了《大話西遊II》的Lua位元組碼格式,讓官方的Lua虛擬機無法兼容《大話西遊II》的Lua位元組碼。如果採用不開源的JScript,就不可能自己修改虛擬機和編譯器了。

不過很遺憾,《大話西遊II》的Lua 4.0並不支持協程。

------------------------------------------------------------------------

最後我想說,開發遊戲並不一定要腳本語言。C/C++這類低級語言寫邏輯太不方便,腳本語言能彌補這個缺陷。但如果你的項目主要語言不是C/C++,而是D、Java、Scala、Haskell、Go、C#、F#等性能接近C/C++的高級語言,那麼你就不需要額外的腳本語言。王垠寫過什麼是「腳本語言」,和我的看法基本相同。

當然還有Haxe這種既可以編譯成腳本語言,也可以編譯成C++的古怪語言來搗蛋。


Lua 被運用的領域遠不止遊戲。我的感覺是:遊戲是一個更容易被大多數人認識到的領域。比如說 Adobe Photoshop Lightroom 的 40% - 60% 由 Lua 寫成。版本 3.0 之後幾乎沒有新的 non-Lua 代碼加入。但是大多數非專業人士連 Lightroom 這個名字都沒有聽到過。所以說,Lua 在遊戲領域被廣泛運用只是 Lua 被所有領域廣泛應用的顯現。

Lua 能得到廣泛應用,是因為它完全符合 Richard Gabriel 關於軟體如何能得到認可的理論。

Language are accepted and evolved by a social process, not a technical or technological one. Successful languages must have modest or minimal computer resource request.

我曾經給 Lua 克服的問題起了一個名字:集成污染。我認為這也是 Richard Gabriel 提到了 socially acceptance 的一個重要因素。


我從另一個角度來回答這個問題。揭示遊戲程序框架與Lua關係一個關鍵的方面。

和所有人一樣,曾經認為所有腳本語言能嵌入到引擎中都是一樣的。直到引擎架構足夠複雜的時候,才發現了區別。在將腳本嵌入到本身就要處理多進程、多線程的框架之中時,腳本本身的架構會造成根本性差異,以下討論都是針對這一點說的

先放一張源碼行數對比表:

放心,我不是來說Lua有多麼簡潔多麼美妙,問題不在這裡。問題是:為什麼Lua這麼短?

任何一種程序,它所包含的邏輯功能大致和源碼規模是相關的。任何一種實用性的語言都不可能比Lua的源碼規模更小,而且未來Lua也不會變大很多,原因是——Lua嚴格限制了自己要解決的問題,從而把語言特性限制在一個非常有限的範圍之內。

其實要說Python等其它動態語言,誰也沒想讓自己變得臃腫(又不是Windows),但是事情並不總能按照想像的發展。根源在於虛擬機的框架設計主導了語言未來的走向,這裡比較一下在C語言中初始化Python和Lua的方法:

lua_State* L1;
lua_State* L2;

L1 = luaL_newstate();
L2 = luaL_newstate();

// 以上代碼初始化了兩個獨立的Lua虛擬機環境

// 初始化Python環境:
Py_Initialize();
// 之後無法初始化另一個環境,如果再次調用Py_Initialize就會錯誤

看看注釋,區別顯而易見。大部分語言的虛擬機設計的目的是為了直接解決實際問題的,所以希望虛擬機能夠獨立運行,這就與線程、進程等等操作系統功能發生了直接聯繫。比如Python環境就直接是全局變數,導致你無法在C裡面優雅地使用一個沙盒式的Python環境,也就是說Python環境和C代碼的部分理論上來講是毫無分隔的。

以下說明有不準確的地方請輕噴。

而Lua虛擬機,不準確的說,和線程、進程關係都不大,一開始就把自己摘的乾乾淨淨,沒規定1個進程只有一個Lua虛擬機,也沒規定一個線程只執行一個Lua虛擬機,X個進程Y個線程Z個虛擬機你想怎麼來就怎麼來,一切都根據你的需求來設計即可(註:實際設計時需要搞清楚全局ENV問題)。說到這裡必須提一下Skynet(雲風設計的一種伺服器框架),Skynet就是對Lua虛擬機一種很高級的應用,每次給別人介紹Skynet的「服務」與Lua虛擬機的關係,都要費不少口舌而且說不清楚,原因就是我們大部分人對進程、線程、虛擬機的關係有一些不準確的先入為主的概念。

Lua所有API的設計,都帶有上面的lua_State* L參數,這就用無副作用的方式讓Lua成為了一種非常非常非常適合嵌入的語言。無論你的框架是如何複雜,你總能找到一種簡單的嵌入Lua的方式而且對框架沒什麼影響。

以上例子都說的是伺服器框架,因為伺服器框架一般邏輯架構比較複雜。其實由於多線程和並發難題的存在,未來的客戶端邏輯框架也會有複雜化的趨勢,與Skynet同樣的Actor模型也會被應用在客戶端引擎架構上,這種情況下Lua的優勢也同樣會體現出來。

也是基於同樣的原因,Skynet這種框架很難修改為除Lua以外的其他語言的版本。

如果你恰好熟悉Python語言,那麼正好可以對比一下所謂GIL(Python全局鎖)的問題,在理解了Lua的設計思路之後,你就大概能猜到為什麼從來沒有人提Lua的全局鎖了,因為這個問題本身就不存在。

大概意思就說到這裡吧,可以在評論中繼續探討。至於Lua速度快、小巧等等其他特點,也都是Lua廣泛流行的原因的一部分。

感謝這種神奇的小語言。


Lua 虛擬機小,嵌入方便,而且效率較高,語言也有很好的設計(個人認為比 JavaScript 好)


自己用VC2008和Lua寫的一個遊戲框架,結構應該說比較美觀吧,相信不會讓大家失望,下載地址為:
百度網盤:http://pan.baidu.com/s/1sjILNrR
GitHub:GitHub - LikeUSummer/GamePainter: A repository to store my game framework
也許下面的回答還是不能說清楚lua到底哪點好,哪點適合遊戲製作,但是下載查看這個具體的程序後相信會慢慢喜歡它的*_^

以前一直聽別人說lua在遊戲領域如何流行,但是在網上搜索許多,也只是見到一些文章介紹,於是最終決定自
己來寫一個,宿主引擎和腳本框架都從零開始寫,在構思和動手製作了幾個月後,終於完成了這個完整框架,相信下載使用的同學一定會對這個引擎,以及我已編寫好的部分Lua框架模塊感到滿意,當然如有不足之處也只管指出哈。
這個框架的宿主程序(引擎)是用VC2008開發的,運行效率較高(極限測試可裝載幾百兆大地圖,上百活動遊戲對象等),這個宿主程序負責繪圖,聲音,操作消息傳遞
等基本內容,並向lua提供介面,參數簡單,函數名好記;而遊戲的上層實現則全部由lua腳本完成;
對windows開發熟悉的同學肯定都知道
MFC庫對winAPI完善的封裝,使得窗口編程中許多重複的事情不必再親自去處理,根據共性和不同點從基類往下派生,使得結構很清晰,代碼重用性很高;
這裡正是借鑒了這一思路,先總結遊戲程序的共性,從邏輯上把遊戲劃分成若干模塊,確定框架,再充分利用lua的表結構,模擬派生和繼承等面向對象特性,然
後把諸如地圖,角色,怪物,動畫,界面控制項等寫成lua模塊,通過約定一些同名介面來規範協調一些有關聯的模塊,方便世界管理器統一管理
(world.lua),這樣在製作不同遊戲時只需要通過搭配已有模塊和派生一些新模塊或寫新模塊,即可完成一個確定的新遊戲,當然我還會不斷更新lua
框架模塊,而大家如有新作品也歡迎分享出來哦
這是框架使用截圖:

這是用它做的遊戲與小應用截圖:

下面這個是一個網路搜索實驗:

下面是一個信息瀏覽工具:

以上截圖都是用這個框架開發的,希望大家能喜歡,也真的希望能有更多人了解並喜歡上lua語言
--------------------------
最後在這裡打個小廣告吧,是一個原創的數學軟體,類似matlab的simulink,個人編寫和更新了十餘版本,這是最新版,下載地址為:
http://pan.baidu.com/s/1eQEPWJo
歡迎有興趣的朋友們試用,感謝您的支持哦(軟體詳情也可以看我在知乎的另一個回答) 2016年4月7日


是因為Lua太優秀了大家不得不用它。

我不去談Lua一些高級特性,實際上長期以來,遊戲需要的腳本,功能上要求不會太高。但是,必須方便與C/C++集成。

用過Lua的都知道,Lua無論在與C/C++數據傳遞,還是在封裝都很方便,API非常簡單。同時Lua的許可證和緊湊性(把lib編譯進程序即可),都十分利於集成。這些都是Python和V8不能比的。同時,Lua編程學習難度極低。Python雖然容易學,但不簡單;JavaScript學習難度不夠低。

實際上,Lua進入遊戲業非常早,早在1998年盧卡斯的《異域狂想曲》(Grim Fandango)中,就首次在遊戲領域用到了Lua。十年之前著名的遊戲博德之門、猴島4都用了Lua。

至少從開源代碼來看,雲風對Lua的使用是十分重度的,比如skynet的入口是在Lua上。國內很多遊戲對Lua的使用很淺,多是把一些需要經常改的運算放出來給Lua做。所以很多特性顯得不那麼重要,有三大結構用,能傳遞返回參數就成。如果嵌一個腳本機到程序里來有那麼多麻煩,估計他們會自己寫套命令腳本。


遊戲領域的核心功能往往用C++等語言編寫,為了滿足遊戲活動中的各種功能組合,需要的是一個比C++這種語言簡單的,輕量級的,容易學習和使用的,性能又不錯的語言。 最好是業界有大量產品使用,得到了實際驗證。

Lua 的特點:

* 可以很方便的和用C/C++編寫的遊戲邏輯互相調用
* 很簡單,不涉及任何複雜的編程概念,麻雀雖小五臟俱全,基本的編程需要全都滿足了
* 輕量級,庫體積很小,只有幾百K。
* 學習很容易,甚至策劃都學會了編寫腳本
* 性能好, 消耗的計算機資源不多

* 已經有很多遊戲產品使用Lua
* 大話西遊2
* 魔獸世界Wow
* 劍俠情緣3

* 除了遊戲,也有其它軟體使用Lua
* Adobe Lightroom


我不太熟悉歷史。不過Lua足夠輕量,API簡明易懂。別的腳本語言,perl的API是一坨巨大的奇葩,python個頭太大。別的腳本語言,像Tcl、JS、Lisp我都沒用過。


小弟不是搞遊戲的,不過我確實用了LUA,因為我在國外工作,公司里配的電腦都是英文系統,因此需要中文輸入法。我使用的是谷歌拼音輸入法。
由於我經常需要寫技術報告,經常在開始寫之前,也就是報告的最開始的兩行,我經常寫下日期和時間,如以下格式:
Date: 2016-October-14, Friday
Time: 10:13:45
------------------------------

那這個我後來想想,是不是讓谷歌能夠自動地輸入當前系統的時間和日期呢?查了一下谷歌支持用戶的開發擴展,但是使用的就是LUA語言。

我後來調試了一個很簡短的LUA程序,在谷歌的屬性設置裡面,添加擴展。就可以實現上面的功能。以後在中文輸入狀態下,鍵入idt,然後空格鍵,則在當前的編輯器裡面,自動地輸入上述的三行,第一行日期,第二行是時間,第三行是一個分隔線。

代碼如下。
function CurrentDateTime()
currentdate = os.date("%Y-%B-%d")
weekday = os.date("%A")
currenttime = os.date("%X")
mydt = table.concat({"
Date: ", currentdate, ", ", weekday, "
Time: ", currenttime, "
------------------------------
"}, "")
return mydt
end
ime.register_command("dt", "CurrentDateTime", "test")

在谷歌拼音輸入法添加擴展的地方,如下圖。

小弟不才,很簡短的幾行代碼,供各位,特別是遊戲編程高手一笑。不過這短短的幾行代碼確實解決了我的需要。

如有指點,不勝感激。

2016-Oct-14於英國


對於手游的話

就三個字,熱更新!

須知,蘋果喬布斯定下的BB規矩,弄得很多東手游都只能用 編譯型的語言寫

萬一發現一個bug,尼瑪就要重新打包,重新搞一個 安裝包。

用戶不爽,開發者也吐血

Lua完美解決這個問題。


可以這麼說吧,未來不長的時間內,Lua在手遊客戶端領域的 應用的水平高低,基本直接決定了這個手游公司的水平高低!


因為遊戲這個行業需求變化快也變化多,經常每周都要更新版本出去.這樣的話,如果使用編譯型語言,開發效率慢很多.

最早發現並且引入Lua的遊戲應該是WOW,其中可以使用Lua來開發插件.後來,網易也開始使用Lua來編寫遊戲邏輯了,見於雲風的博客,基本上現在網易系的遊戲都或多或少的有腳本的身影,不論是Lua還是Python.至於使用純編譯語言來開發遊戲的痛苦,只有自己經歷過才會知道的了,呵呵.


國內用在遊戲上的,必然是因為熱更新,無它


在看program in lua,第一次認真看一本英文書,不過Lua的簡潔還是讓我很喜歡的。我們公司另一個大型醫療軟體(開發周期4年)裡面也使用了lua,雖然比例不多,但是至少是遊戲之外的應用。哈哈。。


從技術根本上來說,你用lua不用強制裝runtime denpendency。lua本身也短小精悍,效率也不是幾個現成主流腳本里最挫的,更關鍵是它的c like風格和本身設計理念都讓早期遊戲開發者更為熟悉。以前可沒c#這種高端貨,更早一點連cpp都不用。就是用c。後來嘛,就是效應問題,牛x公司用了這個技術,所以大家覺得好,肯定沒錯,於去跟風。另一個方向就是生態問題,你沒法問為什麼遊戲引擎大多數用cpp寫的,因為那個時候能選的東西不那麼多那麼fancy,寫這個的那幫人就是一直用cpp的...本身走大神踩過的路是比較安全,但是同時喪失了自己探索新東西的機會,but who care?show me the money就好.


體量小巧。c介面設計的很靈活。易集成,易擴展。

語言元素少,簡潔,學習成本低。
字元串處理高效。 對數據結構的描述能力強。
信息密度高。適合做配置文件。
調試機制基本夠用。
支持協程,閉包等簡化實現的手段。開發效率高。

不足之處是缺乏編譯期類型安全機制。
元數據被濫用容易引入太多語法糖。
大項目中框架設計不好的話,用起來不省心。
但這些東西都可以避免,所以總得來說還是非常優秀。


把熱烈奔放的巴西風情融入到遊戲的每行代碼中,遊戲也變有趣了。


說到lua,沒人想到大型交換機路由器上面也在用lua實現複雜電信業務吧?


除了上面那些優點,我認為還有一個很重要的因素:
lua不只是給你一個語言環境,而是給你一個語言機制,你可以在這個機制上構建你想要的東西,想面向對象,可以;想函數式編程,可以;想什麼幾乎都可以,而不是別人給你什麼你用什麼。這個特性在某些情況下是非常有力的。


遊戲界的就行,不得不提魔獸世界。


新手用lua直接上手,開發遊戲時,不需要了解C++這類語言複雜用法


推薦閱讀:

TAG:編程語言 | 遊戲開發 | Lua | 技術史 | 遊戲編程 |