2012年3月11日 星期日

為內建的Unreal資源新增右鍵選項

在UEd的內容瀏覽器裡的資源圖示上按右鍵會出現選單。依照資源的種類會出現不同選項,可以自訂GenericBrowserType類別來為自訂的資源客製選項。

但是如果要為內建的Unreal資源新增右鍵選項呢?其實還是一樣自訂GenericBrowserType類別就可以了,UEd會優先使用專案覆寫的而不是內建的GenericBrowserType。以下程式碼示範如何為內建的SkeletalMesh新增屬性視窗選項:

2012年3月8日 星期四

自訂動畫事件

在播放骨架動畫時,AnimNotify用來讓開發者在指定的時間觸發事件。例如:
  • AnimNotify_Sound可用來播放音效
  • AnimNotify_PlayParticleEffect可用來播放粒子特效

開發者可以自行擴充AnimNotify系統,透過繼承AnimNotify類別體系就可以自訂動畫事件。編輯器會偵測所有的AnimNotify,所以不需修改編輯器的原始碼就可看到新增的動畫事件。AnimNotify是存放在AnimSequence裡,所以不同模型實例播放同一個動畫時用的是相同的AnimNotify,這點在撰寫AnimNotify時要特別留意。

當解析度變更時通知ActionScript

當解析度變更時,Swf原本會根據Stage.scaleMode的設定自動變更大小和位置。但是如果想要自行在ActionScript內調整,就會需要在ActionScript中取得解析度變更的通知。

雖然本來ActionScript就有提供Stage.onResize函式,不過只有在Stage.scaleMode設為noScale才會通知。然而實際使用時通常是不會設為noScale,所以只好另外從UE去通知ActionScript。

UE在解析度變更時有提供一個事件CALLBACK_ViewportResized。Scaleform GFx的介接碼也有使用這個事件,請參考UGFxInteraction::Send()。所以其實只要在這個函式中通知ActionScript就好了。呼叫GGFxEngine->GetOpenMovie()可取得目前開啟的GFxMoviePlayer,然後呼叫Invoke()來通知某個自訂的ActionScript函式就可以了。

更新Unreal的屬性視窗

在撰寫編輯器時,如果使用屬性視窗顯示UnrealScript物件,那麼在程式碼中去修改物件屬性時,會需要通知屬性視窗更新。雖然UE有提供更新的方法:
GCallbackEvent->Send(CALLBACK_ObjectPropertyChanged, Obj);

不過有兩個問題:
  • 如果第二個參數傳入NULL,那整個屬性視窗樹都會重建(請參考WxPropertyWindow::Rebuild()),這個動作可能會很慢。
  • 如果指定物件,WxPropertyWindow::Rebuild()只會檢查指定物件是否在第一層才更新(請參考WxPropertyWindow::ContainsObject())。但如是是第一層以下的子物件才擁被修改的屬性,那麼將不會更新視窗。

Unreal編輯器的兩個世界

UE的程式碼使用一個全域變數GWorld指向遊戲世界,其型別為UWorld。開發者可以透過這個全域指標呼叫UWorld的函式SpawnActor()來產生Actor,或者呼叫SingleLineCheck()進行射線檢查看看有沒有打中物件。

從Actor:Spawn()不需指定世界可以看得出UE是假設世界只有一個,Actor也沒有提供得知自己身處於哪個世界的方法。或者至少可以退一步說,就算有複數個世界,在呼叫UE前得先把GWorld設定好。

PIE的另一個世界


然而編輯器的PIE(Play in Editor)功能需要有另一個世界以供試玩,才不會在試玩過程中破壞了編輯到一半的關卡。PIE是採用偷天換日的寫法來達成,在同一個frame中適時切換GWorld指向編輯世界和試玩世界,讓兩者輪流更新。主要的相關變數或函式有:

2012年3月7日 星期三

Unreal中ActionScript的讀檔路徑

ActionScript的讀檔路徑 

 

在Unreal中的swf執行其ActionScript時,當呼叫到如MovieClipLoader.loadClip()之類的讀檔函式,讀檔路徑會對應到該Swf的Unreal package路徑。

例如:在package P的group G中swf A呼叫MovieClipLoader.loadClip("B.swf")時,會去載入Unreal content中的"P.G.B"。

這代表這些在ActionScript中會互相載入的swf必須放在同一個package裡路徑才會正確。然而如果是使用一個swf集中載入其他swf的管理方法,這個限制可能會造成多個swf集中在一個package檔,造成版本控管不便。

UnrealScript和C++之間的函式呼叫

UnrealScript是用C++實作的腳本語言。雖然有些功能可以用UnrealScript實作,不過在需要效能的場合還是得跟C++溝通。UnrealScript類別若宣告成native,會在自動生成的C++標頭檔裡產生對應的C++類別。當然這功能需要有原始碼授權才能正常運作。

UnrealScript呼叫C++函式


UnrealScript不能直接存取C++的函式。不過可以在UnrealScript宣告native function,在C++實作,使得UnrealScript函式可以呼叫native function來使用C++函式。例如在Actor.uc檔內:
class Actor extends Object
    native
...
native final function bool Move( vector Delta );

Unreal的ini檔

Unreal的ini檔可以用來變更許多設定,格式跟Windows的ini檔有點像,但多了許多自訂的功能。它一樣也是用Section、Key=Value的格式來排列分類,不過型別變成是UnrealScript支援的型別。

UObject的ini格式


例如UDKInput.ini的前兩行:
[Engine.PlayerInput]
MoveForwardSpeed=1200
第一行中括號內的Engine.PlayerInput對應到Engine package內的PlayerInput類別。點的前面是script package的名稱,後面是類別的名稱。

第二行則是對應到PlayerInput類別的MoveForwardSpeed屬性,可以在PlayerInput.uc中找到這個屬性: