Home > 腳本編程 > 解構 CryEngine2 的 Script 物件模型(一)

解構 CryEngine2 的 Script 物件模型(一)

這幾天看了一點 Crysis 的 Script。CryEngine2 和 CryEngine 一樣是使用 Lua 為 Script 語言。CryEngine2 把 Lua 升級上 5.x 的版本。

雖然 CryEngine2 的功能實在比 CryEngine 進步許多,可是,有點失望的是 Crysis 的說明文檔比 Farcry 少,甚至最近才釋出的 SDK 也沒有 Script 的 API 參考文檔。暫時只看了一篇官方的 “Creating a new entity”文章和 Crysis 遊戲裡的 Script,所以很多以下的內容是未經証實的猜想。

這是部份 Script 物件模型的 UML 類別圖:

crysis.png

由於 CryEngine 的 Script 是 loosely typed,實際上並沒有真正的 Base、EntityBase 等類別和繼承存在。這圖所顯示的,只是我從例子中找到的一些共同部分,把它組合成類別及繼承。由於時間關係,我需要分開數天研究不同的「類別」,今天主要集中看 Entity。

Entity 的定義

在 CryEngine2 中,Entity 是一些可以放在關卡裡的物件,包括是物理存在的 (例如一扇門、一個補血包)和非物理的(例如 trigger)。CryEngine2 要求一個 Entity 類別要有最少兩個文件,包括一個 XML 檔和 Lua 檔,XML 包含名字及 Lua 的位置:


而 Lua 檔裡需要定義一個同名的 Class (Lua 中其實是 Table):

MyEntity = {
    Properties = {
        -- ...
    },
    Editor = {
        -- ...
    }
}

function MyEntity:OnInit()
    -- ...
end

function MyEntity:OnReset()
    -- ...
end

-- ...

Properties

Properties 是一個 Table,儲存每個 Entity instance 的屬性。所謂屬性,就是使用者定義的物件資料,而這些屬性可以在 Sandbox2 (CryEngine2 的遊戲編輯器)裡修改。Properties 可以是一般變數,也可以是 Table,例如:

MyEntity = { 
	Properties = { 
		fMessageDuration = 10.0, 
		sMesage = “Use me”, 
		bDoesNothing = 0, 
		object_MyModel = "Editor/Objects/objective.cgf", 
		Colors = { 
			clrColor = {x=1, y=0, z=0 }, 
		}, 
	}
}

每個變數的頭一個字母(如f、s、b、object_、clr等)是用來說明變數的型別,這些型別資料有助在 Sandbox 建立合適的使用者介面。另外,變數需要有預設的數值。

Editor

Editor table 放有在 Sandbox2 編輯時有用的資料,例如 Icon 變數就是用來在地圖上顯示 Entity,以顯示一些沒有 3D model 的 Entity 如 trigger、光源等物件。

Event

Sandbox2 或 Runtime 會以事件 (函式呼叫) 方式通知 Entity。其中比較重要的有:

  • OnInit(): 當 Entity 建立時呼叫
  • OnShutdown(): 當 Entity 消除時呼叫
  • OnReset(): 當 Entity 重置時呼叫,例如在 Sandbox2 進入遊戲模式後返回編輯模式時。
  • OnUpdate(): 每 frame 通知。
  • OnPropertyChange(): 有屬性被修改。
  • OnLoad(): 載入遊戲時。
  • OnSave(): 存檔時。

以下例子是當重置 Entity 時,把屬性 object_MyModel 的三維模型載入至 slot 0 (有關 slot 的概念要以後再研究)。

function MyEntity:OnReset() 
    if (self.Properties.object_MyModel ~= "") then 
        self:LoadObject(0, self.Properties.object_MyModel); 
    end 
end

Use

在 Crysis 和許多遊戲中,當玩家走到一些可互動物件時,可以按下 ‘F’ 鍵「使用」該物件,例如開門,拾起武器等。Entity Script 需要建立三個函式去實現這個功能:

  1. 編寫 IsUsable(),並傳回 2 (為甚麼是 2? 現在還不知道)。
  2. 編寫 GetUsableMessage(idx),傳回一個 string。當玩家接近這物件時,這段文字會顯示在 HUD 上。
  3. 編寫 OnUsed(user, idx),就是使用者按下 ‘F’ 鍵後,該物件會產生甚麼反應。

以下例子是當使用 MyEntity 時,會在 HUD 上顯示一句文字一段時間:

function MyEntity:IsUsable(user)
    return 2; 
end 

function MyEntity:GetUsableMessage(idx) 
    return self.Properties.sMessage; 
end

function MyEntity:OnUsed(user, idx) 
    CryAction.Persistant2DText(string.format("Used> %s", self.Properties.sMessage),2, self.Properties.Colors.clrColor, "OnUsed", self.Properties.fMessageDuration); 
end

FlowEvents

在 CryEngine2 中,新增設了一個 Flow Graph Editor。所謂 Flow Graph,就是一個視覺化的腳本。在設計關卡時,可以把 Entities 之間以事件聯系起來。例如,可以建立一扇「門」的 Entity實體,當開啟這扇門時,會引爆一個炸彈。這些因果關係可以用 Flow Graph 的形式簡單在 Sandbox2 裡建立。

要令 Entity 支持 Flow Graph,在 Script 裡要加入一個 FlowEvent 的 Table。這 FlowEvent Table 裡定義兩個名為 Inputs 和 Outputs 的 Table,分別放著輸入及輸出的事件。所謂輸入事件,就是當有訊號到達,就會呼叫一個事件函式,讓這個 Entity 的處理。而輸出事件則會產生一個訊號,通知連接到這個輸出的 Entity。例如:

MyEntity.FlowEvents = { 
    Inputs = { 
        Clone = { MyEntity.Event_Clone, "bool" }, 
        Message = { MyEntity.Event_Message, "string" } 
    }, 
    Outputs = { 
        Used = "bool" 
    } 
}

function MyEntity:Event_Clone(sender) 
    self:Clone(); 
end 

function MyEntity:Event_Message(sender, msg) 
     self.Properties.sMessage = msg; 
end

function MyEntity:OnUsed(user, idx) 
    -- ...
    self:ActivateOutput( "Used" ,true ); 
end

在最後的函式中看到,可以使用 ActivateOutput() 產生一個訊號。以這個例子來說,就是把 true 這個值輸出到 Used 事件。

加入這段 Script 後,在 Flow Graph Editor 中,就可以看到這 Entity 的輸入輸出事件。以下是一個例子,把 Used 連繫至一個 DisplayInstructionMessage Entity。那麼當「使用」 MyEntity 時,就會顯示一個訊息。

crysis_script.png

總結

這篇文主要記述 CryEngine2 的 Entity 部份。其實 Entity 還有許多要理解的地方,例如它如何連接圖像、物理、動作等引擎功能;如何做到多人同步 (Client 和 Server table);如何定義狀態機等等。此外,除了 Entity,其他種類的 Script 也很重要,例如遊戲規則、玩家、任務等等。看來還要花許多時間慢慢研究,不過,CryEngine2 的 Script 系統感覺上是很容易使用,非常值得參考。

在這星期,除了繼續了解其他遊戲對 Script 的應用,還想開展一些引擎的其他部份,例如簡單的圖像及輸入,使我可以做一些 prototypes 來測試 Script 的部份。

Comments:1

半路 08-04-09 (三) 15:43

之前只是大略知道 CryEngine2 有使用到 Lua,但是沒有深入去研究,看完了這篇文章之後,才發現 CryEngine2 真是一個非常棒而且很成功的 Lua 應用實例。

以前的時候有研究過 WoW 中的 Lua 應用,看起來 CryEngine2 的應用更為深入且有趣,真希望之後也能有時間去探索 CryEngine2 中的應用。

Comment Form
Remember personal info

Trackbacks:0

Trackback URL for this entry
http://miloyip.seezone.net/wp-trackback.php?p=25
Listed below are links to weblogs that reference
解構 CryEngine2 的 Script 物件模型(一) from Milo的遊戲開發

Home > 腳本編程 > 解構 CryEngine2 的 Script 物件模型(一)

Search
Feeds
Meta

Return to page top