Scripting系統概論與Lua簡介

Lua Programming Language基於我很愛 Lua 這個 Scripting Language(劇本描述語言←有點彆扭的翻譯 Orz)的立場,不先來篇介紹實在說不過去啊。不過在介紹 Lua 出場前,要先把老大哥 Scripting Language 推出來暖暖場才行。

一般的程式語言,在程式碼撰寫完畢後都需要經過編譯 (Compile) 這個步驟,交由程式語言工具的編譯器 (Compiler) 進行語法驗證、程式碼連結與機器碼建立,最後才能產生出所謂的可執行檔 (Executable Files),也就是在 Windows 平台下滑鼠左鍵雙擊就會開始執行的檔案類型。而使用 Scripting Language 編寫好的程式碼,無須經過編譯的步驟就能夠被直譯 (Interpreted) 並且執行。使用 Scripting Language 有點像是使用一組預先定義好的指令集,在直譯器 (Interpreter) 解析到這些指令時,就能夠去執行預先定義好的行為與程式。所以相較於 C/C++ 屬於需要經過編譯才能執行的程式語言 (Compiled Language),Scripting Language 被稱為是一種直譯式的語言 (Interpreted Language)

有了基本的概念之後,首先,應該要問的問題是,為什麼要使用 Scripting Language?Scripting 系統與遊戲開發有什麼關連性?關於這兩個問題,這裡訪問到三位不願具名的受訪者:

  • 程式開發者A君:它可以幫助我們節省開發時間,不用每次做個小更動就要等待程式重新編譯連結,也會減少被企畫騷擾的時間。
  • 企畫設計者B先生:終於可以自由地測試各種想法與做法,而不用每天跑去問程式:請問~這個功能可不可以加一下了。(淚)
  • 美術設計者C小姐:聽說可以用來做 GUI(圖形化使用者介面)耶,不過我沒用過。

在一般遊戲開發的過程中,常見的情境是:程式開發者依據企畫設計者所訂定的文件規格,製作完成某功能後,再交由企畫檢視成果與預想的設計是否符合、是否有需要改進之處,然後再將設計交回程式開發者進行修改,修改完畢後再交由企畫設計者檢閱。以上程序會一直跳針,反覆反覆再反覆直到完成為止。設計本身是一種需要反覆迭代進行的程序,但是太頻繁的來往溝通,可能會殺死程式開發者的專注力與工作效率,也無法使企畫設計者的想法得到迅速的反饋。為了能讓程式開發者放下一點點肩上的擔子,將部分權責交由企畫設計者獨立處理,於是有了各種編輯器與 Scripting 系統的發明。

那麼,運用 Scripting 系統與一般的編輯器來開發遊戲有什麼不同?其實兩者各有所長。編輯器之類的工具,通常是一組程式設計者預設好的功能,讓使用者能夠以直覺化的方式去操作各種程序,例如場景、人物與特效編輯等等。而 Scripting 系統,則帶給使用者更大的權力與更多的可能性,可以提供使用者極大的彈性去調整與預覽製作的成果。要做出好學好用的編輯器,通常是相當曠日費時的工作,並且還需要持續地依照企畫設計者的需求增加功能與修補臭蟲。製作編輯器這項工作,可以說是沒有真正完整完成的時候。相較之下,使用 Scripting 系統需要企畫設計者更多的程式相關知識,但是卻能夠在耗費較少開發時間的情況下,達到最大的彈性與效益。

瞭解為什麼要使用 Scripting Language 之後,下一個問題是,在這麼多種類的 Scripting Language 中,為什麼要使用 Lua?它到底有什麼好處可以勝過其他競爭者?來聽聽官方的說法:

  • Lua 既小且快又不用錢。
  • Lua 是非常易學易用的的一種語言。
  • Lua 與 C/C++ 的整合性很好。
  • Lua 的可移植性極高。

Lua 的核心非常緊實且不佔空間,執行速度優於其他 Scripting Language,可擴充性極高。因為 Lua 語言本身是以 ANSI C 標準寫成,幾乎所有平台上都能夠執行,目前已經有相當多遊戲專案與其他應用程式的成功實例。我曾經在 LinuxMac OS X 平台上,測試 Windows 中寫好的 Lua 程式,在不修改任何 Script 程式碼的情況下,的確能夠順利執行無誤。

談到 Lua,就不能不提這位超級具份量的客戶:魔獸世界 (World of Warcraft)。在這款超級著名的多人線上遊戲中,也借助了許多 Lua 的威力。最為人所熟知的,就是遊戲允許玩家自行製作各式各樣的 UI(使用者介面);藉由 XML 負責定義外型配置,而 Lua 負責執行核心功能,我們可以看到世界各地玩家成千上萬的自製 UI 模組,很多的成果都不遜於官方原本製作的版本。因為這項讓玩家自製內容的開放功能,大幅增強了魔獸世界遊戲裡,以及遊戲外的社群互動。

另外,魔獸世界中的大型頭目怪物,總是擁有非常多樣化的攻擊模式,這是在其他多數 MMOG 中很少見的遊戲樂趣。我推論其中的怪物 AI,同樣也是透過 Lua 的編寫來達成這樣的功能(未證實)。假設,魔獸世界沒有使用 Lua 或其他 Scripting 系統的方式來開發這些 AI 行為,應該還有以下兩種方式,可以達成如此豐富多變的 AI 行為:

  • 交給程式開發者:每隻頭目都要寫出特定的程式碼,多少頭目就有多少特製化的程式碼,或是複製貼上複製貼上複製複製複製貼上的程式碼。
    程式開發者A君:………我要換工作(找離職單)。
  • 交給企畫設計者:需要一張超大的表格,定義所有可能發生的條件與行為,然後每次只取用其中一小部分的欄位使用。
    企畫設計者B先生:………幫我多拿一張。

回顧歷史,在不很久以前,那段晦暗不明的日子裡,許多開發者為了能得到 Scripting Language 這帖靈藥,於是自己動手寫出了各式各樣的 Scripting Language,程式碼的長相有可能類似於這樣:

IF player_hp < 100 THEN
    CAST_SPELL(1)
ELSE IF self_hp < 50 THEN
    RUNAWAY
ELSE
    MELEE_ATTACK
END

這種自家製造的 Scripting Language,往往陷入太難學習、效能太差與後續維護除蟲的無盡深淵中。終於,在 LuaPythonRuby 三者出現之後,遊戲界就像是現出了三道曙光一樣,再也不必投注人力時程開發不知會不會有問題的語言,也不必擔心開發者離職後的語言維護除錯問題。這三大 Scripting Language 在遊戲業界中都有各自的支持使用者與廣泛的應用;例如在 RPGMaker 這套著名的遊戲製作工具中,也能夠使用 Ruby 來撰寫進階的加強功能。

如果你有一種以上的程式語言學習經驗,對於 Lua 肯定能夠輕鬆上手。就算從來沒有學過任何程式語言,Lua 的學習也比其他語言來得容易許多。讀過官方網站幾個章節的參考手冊之後,就能夠很輕易地開始寫 Lua 程式了。如果對於 Lua 有進一步興趣的話,《Programming in Lua》是一本必看不可的好書。另外如果想要瞭解 Lua 如何運用在遊戲開發的各種功能上,我會推薦閱讀《Game Development with Lua》這本書。

最後,以場景編輯為例,舉個簡單的應用示範 Lua 其中一種使用方式:程式開發者需要先在 C++ 端撰寫好 Lua 端程式碼可呼叫使用的函式,然後在 Lua Script 中就可以自由呼叫使用。首先在 C++ 端的主程式中寫好:

// 在場景上增加一個物件
static int AddObject(lua_State* _pkState)
{
    string kObjectType;
    // 取出 script 傳來的第一個參數
    g_ScriptManager->GetValueAt(1, kObjectType);

    if (kObjectType == "monster") {
        // 取出後續的參數進行處理
    }
    else if (kObjectType == "light") {
       // 取出後續的參數進行處理
    }

    // 把物件交由場景相關的介面處理
    g_SceneManager->AddObject(kObjectType);
    return 0;
}

以上這樣的函式稱為 Glue Function,負責把 C++ 與 Lua 兩端膠黏起來以便於相互溝通。把這個函式註冊好之後,在 Lua 端裡就可以這樣使用:

-- 這是 Lua 中的註解

-- 增加一隻怪物在 (10, 20, 5) 的位置
AddObject("monster", 10, 20, 5)
-- 增加一個白色燈光在 (0, 50, 0) 的位置
AddObject("light", 0, 50, 0, 255, 255, 255)
-- 增加一個寶箱在 (-51, 512, 3) 的位置
AddObject("treasure", -51, 512, 3)

對於場景上各種物件的增加與刪減,從此不用透過 C++ 端程式碼的修改,能夠直接利用 Lua 端的 Script 做出更加動態與彈性的關卡設計。在下篇進階技術的文章中,會以小型商業遊戲中應用的實例,來看 Lua 真正使用在遊戲中的實做細節,敬請期待囉。

最後,讓我們一起大呼:葡萄牙月亮萬歲~! XD

28 Replies to “Scripting系統概論與Lua簡介”

  1. Script比較常見的翻譯是「腳本」,這大概是對岸流傳過來的用語。

    雖然我覺得腳本這個翻譯也沒有好到哪裡去,不過實在想不到什麼精闢又好聽的詞彙可以拿來指script…

    半路:
    阿,腳本確實是比較常見的用語。不過「腳本語言」聽起來還是不太自然就是, XD
    所以一些專有術語和專業名詞,我還是會盡量保留中英文對照,這樣應該能減少一點閱讀上的困擾。

  2. 我用的script是python. 當script嵌入至C/C++時, 真正執行的API是C/C++,
    如果把script翻譯成腳本, 那麼真正在演戲的就是這些C/C++的API了.
    所以覺得用script/腳本來稱呼這種類型的語言, 好像有那麼點傳神.
    但是在單獨寫Python時, 就不會有寫script的感覺了.

    半路:
    Script 是電影的劇本,負責安排場景、燈光、人員以及台詞,
    而 C/C++ 是真正演戲的演員,要拍出好電影還是得靠他們的表現。
    以這個角度思考,的確是一個很不錯的比喻。

    我對 Python 不熟,不過我知道它能夠用來建構比較複雜的系統,
    寫起程式的感覺,應該就和 C/C++ 相當接近了。
    不過我們還是會習慣統稱 Lua/Python/Ruby 這些傢伙為 Scripting Language 就是。

    謝謝你的回應。 ^^

  3. @Wallace:
    這玩意兒真不賴!它有點像是懶人包的 Lua 套件安裝程式,除了 Lua 本身的 binaries 與 libraries 以外,還加入了許多不同功能用途的第三方函式庫、文件與範例程式,以及 SciTE 這個很不錯的免費 Lua 編輯器加除錯器。N 個願望一次滿足!讚啦~ XD

    我也是第一次知道有這個東西,大感謝你的分享! :D

  4. 單晶片的Lua:eLua
    http://elua.berlios.de/index.html
    它沒有使用作業系統,Lua本身就是管理系統。利用IC內的CPU,Flash ROM,RAM來執行Lua,真正做到單一晶片的Lua。
    這個世界就是這樣,構想不去做,沒多久就會在網路上找到。可見好的構想還是要努力去實現。

  5. @Wallace:
    的確有構想就要盡力去嘗試才行,不認真試看看,永遠沒機會知道結果是什麼!
    Lua 的特性真的很適合運用於 embedded system 之中,現在更是證實能夠在單晶片架構上運作,真是非常有意思,不禁讓人更加期待 Lua 未來的發展與應用了。

    感謝你提供的資訊。 :D

  6. @Wallace:
    太棒了,原來有這樣一個專注於 Lua 程式設計的論壇!

    或許目前知道這個論壇的人並不多,但是有這樣一個地方真好,能夠專心討論一些比較深入的 Lua 議題。以後我會經常過去挖寶,還請多多討論指教哩。

    感謝您再次提供很棒很有用的資訊~ :D

  7. @Wallace:
    真厲害!執行出來的成果也很不錯~

    如果 Luaer 能夠提供 Lua 語法的 syntax coloring 就更好了。否則要在論壇上閱讀程式碼,實在是件頗辛苦的事情哪。

  8. @matt:
    你好,

    可以。只要利用 Lua 內附的編譯器 luac.exe,就可以將原來純文字格式的程式碼,轉換成為 binary 格式。

  9. 「Lua Performance Tips」《Lua Programming Gems》書中的一篇文章,由 Lua 之父 Roberto Ierusalimschy 詳細論述 local、string 與 table 三者對於 Lua 程式碼效能的影響,並且提出 Reduce、Reuse、Recycle 三大優化技巧,非常值得仔細參詳閱讀!

    對於程式設計者來說,雖然效能優化的議題很有意思,但其實 Lua 本身的效能已經相當優異,上述這些優化技巧大多只會在資料量超越百萬數量級時,才會產生比較顯著的影響與差異。

    謹遵優化第一守則:不要過早進行最佳化。

  10. 還是看不太懂

    既然是要用來輔助c++的東西

    為什麼不直接學c++更快?

    難道lua跟叉子一樣讓任何人一碰就會嗎?

  11. @mono:
    1.雖然沒有簡單到一碰就會(簡單到一碰就會的大概功能也不夠強),至少比C/C++容易上手,C/C++要了解系統底層才能駕馭,這不是每個人都學得來的
    2.底層的語言自由度大但可能因為一個小錯誤破壞整個系統,script語言讓使用者的權力受適當限制,可避免這個問題
    3.一些常用功能script系統幫你做好了(如字串處理、hash table),不用自己寫

  12. @mono:
    你好,

    Lua 語言並不像是拿叉子這麼簡單,不過若是比起 C++ 語言的話,它可是來得短小精悍許多。為什麼不直接學 C++ 就好?因為 Lua 可以輕易做到 C++ 很難達成的事情。

    如果 C++ 是牛刀,那麼就用這把 Lua 小刀殺雞吧!

    @Shark:
    謝謝你的解說。

  13. 今天第一次接觸利用Lua開發Mac ios 手機程式,想詢問一下如果我單純想把一個comboBox點選的資料內容顯示到一個Label上,是要參考官方哪一個章節比較有幫助啊?感謝。

  14. @Ray:
    Lua 的使用和 UI 完全無關喔。

    它不會管你要如何把內容顯示到 UI 上,把它想像成純 C 語言比較接近喔。

  15. 不好意思 請問一下 我現在在使用 corona SDK 製作手機的APP 使用Lua語法
    然後今天看到一則新聞是{一位 Android App 開發者,被警察搜索},然後查詢了一下手機APP很容易被反組譯
    所以想請問Lua有什麼的防護之道嗎?? ,因為像是proguard這種混淆程式是用在寫java的eclipse,那麼Lua有這種混淆程式或是其他的嗎?? 希望老師幫忙解惑

  16. @Mark:
    首先,至少可以用 Lua 官方編譯器 “luac”,把原來純文字格式的 Lua 原始碼編譯成二進位制 binary 格式。雖然光是這樣做,並不能做到 100% 完美的防護,但至少可以避免程式碼直接被有心人士拿去竄改。

  17. 好的 謝謝半路老師 那麼在請問一個問題 先轉換成binary格式 然後在建立成APK是這樣子嗎 (擔心這樣子會無法建成)

  18. 請問半路老師 所以是把luac檔案 全部替換成 lua檔嗎 可是無法建立成apk呢 請問有什麼好方法 可以建立 luac 的apk檔嗎 網路上找不太到 拜託了~

Leave a Reply