2012年11月30日 星期五

自訂預覽視窗

先前提過如何撰寫資源編輯器的主視窗,接著本篇來介紹如何撰寫預覽視窗。許多資源編輯器都有預覽視窗,例如AnimSetViewer和AnimTreeEditor。UEd提供FEditorLevelViewportClient類別方便開發者撰寫預覽畫面,以及FPreviewScene類別方便管理預覽場景,接下來說明一下幾個相關的類別。

FEditorLevelViewportClient


在一般的資源編輯器中,預覽畫面大多是繼承FEditorLevelViewportClient類別加以改寫,它代表用來看預覽畫面的一個視埠,可說是撰寫預覽視窗時的主要框架。其實它不限用於預覽,Matinee編輯器的軌道視窗也是用它寫的。FEditorLevelViewportClient類別並不包括視窗的部分,所以需要把它放進一個視窗。它以虛擬函式的方式提供輸入、繪製、更新的擴充界面。以下列出幾個主要的成員:

2012年11月27日 星期二

自訂資源編輯器

自訂新的資源時,通常也需要在UEd裡撰寫相應的編輯器。就好比AnimSet有AnimSetViewer,AnimTree有AnimTreeEditor。UEd的GUI是用wxWidgets寫的,這是一個第三方跨平台的GUI函式庫。

為了結合UE系統以及寫碼方便,UEd繼承wxWidgets的類別進行擴充。原本wxWidgets的類別前綴小寫的wx,UEd繼承後變成首字大寫的Wx,所以可以依此區分是否為原wxWidget內建的型別。

以下列出幾個撰寫編輯器主視窗時常用的類別。當然編輯器不是只有主視窗而已,只是篇幅已經太長,其他像顯示3D物件的部份就另外再寫一篇好了。

2012年10月31日 星期三

利用ini檔存放全域參數

開發專案時,有時會需要開放全域參數給美術或企劃人員設定。程式員可以把這些參數放在一個UnrealScript類別,然後建立一個物件儲存在固定的package檔裡,這其實就跟一般的Unreal資源很像。也可以把參數儲存在Unreal的ini檔裡,格式跟Windows的ini檔很像,一樣也是用section分類存放key=value設定。它也支援UnrealScript類別,一個section存放一個類別的屬性預設值設定。下表列出這三種方法的比較:

存放方式 固定路徑資源 ini檔的section方式 ini檔的屬性預設值方式
程式存取方式 載入物件後存取 呼叫存取函式 建立物件後存取
文字檔存取 不可
屬性視窗存取 不可 可,但需另外寫程式
執行時期更新 可,但需另外寫程式 可,但需另外寫程式 在遊戲中可用set指令修改

以方便性考量,建議將參數放在一個UnrealScript類別後利用ini檔儲存。這樣可以在文字檔內編輯參數,也可在遊戲執行時使用set指令修改參數。set指令的格式如下:
set <類別名稱> <屬性名稱> <數值>

2012年10月10日 星期三

在C++中存取UnrealScript物件屬性

在C++中要存取UnrealScript物件的屬性時,一般的做法是宣告此類別為原生類別,這樣在編譯UnrealScript時會自動產生對應的C++類別定義,就可讓C++認得此類別的成員。不過如果是非原生類別,難道就沒有其他方法可以存取其屬性嗎?答案是當然可以,不然用C++實作的UnrealScript虛擬機就寫不出來了。

由UnrealScript定義的類別必須繼承自Object,它在C++中的對應型別為UObject。由於Object這個名稱容易混淆,所以接下來皆以UObject稱之。每個UObject都會記得自己當初建立時的UnrealScript類別,在UnrealScript中可以用Object:Class屬性取得,在C++中可以用UObject::GetClass()函式取得。它在C++中是一個型別為UClass的物件,記錄著對應UnrealScript類別的相關資訊,可以從這裡得知這個類別包括屬性在內的所有成員。

取得屬性


以下程式碼展示如何在一個UObject中取得其所有屬性:
for( UProperty* Property = GetClass()->PropertyLink; Property; Property = Property->PropertyLinkNext )
{
    ...
}
UnrealScript屬性在C++中的對應型別稱為UProperty,它是一個基底類別,依據屬性的型別有各自的具象類別:

2012年9月26日 星期三

動態存取UnrealScript的enum

雖然對於UnrealScript來說,enum一旦編譯完是不能修改的。但對C++而言就不是這麼一回事了,畢竟UnrealScript是用C++實作出來的。

例如AudioDevice類別的ESoundClassName列舉,在uc檔裡只宣告了一個Master項目:
enum ESoundClassName
{
     Master
};
實際上編輯SoundMode時,型別為ESoundClassName的SoundClassName卻會列舉出所有的SoundClass。其實這是因為在C++中可以動態修改UnrealScript的enum。

2012年9月16日 星期日

自訂骨架控制

UE的動畫樹(AnimTree)提供動畫混合、變形混合、骨架控制三種功能。它可以讓開發者自訂節點來擴充新的功能,在此篇簡單說明一下如何自訂骨架控制節點。

骨架控制節點的基礎類別叫做SkelControlBase,其他的骨架控制節點都會直接或間接繼承自此類別。它定義數個C++虛擬函式以供子類別擴充,以下列出重要的成員:
  • GetAffectedBones(BoneIndex, SkeletalMeshComponent, OutBoneIndices):可覆寫此函式傳回要修改的骨頭之索引值。
  • CalculateNewBoneTransforms(BoneIndex, SkeletalMeshComponent, OutBoneAtoms):可覆寫此函式傳回修改後的骨頭位置和方向。傳回的陣列必須和GetAffectedBones()相對應。
  • CalculateNewBoneScales(BoneIndex, SkeletalMeshComponent, OutBoneScales):可覆寫此函式傳回修改後的骨頭縮放值。傳回的陣列必須和GetAffectedBones()相對應。
  • GetBoneScale(BoneIndex, SkeletalMeshComponent):可覆寫此函式傳回此骨架控制的骨頭縮放值。
  • TickSkelControl(DeltaSeconds, SkeletalMeshComponent):可覆寫此函式每畫面更新骨架控制節點。