cryengine3中lua腳本模塊集成筆記

      公司上個仿真項目使用了cryengine3來製作,所以有機會接觸和分析世界頂尖的引擎。作爲一個通用引擎,那麼必須具備很好的擴展性,讓用戶能夠自定義開發,其中腳本是不可缺少的一個模塊,與unreal engine 3的專用腳本不同,ce3使用了lua腳本,因wow而出名。由於lua是一個獨立的腳本語言,所以可以集成任何引擎,而分析ce3可以學習頂尖引擎是如何設計和集成腳本的。
      首先談下自己對腳本模塊的看法,腳本的好處是即時修改,不用重新編譯並運行exe程序,基於這個好處,可以把可能會經常修改調整的邏輯用腳本來實現,而引擎只負責基本不變的邏輯。但變與不變具有相對性,對專用引擎來說,因爲需要定製很多功能,所以經常 變的主要是這些功能的配置等邏輯,而對通用引擎來說,理論上用戶可以自定義開發各種各樣的遊戲,所以整個遊戲邏輯都屬於會變的,應該可以由腳本來實現,當然完全獨立出來是不現實的,因爲有些邏輯跟引擎結合很緊或腳本實現效率太低。
      現在回到ce3,ce3確實儘量把很多遊戲邏輯獨立出來,比較深入用過ce3的編輯器sandbox的人應該有所體會,sandbox裏面有很多entity對象,這些對象都有腳本文件,實際上這些對象都是由自己的腳本文件創建出來的,用戶可以通過創建腳本來創建自己的entity和entity的遊戲邏輯,下面分析下ce3裏面entity的lua腳本集成做法,只記錄下實現思想,不涉及具體代碼。
1、用lua表現一個entity對象
     在c++中要表現一個對象最常用的就是類(類包含數據和函數),lua中沒有類,但使用的技術可以變相實現相同的效果,lua通過table、 meta table、__index、__newindex來實現c++類中的基類和派生類,ce3中entity對象都是以table來定義的,對象的屬性和函數都是table中的數據。
2、引擎和腳本的交互
     一個lua對象定義好後,那麼需要和引擎就需要進行交互,如:創建一個實例、修改實例屬性、調用實例的函數等。
     ce3在引擎腳本模塊初始化時會掃描entity的資源,把每個entity對象(table)加載到lua中,然後c++內保存的lua中的引用,這個entity對象或者說table對象是被實例所共享。

     當加載關卡或sandbox編輯時一個entity對象可能會產生多個實例,每個實例的屬性可以不同,遊戲過程中可以調用實例的函數或事件進行交互。這一過程中引擎內部的實際操作是這樣的:實例創建的實際操作是創建了兩個lua內的table,一個是實例,一個是屬性,然後將上面提到的共享的對象中的屬性表(以字符串"properties"命名)複製到實例的屬性,這些值對於編輯時新加的實例是默認值,關卡加載時這些值則會被編輯時編輯後的值覆蓋,最後屬性(表)會放到實例(表)中,然後共享的對象表作爲實例的__index,這樣實例就"繼承了"entity的函數。

    當引擎調用entity的函數時,將實例(一個lua table)作爲第一個參數傳給實例的函數,這樣函數內訪問的值就是實例的值而不是共享對象的值。

    由於引擎對腳本的定義是一無所知的,所以所有屬性和函數都是用字符串作爲關鍵字來訪問的,也預設了一些關鍵字,如上面提到的屬性表名爲"properties"還有一些函數名,函數調用參數個數在引擎內部也是預先定義好多個參數的模板。除了一些預設的函數,比如實例的初始化,引擎一般不會調用實例的函數(也不知道entity有那些函數),這些函數通常由用戶定義的邏輯來調用,如flowgraph、ai、trackview等。

    筆記比較凌亂,主要用於記錄自己理解一些思想,要實現完整的腳本模塊還有非常多的細節需要考慮和完善。

    

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章