2014年5月30日 星期五

自訂UnrealScript內建型別

UnrealScript跟C++一樣可以自訂struct、class、enum型別,但是如果想要增加內建型別的話,還是得修改編譯器才辦得的。雖然新增一個內建型別並不是一件簡單的事情,不過UE的程式結構寫得很系統化,很容易就可以找到要改哪些地方。本篇就來示範一下如何為UnrealScript增加一個倍精確度浮點數型別。

由於UnrealScript裡已經定義了一個名為double的struct在Object.uc如下:
struct {DOUBLE} double
{
    var native const int  A;
    var native const int  B;
};  
所以在本例中的倍精確度浮點數型別就改叫real以避免名稱衝突。當然real寫完之後其實是可以取代原來的double。這個struct只是給原生屬性佔位用的,實際上不能在UnrealScript中當成浮點數使用。

除了加入double型別外,當然還會示範如何加入基本的四則運算:
native(1111) static final operator(20) real +  ( real A, real B );
native(1112) static final operator(20) real -  ( real A, real B );
native(1113) static final operator(16) real *  ( real A, real B );
native(1114) static final operator(16) real /  ( real A, real B );
先在UnNames.h中定義待會會用到的名稱:
REGISTER_NAME( 16, DoubleProperty)
REGISTER_NAME( 17, Real) 
所有的內建型別都有對應的屬性類別,在UnType.h中定義對應double型別的UDoubleProperty類別:

2014年4月29日 星期二

使用C++實作UnrealScript也認得的原生類別

一般而言,想要使用C++實作類別給UnrealScript使用時,通常會使用UnrealScript撰寫原生類別,這樣會編譯器自動產生對應的C++類別定義,比較方便。但如果想要連一行UnrealScript都不寫,只用C++實作出UnrealScript也認得的類別,其實還是做得到的。

C++的類別可以分為POD(Plain Old Data)以及非POD。POD可以對應到UnrealScript的struct;而非POD的類別則要對應到UnrealScript的class,也就是必須繼承UObject才行。這種類別稱為固有類別(Intrinsic Class)。

固有類別比起一般的C++類別多了一些要注意的事項:
  • 必須直接或間接繼承UObject
  • 要在類別定義內使用DECLARE_CLASS_INTRINSIC巨集
  • 若有想要在UnrealScript中使用的欄位,要在成員函式StaticConstructor註冊。
  • 若有參考到UnrealScript物件的欄位,必需使用EmitObjectReference函式或AddReferencedObjects函式註冊。
  • 可在成員函式InitializeIntrinsicPropertyValues給定欄位初值。
  • 在AUTO_INITIALIZE_REGISTRANTS_XXX使用StaticClass()註冊,XXX替換成實際的Script Package名稱。

2014年3月23日 星期日

自訂瀏覽視窗

UE的內容瀏覽器(Content Browser)相信是大家最常用的功能之一,它除了列出在檔案裡的各種資源外,還有其他頁面用來列出類別或場景物件等功能。這每一頁在UE中稱為瀏覽視窗,而且開發者可以自行添加新的頁面。

瀏覽視窗的基礎類別是WxBrower,每個頁面都需要繼承自它。它的重要成員有:

  • MenuBar[wxMenuBar*]:如果有指定,切換到這頁時會出現指定的選單。UE會自動加上Docking子選單。
  • Activated():切換到這頁時會呼叫此函式。
  • Send(ECallbackEventType):這其實是FCallbackEventDevice界面的處理事件函式,WxBrower有繼承該界面並覆寫。預設是呼叫Update()。
  • Update():更新視窗。像是如果收到CALLBACK_RefreshEditor_AllBrowsers事件的話預設會呼叫這個函式。
  • IsClonable():傳回這個視窗允不允許被複製。不允許的話,Docking選單裡的Clone Browser選項會變成不能按。

2014年2月23日 星期日

改善對地形的射線追縱

Actor提供的Trace函式若打到地形,並不會傳回材質資訊而且傳回的物理材質也都是引擎的預設材質,並無參考價值。如果想要依據不同材質播放不同特效音效,就得想辦法得知擊中的材質為何。本篇文章告訴你如何修改射線追蹤傳回的材質,反映出實際擊中的材質。

為了不變更原本程式的運作,首先定義另一個Trace函式:

2014年1月31日 星期五

自訂效能記錄

在UE的命令列中輸入stat xxx可以觀看對應系統的所花費的時間,優化時可以方便初步縮小範圍,找出可能的瓶頸。這個指令其實UE也有提供擴充的功能,本篇就來看一下如何自訂效能記錄。

自訂效能記錄需要用到以下三個巨集:

  • DECLARE_STATS_GROUP(group_name, group_id):宣告效能記錄群組,當使用stat指令時需要輸入的參數即為此群組名稱。開發者使用的群組ID要大於等於STATGROUP_LicenseeFirstStatGroup所對應的數值。
  • DECLARE_CYCLE_STAT(stat_name, stat_id, group_id):宣告隸屬某個群組中的單筆效能記錄。開發者使用的記錄ID要大於等於STAT_LicenseeFirstStat所對應的數值。
  • SCOPE_CYCLE_COUNTER(stat_id):定義一個效能記錄器。把它放在想要測量的函式內即可。它會記錄一個畫面中被呼叫的次數和執行所花的時間。

範例


以下程式碼示範如何自訂效能記錄:

2013年12月26日 星期四

編輯器的復原和重做功能

UEd裡的許多編輯器有提供常見的復原(Undo)和重做(Redo)功能,例如AnimSet Editor、Matinee、PhAT等,它們其實都是透過交易(Transaction)功能實作出來的。本篇就來介紹一下如何利用交易為自訂的編輯器寫出復原和重做功能。

首先要知道交易功能是利用UObject的序列化(Serialization)實作出來的功能,概念上就是把變更前後的物件狀態儲存起來,然後復原時恢復成變更前的狀態,重做時回到變更後的狀態。所以你想要復原的狀態必需是某個UnrealScript類別的欄位。

基本上復原和重做功能就是在變更物件時順便建立一份交易資料,然後利用它復原或重做。建立交易資料的步驟如下: