總體特征
(1)大小寫不敏感。關鍵字、宏、變量名、函數名以及類名不區分大小寫;變量名可以與關鍵字同名
(2)局部變量、成員變量未初始化時,會被編譯器初始化
(3)沒有全局變量、全局函數,所有東西必須寫入類中
(4)一個uc文件中,有且只能寫一個類,且文件名與類名要一致
(5)變量和函數默認為public類型,函數默認為虛函數
(6)不支持函數重載,但支持運算符重載和缺省參數
(7)不支持異常處理,不支持模板泛型
(8)無需顯示導入外部包,uc文件可以使用當前包及之前編譯的包中定義的類型和函數
(9)沒有構造函數,沒有析構函數,通過引用計數機制進行垃圾回收
(10)沒有指針類型;數值型、bool型、名稱、字符串、枚舉、數組、結構體為值類型;類、接口為引用類型
(11)只支持一維數組
(12)沒有靜態變量,沒有union類型
(13)所有對象都從Object類單根繼承,支持接口多繼承
(14)強類型,編譯時檢查
(15)解釋執行,運行時安全
預處理
編譯命令參數
make -intermediate // 編譯腳本,並將預處理結果保存到 UDKGame\PreProcessedFiles\<package>\<class>.uc
make -debug // 定義名為debug的宏變量,啟用`logd宏函數,並編譯腳本
make -final_release // 定義名為final_release的宏,禁用`log、`logd、`warn、`assert宏函數,並編譯腳本
make -nopreprocess // 不進行預處理(關閉宏及注釋的預處理)
注:
`log(string OutputString, optional bool bRequiredCondition, optional name LogTag);
`logd(string OutputString, optional bool bRequiredCondition, optional name LogTag);
`warn(string OutputString, optional bool bRequiredCondition);
`assert(bool bCondition);
作用范圍
1. 宏的作用范圍是在文件內,意味着當前文件中的 X 行上的宏變量只能在該文件的 X+n 行中使用
2. 為了能讓工程中多個文件使用宏變量,一般是將宏變量定義在.uci文件中(如:TGDefine.uci),然后各個文件的起始處`include(TGDefine.uci)
3. 定義在工程的根目錄下的Globals.uci文件中的宏,能直接被這個包和依賴該包的包使用
注:腳本編譯程序不能監測出uci文件的修改,因此修改uci文件后可以同時修改某個uc文件以觸發所在包的編譯;或者全量編譯腳本
條件編譯
`if(`notdefined(USE_ASYNCHRONOUS_MOVE)) // ... `endif `if(`isdefined(USE_ASYNCHRONOUS_MOVE)) // ... `else // ... `endif `if(`isdefined(USE_ASYNCHRONOUS_MOVE)) // ... `else `if(`isdefined(USE_COMMAND)) // ... `else // ... `endif
宏定義、宏取消
`define USE_ASYNCHRONOUS_MOVE `define WEAPON_CONFIG config // `WEAPON_CONFIG 另外可以加上花括號,確保宏周圍的空白是有效的 如:var `{WEAPON_CONFIG} bool m_bConfigTest; `define GRAPH_INCOSIZE 8 `define LOCATION "(" $ Name $ ") `{ClassName}::" $ GetStateName() $ ":" $ GetFuncName() `define MAX(a, b) ( ((`a)<(`b))?(`b):(`a) ) `define ShowVar(expr,name) "`if(`name) `name `else `expr `endif:'" $ `expr $ "'" // ShowVar換行寫法如下 `define ShowVar(expr,name) "\ `if(`name)\ `name\ `else\ `expr\ `endif\ :'" $ `expr $ "'" `define LogWarn(cat, msg) `log("WARN:" @ `msg,,`cat) // 定義一個代理對象數組 `define DefineDelegateVariable(CallbackName) var private array<delegate<On`{CallbackName}> > On`{CallbackName}Delegates; // 增加一個代理對象到數組中 `define DefineAddDelegateHandlers(CallbackName) \ function Add`{CallbackName}Delegate(delegate<On`{CallbackName}> CallBack) \ { \ if (On`{CallbackName}Delegates.Find(Callback) == INDEX_None) \ { \ On`{CallbackName}Delegates[On`{CallbackName}Delegates.Length] = Callback; \ } \ } // 從數組中刪除指定的代理對象 `define DefineRemoveDelegateHandlers(CallbackName) \ function Clear`{CallbackName}Delegate(delegate<On`{CallbackName}> Callback) \ { \ local int RemoveIndex; \ RemoveIndex = On`{CallbackName}Delegates.Find(Callback); \ if (RemoveIndex != INDEX_None) \ { \ On`{CallbackName}Delegates.Remove(RemoveIndex, 1); \ } \ } // 取消宏定義 `undefine(INCLUDE_GAME_STATS)
文件包含
`include(TGOnlineLogicMacros.uci)
引擎定義的宏
`{Data} // 當前日期 `{Time} // 當前時間 `{GameName} // 游戲名稱 `{ClassName} // 當前類名 `{PackageName} // 當前包名
特殊宏
`define MyMacro(p1, p2, p3, p4) “This macro contains `# parameters.”// `#為4,為宏參數的個數
常量
作用范圍
1. 常量在運行時不可改變,可以定義在類中、成員函數內、狀態塊內,但編譯器會將其統一調整到類中;好的編碼習慣是將常量定義在類的起始處。
2. 定義在結構體中的常量將只能在結構體中使用,外部無法訪問。
3. 當前類中定義的常量可直接訪問:PI;訪問外部類TGTest中定義的常量:class'TGTest'.const.PI 注:TGTest類的工程編譯需在使用該常量的工程之前或同處一個工程
4. 對於公共常量,一般會將這些常量集中寫入到一個單獨的.uci文件中(如:TGConst.uci),然后類的起始處`include(TGConst.uci)
舉例
const a = 10; // 十進制 a=10 const b = 0x10; // 十六進制 轉成十進制為:b=16 const c = 010x; // 八進制 轉成十進制為:c=8 const d = true; const f = 3.14; const s = "Hello World!"; // 字符串需加上雙引號 const n = 'James'; // name需加上單引號 const o = none; // 空對象 相當於C/C++中的NULL const oc = class'UTGame.UTPawn'; // 類模板(引號中不能有空格) class<UTPawn> const oc2 = class'UTBot'; // 類模板(引號中不能有空格) class<UTBot> const or = Texture2D'EngineResources.DefaultTexture';//紋理對象(引號中不能有空格) const v = vect (1.2, 3.4 , 5.6); // vector常量 const r = rot(1234, 5678 , 9012); // rotator常量
Object類中的常量
const MaxInt = 0x7fffffff; const Pi = 3.1415926535897932; const RadToDeg = 57.295779513082321600; // 180 / Pi const DegToRad = 0.017453292519943296; // Pi / 180 const UnrRotToRad = 0.00009587379924285; // Pi / 32768 const RadToUnrRot = 10430.3783504704527; // 32768 / Pi const DegToUnrRot = 182.0444; const UnrRotToDeg = 0.00549316540360483; const INDEX_NONE = -1; // Aspect ratio constants const AspectRatio4x3 = 1.33333; const AspectRatio5x4 = 1.25; const AspectRatio16x9 = 1.77778; const InvAspectRatio4x3 = 0.75; const InvAspectRatio5x4 = 0.8; const InvAspectRatio16x9 = 0.56249;
變量
更多類型說明請參見:https://wiki.beyondunreal.com/Types
unreal texture:http://www.unrealtexture.com/Unreal/Downloads/3DEditing/UnrealEd/Tutorials/unrealwiki-offline/variable-type.html
unrealscript DefaultProperties:中文 en
數值型
類型 | 長度 | 范圍 | 舉例 |
byte |
8位無符號整型 | [0, 255] | 十進制:2 八進制:012x 十六進制:0xFF |
int | 32位整型 | [-2^31, 2^31-1] | 十進制:-500 八進制:018000x 十六進制:0x12FC |
float | 32位浮點(單精度) | [-3.403e+38, 3.403e+38] 有效精度:6-7位有效數字 |
-3.25 5.0f 0.35 10. .58(不支持省略0的寫法,編譯失敗) 1.23E2(不支持科學計數法,編譯失敗) 1.0/0.0=1.#INF00(比任何浮點數都大) -1.0/0.0=-1.#INF00(比任何浮點數都小) |
數值型間轉換規則
1. 自動隱式轉換
2. 精度高向精度低轉換:
(a) 內存截斷 (b) 精度丟失
類的缺省變量
simulated function float GetRange(Pawn P) { if (default.LifeSpan == 0.0)//訪問當前類的缺省變量LifeSpan { return 15000.0; } if (P.Default.JumpZ > 1000)//訪問對象P所在類的缺省變量JumpZ { return 20000.0; } if (class'Pawn'.Default.MaxStepHeight > 100)//訪問Pawn類的缺省變量MaxStepHeight { return 25000.0; } return 10000.0; }
>>>補零右移運算符
local int a, b; a = -1; // 0xFFFF FFFF b = a>>2; // b=0xFFFF FFFF=-1 b = a>>>2; // b=0x3FFF FFFF=1073741823
float ~= 約等於符號
local float f; local bool b; f = 0.00001; b = (f~=0); // b=true 等價於 abs(f)<0.0001
float ** 冪函數符號
local float f1, f2, f3; f1 = 3.0; f2 = 2.0; f3 = f1**f2;//f3=9 3的2次冪
float極大值、極小值 、NaN
local bool b1; local float f1, f2; f2 = 0.0; f1 = 1.0 / f2; // 1.#INF00 b1 = IsNan(f1);//false b1 = (f1==f1);//true if (f1 > 1000000000)//true { `log("f1為極大值"); } if (f1 < -1000000000)//false { `log("f1為極小值"); } f1 = -1.0 / f2;// -1.#INF00 b1 = IsNan(f1);//false b1 = (f1==f1);//true if (f1 > 1000000000)//false { `log("f1為極大值"); } if (f1 < -1000000000)//true { `log("f1為極小值"); } f1 = f2/f2;//-1.#IND00 b1 = IsNan(f1);//true b1 = (f1==f1);//false f1 = -f2/f2;//-1.#IND00 b1 = IsNan(f1);//true b1 = (f1==f1);//false
bool
(1)bool型只能為True或False
(2)bool型與數值型間不支持隱式轉換
local int a; local bool b; a = 10; b = a; // 編譯錯誤 b = bool(a); // b=true a = b; // 編譯錯誤 a = int(b); // a=1
(3)^^ 異或
local bool b1, b2, b3; b1 = true; b2 = false; b3 = b1^^b2; // b3=true b1 = true; b2 = true; b3 = b1^^b2; // b3=false
name
(1)name字符:“a..z”、“A...Z”、"0...9"、“_”、“-”、空格,最大允許長度為1023字符
如: 'Nico Chen' '123' '' '#逆戰@123' name ("#逆戰@123")
(2)name不區分大小寫 'nico' 和 'Nico'是相等的
(3)name在函數中用單引號包含,defaultproperties塊中無需包含或使用雙引號包含
defaultproperties { m_name1='Hello'//Warning, Invalid property value m_name1='' m_name2=Hello_123//m_name2='Hello_123' m_name3=Hello World//m_name3='Hello' m_name4=Hello#World//m_name4='Hello' m_name5="Hello World!"//m_name5='Hello World!' m_name5=Hello// Warning, redundant data m_name5仍然為'Hello World!' }
(4)通過NameOf()偽函數在編譯時,將變量名和函數名轉換成name
(5)name只能強制轉換成string,不能轉換成其他類型;同時string可以強制轉換成name
(6)可以修改name,但無法修改name的內容
(7)name只支持兩種比較運算符:==、!=
string
(1)string中的字符為16位unicode,最大允許長度為1023字符
如: "NicoChen" "Hello World!\n" "" "逆戰"
(2)string區分大小寫 "nico"和 "Nico"是不相等的
(3)可以修改string,但無法修改string的內容
(4)string在函數中用雙引號包含,defaultproperties塊中無需包含或使用雙引號包含
defaultproperties { m_string1='Hello'//Warning, Invalid property value m_string1="" m_string2=Hello_123//Warning, Missing " m_string2="Hello_123" m_string3=Hello World//Warning, Missing " m_string3="Hello" m_string4=Hello#World//Warning, Missing " m_string4="Hello#World" m_string5="Hello World!"//m_string5='Hello World!' m_string5=Hello// Warning, redundant data m_string5仍然為'Hello World!' }
(5)除了數組與結構體外,其他類型都可強制轉成string
local string s; // 其他類型轉成字符串 s = string(''); // s="" s = string('James'); // s="James" s = string(50); // s="50" s = string(-1234); // s="-1234" s = string(-13.89); // 保留6位有效數字 s="-13.8900" s = string(true); // s="True" s = string(false); // s="False" s = string(ENetRole.ROLE_Authority); //s="3" s = string(GetEnum(Enum'ENetRole', ENetRole.ROLE_Authority)); //s="ROLE_Authority" s = string(self); //代碼位於MyPawn類中,s="MyPawn_1" s = string(none); //s="None"
(6)string可強制轉成數值型、bool和name
local name m; local bool b; local byte n; local int a; local float f; // 字符串轉成name m = name("test"); // m='test' m = name("Hello World!"); // m='Hello World!' // 字符串:整型 b = bool("-1"); // b=true a = int("-1"); // a=-1 n = byte("-1"); // n=255 f = float("-1");// f=-1.000000 // 字符串:浮點數 b = bool("-300.23"); // b=true a = int("-300.23"); // a=-300 n = byte("-300.23"); // n=byte(-300)=212 f = float("-300.23");// f=-300.230011 // 字符串:布爾值 b = bool("True"); // b=true a = int("True"); // a=0 n = byte("True"); // n=0 f = float("True");// f=0.000000 // 字符串:起始為數字子串 b = bool("210fAlse300"); // b=true a = int("210fAlse300"); // a=210 n = byte("210fAlse300"); // n=210 f = float("210fAlse300"); // f=210.000000 // 字符串:起始不為數字子串 b = bool("True335Test"); // b=false a = int("True335Test"); // a=0 n = byte("True335Test"); // n=0 f = float("True335Test"); // f=0.000000
(7)string支持所有的比較運算符 >、>=、<、<=、==、!=、~=
(8)string特有連接運算符 @ $ @= $= 注:@ 、$會將其左右操作數執行coerce轉換成string類型;@= 、$=會將右操作數執行coerce轉換成string類型
(9)string特有運算符 -= 注:-=會將右操作數執行coerce轉換成string類型;a -= b等價於a = Repl(a, b, "", false)
local bool b1; local string s1; // string操作符 s1 = "Hello"$"World"; // "HelloWorld" s1 = "Hello"@"World"; // "Hello World" s1 = "Hello"; s1 $= "World"; // "HelloWorld" s1 = "Hello"; s1 @= "World"; // "Hello World" //s1 = "Hello"+"World"; // 編譯錯誤 //s1 += "World"; // 編譯錯誤 s1 = "Hello WOrld"; s1 -= "o"; // 去掉子串中所有的小寫字母o(大小寫敏感) s1="Hell WOrld" b1 = "Hello"<"World"; // 大寫字母<小寫字母 b1=true b1 = "Hello">"hello"; // 大寫字母<小寫字母 b1=false b1 = "Hello"!="hello"; // 大小寫敏感 b1=true b1 = "Hello"~="hello"; // 大小寫敏感 b1=true b1 = "Hello"=="Hello"; // b1=true b1 = "Hello"<="Hello"; // b1=true b1 = "Hello">="Hello"; // b1=true b1 = "Hello"!="Hello"; // b1=false b1 = "Hello"~="Hello"; // b1=true
(10)string函數
local int a1; local array<string> v1, v2, v3, v4; local string s1; // Object函數 a1 = Len("Hello"); // a1=5 a1 = Instr("THIS is my book!", "is"); // 返回第1個is的位置(大小寫敏感) a1=5 s1 = Mid("Hello", 0, 2); // 返回從0索引開始后2個長度的子串 s1="He" s1 = Mid("Hello", 2); // 返回從2索引開始到結尾長度的子串 s1="llo"; s1 = Left("World", 2); // s1="Wo" s1 = Right("Hello", 4); // s1="ello" s1 = Caps("Hello"); // 返回字符串的大寫版本 s1="HELLO" s1 = Locs("World"); // 返回字符串的大寫版本 s1="world" s1 = Chr(97); // 返回給定int的字符串表示形式(可以是Unicode:0-65535內的任何值)s1="a" a1 = Asc("Hello"); // 返回字符串第一個字母的Unicode數值 a1=72 // 將"This is a test"中的"is"替換成"was" 大小寫不敏感 s1="THwas was a test" s1 = Repl("THIS is a test", "is", "was"); // 將"Two be or not two be"中的"two"替換成"to" 大小寫敏感 s1="Two be or not to be" s1 = Repl("Two be or not two be", "two", "to", true); // 將"Two be or not two be"中的"two"替換成"to" 大小寫不敏感 s1="to be or not to be" s1 = Repl("Two be or not two be", "two", "to", false); // 返回從第1次出現"is"(大小寫敏感)到結尾的子串(含is) s1="is is a test" s1 = Split("This is a test", "is", false); // 返回從第1次出現"is"(大小寫敏感)到結尾的子串(不含is) s1="a test" s1 = Split("THIS is a test", "is", true); // 返回"Test_45_50_me20"最右邊"_"后的子串 s1="me20" s1 = GetRightMost("Test_45_50_me20"); v1[0] = "Hello "; v1[1] = ""; v1[2] = "World"; // 使用#連接數值v1中的各個元素(空串不跳過) s1="Hello ##World" JoinArray(v1, s1, "#", false); // 使用#連接數值v1中的各個元素(空串跳過) s1="Hello #World" JoinArray(v1, s1, "#", true); // 使用"M"分隔字符串(大小寫敏感),並將結果保存到數組v2中(空串不跳過) ParseStringIntoArray("HelloMMmWorld", v2, "M", false);//v2[0]="Hello" v2[1]="" v2[2]="mWorld" // 使用"M"分隔字符串(大小寫敏感),並將結果返回到數組v2中(空串不跳過) v2 = SplitString("HelloMMmWorld", "M", false); //v2[0]="Hello" v2[1]="" v2[2]="mWorld" // 使用"M"分隔字符串(大小寫敏感),並將結果保存到參數數組v2中(空串跳過) ParseStringIntoArray("HelloMMmWorld", v3, "M", true);//v3[0]="Hello" v3[1]="mWorld" // 使用"M"分隔字符串(大小寫敏感),並將結果返回到數組v2中(空串跳過) v3 = SplitString("HelloMMmWorld", "M", true); //v3[0]="Hello" v3[1]="mWorld" // Actor函數 s1 = "This is a test"; // 等價於:s1=Repl(s1, "is", "was", true); 將字符串中的"is"替換成"was" 大小寫敏感 s1為輸出參數 ReplaceText(s1, "is", "was"); // 返回s1="Thwas was a test" s1 = "Two be or not two be"; // 等價於:s1=Repl(s1, "two", "to", true); 將字符串中的"two"替換成"to" 大小寫敏感 s1為輸出參數 ReplaceText(s1, "two", "to"); // 返回s1="Two be or not to be" // 等價於:v4=SplitString("www.qq.com", ".", true);s1=v4[v4.Length-1]; s1="com" s1 = GetItemName("www.qq.com");
enum
(1)枚舉只能在類中定義,不能在函數中定義 如:ENetRole
// Net variables. enum ENetRole { ROLE_None, // No role at all. ROLE_SimulatedProxy, // Locally simulated proxy of this actor. ROLE_AutonomousProxy, // Locally autonomous proxy of this actor. ROLE_Authority, // Authoritative control over the actor. }; var enum ENetMode { NM_Standalone, // Standalone game. NM_DedicatedServer, // Dedicated server, no local client. NM_ListenServer, // Listen server. NM_Client // Client only, no local server. } NetMode;
(2)枚舉第一個元素的值為0,后續依次+1;不能隨意地指定新的起始值
(3)enum內部為一個byte類型,其支持最大的枚舉值為255
(4)在defaultproperties中對枚舉成員變量初始化時,不能帶枚舉類型前綴,否則會失效
(5)枚舉類型(等於枚舉元素的個數)、類型.前綴_MAX、類型.EnumCount及類型.枚舉元素(一定要帶上類型)可作為靜態數組的大小
local int a1[ENetRole]; // 等價於a1[4] local int a2[ENetRole.EnumCount]; // 等價於a2[4] local int a3[ENetRole.ROLE_MAX]; // 前綴_MAX 等價於a3[4] local int a4[ENetRole.ROLE_Authority]; // 等價於a4[3]
(6)整型與enum之間支持隱式轉換
local byte a; local ENetRole nr; nr = 3; // nr=ROLE_Authority nr = -1; // nr=INVALIDE nr = 10; // nr=INVALIDE a = ENetRole.ROLE_SimulatedProxy; // a=1
(7)使用GetEnum函數將enum轉換成name
local name m; m = GetEnum(Enum'ENetRole', ENetRole.ROLE_Authority); // m='ROLE_Authority'
(8)枚舉定義所在工程編譯需在使用該枚舉的工程之前或【同處一個工程且使用該枚舉所在類名按字母升序比枚舉定義所在類名靠后】
如果一個枚舉在當前工程中廣泛地使用,需要打破類名按字母升序的限制,可以將該枚舉定義在一個單獨從Object派生的類中(如:TGType)
若使用該枚舉所在的類名按字母升序較靠前,可以使用dependson(TGType)來解決編譯找到類型問題
(9)枚舉類型定義采取的是覆蓋規則:若包加載序列為:ABC,A中定義了枚舉類型EType,B中也定義了該類型,則C包中則會使用B中定義的枚舉類型
靜態數組
(1)不支持size為1的靜態數組定義 local int a[1];
(2)不支持bool型靜態數組定義 local bool b[5];
(3)不支持多維靜態數組 local int a[2][2];
(4)無法修改靜態數組的值,但可以修改靜態數組的內容 如:b=a; // 編譯錯誤
(5)越界訪問情況,不會導致崩潰
local int a[5]; a[6] = 8; // a[4]=8 a[-1] = 2; // a[0]=2 a[1] = a[-1]; // a[1]=2
(6)通過ArrayCount()偽函數在編譯時,得到靜態數組大小
(7)靜態數組元素訪問在函數中用[],defaultproperties塊中用()或[]均可
var int m_sa1[5]; defaultproperties { m_sa1(-1)=2 // m_sa1(0)仍然為0 m_sa1(0)=3 // m_sa1(0)=3 m_sa1(3)=1 m_sa1(3)=5 // Warning, redundant data m_sa1(3)仍然為1 m_sa1(6)=8 // Warning, Out of bound array m_sa1(4)仍然為0 }
(8)靜態數組作為函數參數
simulated function Test() { local int xx[3]; StaticArrayTest(xx); } function StaticArrayTest(int a[3]) { a[0] = 5; a[1] = 12; a[2] = 20; }
(9)靜態數組不能作為函數返回值
動態數組
(1)可以定義bool類型的動態數組
(2)動態數組既可以作為函數參數,也可以作為函數返回值
(3)避免寫>>,否則編譯不過 local Array<class<Actor>>; local Array<delegate<OnFailed>>
(4)不支持動態數組嵌套 local Array<Array<int> > vva;
(5)既可以修改動態數組的值,又可以修改動態數組的內容
(6)函數中通過Length字段,獲取動態數組size(defaultproperties塊中不能訪問Length)
(7)函數中修改Length字段,調整動態數組size
local array<int> va; va.Length = 5; // va size=5: 0 0 0 0 0 va.Length = 0; // va size=0 va.Length = va.Length+3; // va size=3: 0 0 0 va.Length = -1; // va size=-1 //va.Length += 1; // 編譯出錯 不能對Length進行+=運算 //va.Length -= 1; // 編譯出錯 不能對Length進行-=運算 //va.Length++; // 編譯出錯 不能對Length進行后自增運算 //va.Length--; // 編譯出錯 不能對Length進行后自減運算 //--va.Length; // 編譯出錯 不能對Length進行前自減運算 //++va.Length; // 編譯出錯 不能對Length進行前自增運算 // function ChangeArrayLength(out int x){x=10;} //ChangeArrayLength(va.Length); // ChangeArrayLength中修改va.Length,會導致內存泄露和崩潰
(8)動態數組元素訪問在函數中用[],defaultproperties塊中用()或[]均可
(9)函數中使用索引修改元素的值時,若索引>=Length,將引發動態數組size增長
local array<int> va; local array<color> vb; local color c; va[2] = 10; // va size=3: 0 0 10 va[-1] = 5; // 無效語句 va size=3: 0 0 10 va[1] = 3; // va size=3: 0 3 10 va[2] = va[5]+8; // va size=3: 0 3 8 vb[1].R = 255; // vb size=0 注:不會引發size增長 c.G = 128; vb[2] = c; // vb size=3 [r=0 g=0 b=0 a=0] [r=0 g=0 b=0 a=0] [r=0 g=128 b=0 a=0]
(10)動態數組在defaultproperties中初始化
var Array<int> m_da1, m_da2; defaultproperties { m_da1[0]=2 // m_da1:2 m_da1(-1)=3 // Warning, Invalid property value m_da1:2 m_da1(1)=5 // m_da1:2 5 m_da1(1)=10 // Warning, redundant data m_da1:2 5 m_da1(3)=7 // m_da1:2 5 0 7 m_da2(4) = 10 //m_da2: 0 0 0 0 10 m_da2 = (1,,3) //m_da2: 1 0 3 m_da2 = () // Warning, redundant data m_da2: 1 0 3 m_da2(1) = 5 // m_da2: 1 5 3 m_da2(4) = 8 // Warning, redundant data m_da2: 1 5 3 }
(11)函數中清空動態數組
va.Length = 0;
(12)defaultproperties中清空動態數組
defaultproperties
{
m_da1.Empty
}
(13)使用函數來修改動態數組size,追加、刪除、插入元素到動態數組中
local array<int> va; va.AddItem(1); // 末尾增加值為1的元素 size=1 a: 1 va.Add(3); // 末尾擴充3個元素 size=4 a: 1 0 0 0 va.Insert(2, 2); // 在索引為2處插入2個元素 size=6 a: 1 0 0 0 0 0 va.Remove(1, 3); // 從索引為1處起刪除3個元素 size=3 a: 1 0 0 va.AddItem(5); // 末尾增加值為5的元素 size=4 a: 1 0 0 5 va.RemoveItem(0); // 刪除所有為0的元素 size=2 a: 1 5 va.InsertItem(1, 7); // 在索引為1處插入值為7的元素 size=3 a: 1 7 5
(14)defaultproperties中使用函數來追加、刪除元素
var Array<int> m_da1; defaultproperties { m_da1.Add(1) // 末尾增加元素為1的元素 size=1 m_da1: 1 m_da1.Add(2) // 末尾增加元素為2的元素 size=2 m_da1: 1 2 m_da1.Add(5) // 末尾增加元素為5的元素 size=3 m_da1: 1 2 5 m_da1.Add(2) // 末尾增加元素為2的元素 size=4 m_da1: 1 2 5 2 m_da1.Remove(5) // 刪除所有值為5的元素 size=3 m_da1: 1 2 2 m_da1.RemoveIndex(1) // 刪除索引值為1的元素 size=2 m_da1: 1 2 }
(15)元素查找
local int n; local Rotator r; local Object o1, o2; local array<int> va; local array<Rotator> vr; local array<Object> vo; va[0]=1; va[1]=2; va[2]=6; va[3]=2; n = va.Find(2); // n=1 第1個為2的元素的索引值為1 n = va.Find(3); // n=INDEX_NONE(即:-1) 未找到為3的元素 r.Pitch=1000; r.Roll=2000; r.Yaw=3000; vr.AddItem(r); r.Pitch=4000; r.Roll=5000; r.Yaw=6000; vr.AddItem(r); n = vr.Find('Pitch', 4000); // n=1 第1個Pitch=4000的元素的索引值為1 n = vr.Find('Roll', 500); // n=-1 未找到Roll=500的元素 n = vr.Find('Yaw', 3000); // n=0 第1個Yaw=3000的元素的索引值為0 o1 = new(self) class'ObjectEx'; vo.AddItem(o1); o2 = new(self) class'ObjectEx'; vo.AddItem(o2); n = vo.Find(o2); // n=1 第1個為o2的元素的索引值為1
(16)元素排序
// 返回值<0,則交換a和b;否則不交換 delegate int IntSortAscDelegate(int a, int b) { if (a <= b) // 等於情況,一定不要交換,否則會死循環 return 0; // 不進行交換 return -1; // 進行交換 } simulated function DynamicArrayTest5() { local array<int> va; va[0] = 8; va[1] = 6; va[2] = 0; va[3] = 5; va[4] = 9; va[5] = 3; va[6] = 2; va[7] = 6; va.Sort(IntSortAscDelegate); // va: 0 2 3 5 6 6 8 9 }
(17)元素遍歷
local int i, n, s1, s2, s3; local array<int> va; va[0] = 8; va[1] = 6; va[2] = 0; va[3] = 5; va[4] = 9; va[5] = 3; va[6] = 2; va[7] = 6; foreach va(n, i) { s1 += i; // s1=0+1+2+3+4+5+6+7=28 } foreach va(n) { s2 += n; // s2=8+6+0+5+9+3+2+6=39 } for(i=0; i<va.Length; i++) { s3 += va[i]; // s3=8+6+0+5+9+3+2+6=39 }
(18)靜態數組與動態數組拷貝比較
local int i; local int a[3], ac[3]; local Array<int> va, vac; a[0] = 2; a[1] = 5; // a: 2 5 // ac = a; // 編譯失敗,靜態數組不能通過賦值方式拷貝 // 循環拷貝靜態數組a中的值到ac中 for (i=0; i<ArrayCount(a); i++) { ac[i] = a[i]; } va.AddItem(2); va.AddItem(5); vac = va; // 拷貝動態數組 vac: 2 5
struct
(1)結構體中可以存放常量和任意類型變量(小心避免直接或間接包含自身類型的變量,會引起編譯崩潰 如下:)
struct STRTest { var STRTest c; };
(2)結構體中不能有函數方法,成員的初始化放在structdefaultproperties塊中
(3)結構體只能在類中定義
struct Student { var string sname; var int age; var float height; var byte scores[3]; var Array<int> history; var Color clr; structdefaultproperties // 初始化變量的默認值 { sname = "James" age = 20 height = 1.83 scores(0)=87.5 scores(1)=96.5 history=(95,100,88) clr= (r=255,g=32,b=128,a=0) } };
(4)支持結構體繼承
// A point or direction vector in 3d space. struct immutable Vector { var() float X, Y, Z; }; // A plane definition in 3d space. struct immutable Plane extends Vector { var() float W; };
(5)函數中對進行結構體賦值和拷貝
local Student s1, s2; s1.sname = "Tom"; s1.age = 30; s1.height = 1.90; s1.clr.r = 255; s2 = s1; // 結構體賦值 s2.sname = "Jack"; // 結構體為值類型 s1.sname仍然為"Tom"
(6)在類的defaultproperties塊中對結構體成員變量進行初始化
var Student m_student1, m_student2; defaultproperties { m_student1 = (sname="Lucy",age=8,height=1.77, clr=(r=200,b=150)) m_student2 = {( sname="Lily", age=10, height=1.68, clr=(r=200,b=150), scores[0]=80,scores[1]=90,scores[2]=85, history=(100,120,150,180,200) )} }
(7)支持==與!=比較(兩個結構體內容完全一致則相等,否則不相等)
(8)結構體定義所在工程編譯需在使用該結構體的工程之前或【同處一個工程且使用該結構體所在類名按字母升序比結構體定義所在類名靠后】
如果一個結構體在當前工程中廣泛地使用,需要打破類名按字母升序的限制,可以將該結構體定義在一個單獨從Object派生的類中(如:TGType)
若使用該結構體所在的類名按字母升序較靠前,可以使用dependson(TGType)來解決編譯找到類型問題
(9)結構體類型定義采取的是覆蓋規則:若包加載序列為:ABC,A中定義了結構體類型FlyInfo,B中也定義了該類型,則C包中則會使用B中定義的結構體類型
修飾符
關鍵字 |
說明 |
immutable | 使用c++來進行二進制序列化,可以減少空間占用和提升性能 在這樣的結構體中增刪成員變量會引發序列化問題 struct immutable Vector |
immutablewhencooked | 在使用cook包時,啟用immutable特性 |
native | native結構體,會導出到.h中 struct native KeyBind /** if true, the bind will not be activated if the corresponding key is held down */ structcpptext |
{XXX} | 在導出的c++中類型名為XXX struct {QWORD} qword // qword在c++中類型為QWORD struct {WxRect} ViewportDimension // ViewportDimension在c++中類型為WxRect struct {FNavMeshEdgeBase*} EdgePointer // EdgePointer在c++中類型為FNavMeshEdgeBase* |
注1:結構體其他修飾符請參考后文中類修飾符對應關鍵字
注2:結構體成員的修飾符請參考后文中類成員修飾符對應關鍵字
結構體更多信息請參見:
常用結構體 -- vector
運算符
(1)向量與向量 加減乘 + - * += -= *=
local vector v1, v2, v3; v1.x = 1.0; v1.y = 2.0; v1.z = 3.0; v2.x = 1.0; v2.y = 5.0; v2.z = 2.0; v3 = v1 + v2; // v3.x=2.0 v3.y=7.0 v3.z=5.0 v3 = v1 - v2; // v3.x=0.0 v3.y=-3.0 v3.z=1.0 v3 = v1 * v2; // v3.x=1.0 v3.y=10.0 v3.z=6.0 //v3 = v1 / v2; // 編譯失敗 沒有除法 v3 = v1; v3 += v2; // v3.x=2.0 v3.y=7.0 v3.z=5.0 v3 = v1; v3 -= v2; // v3.x=0.0 v3.y=-3.0 v3.z=1.0 v3 = v1; v3 *= v2; // v3.x=1.0 v3.y=10.0 v3.z=6.0 //v3 = v1; v3 /= v2; // 編譯失敗 沒有除法
(2)向量比較運算符 == !=
(3)- 負號運算符
local vector v1, v2; v1.x = 1.0; v1.y = 2.0; v1.z = 3.0; v2 = -v1; // v2.x=-1.0 v2.y=-2.0 v2.z=-3.0
(4)縮放
local vector v1, v2; v1.x = 1.0; v1.y = 2.0; v1.z = 3.0; v2 = 2.0*v1; // v2.x=2.0 v2.y=4.0 v2.z=6.0 v2 = v1*2.0; // v2.x=2.0 v2.y=4.0 v2.z=6.0 v2 *= 2.0; // v2.x=4.0 v2.y=8.0 v2.z=12.0 v2 /= 2.0; // v2.x=2.0 v2.y=4.0 v2.z=6.0 v2 = v1/2.0; // v2.x=0.5 v2.y=1.0 v2.z=1.5
(5)dot 點乘
local vector v1, v2, v3; local int n; v1.x = 1.0; v1.y = 2.0; v1.z = 3.0; v2.x = 0.0; v2.y = 5.0; v2.z = 2.0; n = v1 dot v2; // n=v1.x*v2.x+v1.y+v2.y+v1.z*v2.z=16.0
(6)cross 叉乘
local vector v1, v2, v3; v1.x = 1.0; v1.y = 2.0; v1.z = 3.0; v2.x = 0.0; v2.y = 5.0; v2.z = 2.0; v3 = v1 cross v2; // v3.x=v1.y*v2.z-v1.z*v2.y= -11.0 // v3.y=v1.z*v2.x-v1.x*v2.z= -2.0 // v3.x=v1.x*v2.y-v1.y*v2.x= 5.0
(7)旋轉 << >>
local vector v1, v2; local rotator r1; v1.y = 1.0; r1.yaw = 65536/4; // 方位角 0-360分擔到0-65536上 90 左手坐標系 v2 = v1 >> r1; // 正向旋轉 v2.x=-1.0 v2 = v1 << r1; // 反向旋轉 v2.x=1.0
(8)與string進行類型轉換
local vector v; local string s; v = vect(1.23456,2.12,3.5688);//v=(1.234560,2.120000,3.568800) s = string(v);//s="1.23,2.12,3.57" 四舍五入,保留小數點后兩位 s = "-3.7856235,,20,15.688"; v = vector(s);//v=(-3.785624,0.000000,20.000000)//按逗號進行分割,每個子塊按照string轉float規則進行轉換
函數
(1)長度 VSize(v) VSize2D(v)
(2)長度的平方 VSizeSq(v) VSizeSq2D(v)
(3)單位化 Normal(v)
(4)隨機向量 v=VRand()
(5)是否為0向量 IsZero(v)
(6)忽略z的點乘 NoZDot(v1, v2)
常用結構體 -- rotator
pitch (think nodding to say "yes") 俯仰角 繞-y軸 -->可通過下列公式:(65536+pitch%65536)%65536歸一化到[0,65535]
yaw(shaking your head to say "no") 方位角 繞+z軸 -->可通過下列公式:(65536+yaw%65536)%65536歸一化到[0,65535]
roll (tilting your head sideways while looking in a specific direction) 橫滾角 繞-x軸 -->可通過下列公式:(65536+roll%65536)%65536歸一化到[0,65535]
范圍: [0,360)-> [0, 65536) 公式:y = 360.0*x/65536 注:y為度數,x為pitch、yaw或roll
(1)與string進行類型轉換
local rotator r; local string s; r.Pitch = 65536/16;//r1 [Pitch=4096 yaw=0 roll=0] r.yaw = 65536/8;//r1 [Pitch=4096 yaw=16384 roll=0] s = string(r);//s="4096,16384,0" s = "-21.36,70000,65535,100"; r = rotator(s);//[Pitch=-21 yaw=70000 roll=65535] //按逗號進行分割,每個字塊按照string轉int規則進行轉換
(2)運算符
a. rotator與rotator加減 + - += -=
b. rotator比較運算符 == !=
c. 縮放
(3)函數
a. 長度 RSize(r)
b. 求夾角(單位:度 范圍:[0, 180]) RDiff(r1, r2)
控制語句
(1)循環語句
local int i, n, s; local array<int> va; local Controller C; for (i=0; i<=100; ++i) // i<=100 條件為false時,退出循環 { s += i; } //for (i=0,s=0; i<=100; ++i,s+=2) // i=0,s=0 和 ++i,s+=2編譯不過,腳本不支持逗號表達式 //{ //} i = 0; s = 0; while (i<=100) // i<=100 條件為false時,退出循環 { s += i; i++; } i = 0; s = 0; do { s += i; i++; } until(i>100);// i>100 條件為true時,退出循環 // foreach 數組 va[0] = 2; va[1] = 5; va[2] = 3; va[3] = 6; va[4] = 9; i = 0; s = 0; foreach va(n, i) { s += i; // s=0+1+2+3+4=10 } s = 0; foreach va(n) { s += n; // s=2+5+3+6+9=25 } // foreach 迭代器函數 //native final iterator function AllControllers(class<Controller> BaseClass, out Controller C); 注:第2個參數C必須為第1個參數指定的類型,不能為其基類或派生類 foreach WorldInfo.AllControllers(class'Controller', C) { }
(2)goto語句
// 函數中使用goto語句 goto labelname; function GotoTest() { Label1: local name n; local int s; n = 'Label1'; if (s >= 2) { //goto ('Label3'); // 編譯出錯 goto 'Label3'; } s = 1; Label2: s = 2; //goto (Label1); // 編譯出錯 //goto (n); // 編譯出錯 函數中goto的Label不能使用變量 goto Label1; Label3: s = 3; //goto Unknown; // 編譯出錯 函數中找不到名為Unknown的標簽 } // 狀態中使用goto語句 goto expression; state State1 { function name SelectLabel(int Index) { switch (Index) { case 1: return 'Label1'; case 2: return 'Label2'; case 3: return 'Label3'; } return 'Unknown'; } Begin:// State默認進入的Label goto SelectLabel(2); Label1: goto ( SelectLabel(3) ); Label2: LabelName = SelectLabel(1); // LabelName為成員變量 goto LabelName; Label3: //goto Unknown; // 編譯不過 goto 'Unknown'; // 未定義Label,后續的代碼將被忽略 LabelName = 'State1'; // 不會得到執行 }
a. foreach循環中的使用goto只允許跳轉到當前foreach作用范圍的Lable上,不能跳轉到內部嵌套的foreach循環或者foreach外部的Label上;
也就是說每個foreach的作用范圍都是獨立的黑盒(Lable對外不可見),只能在其內部使用goto,不能跨層使用。
b. 其他循環類型及條件語句的作用范圍為整個函數,沒有這樣的限制
類
① 動態地加載某個類模板,並創建出一個實例
local class<actor> NewClass; NewClass = class<actor>( DynamicLoadObject( "UTGameContent.UTVehicle_Hoverboard_Content", class'Class' ) ); if( NewClass!=None ) { Spawn( NewClass,,,Vect(100,0,0) ); }
注:當包未打開時,首先會調用LoadPackage打開該包;該物體有指向外部包的引用時,若外部包未打開,則調用LoadPackage打開外部包並用DynamicLoadObject來加載引用指向的物體(這是一個遞歸過程)
② 在c++中,通過Cast模板函數進行類型轉換
APawn* Instigator; // 若Instigator不為空且為一個ATGPawn實例,則轉換成功,否則返回空 ATGPawn* tPawn = Cast<ATGPawn>(Instigator);
缺省屬性
var class<GameReplicationInfo> GameReplicationInfoClass; var class<LocalMessage> DeathMessageClass; var TGComDamageZone BodyDamageZoneTemplate; var ParticleSystem MuzzleFlashPSCTemplate; var const LightComponent LightComponent; var instanced ParticleSystemComponent PoweredUpEffect; defaultproperties { GameReplicationInfoClass=class'UTGame.UTGameReplicationInfo'//類型與當前類不在同一個包時,必須帶上包名前綴 DeathMessageClass=class'UTDeathMessage' //類型與當前類在同一個包時,可省略包名前綴 // 從Actor生成出來的Archetype資源 被引擎管理 當前類被加載時,BodyDamageZoneTemplate指向的資源也會被加載到內存 BodyDamageZoneTemplate=TGComDamageZone'WP_LinkGun.DamageZone.TGComDamageZone_Body' //MuzzleFlashPSCTemplate指向的資源為模板類型 被引擎管理 當前類被加載時,MuzzleFlashPSCTemplate指向的資源也會被加載到內存 //當前類被卸載時,MuzzleFlashPSCTemplate指向的資源的引用會-1,當該資源沒任何對象引用時,會被GC自動回收 //由於native包會常駐內存,因此要避免在native包中直接引用資源 MuzzleFlashPSCTemplate=ParticleSystem'WP_LinkGun.Effects.P_FX_LinkGun_3P_Primary_MF' // 創建一個類型為DominantPointLightComponent DominantPointLightComponent0對象,並賦值給成員變量LightComponent // 由當前類管理,所有當前類創建出來實例都指向同一份DominantPointLightComponent0的內存 Begin Object Class=DominantPointLightComponent Name=DominantPointLightComponent0 LightAffectsClassification=LAC_DYNAMIC_AND_STATIC_AFFECTING CastShadows=TRUE CastStaticShadows=TRUE CastDynamicShadows=TRUE bForceDynamicLight=FALSE UseDirectLightMap=FALSE bAllowPreShadow=TRUE LightingChannels=(BSP=TRUE,Static=TRUE,Dynamic=TRUE,bInitialized=TRUE) PreviewLightRadius=DrawLightRadius0 PreviewLightSourceRadius=DrawLightSourceRadius0 End Object Components.Remove(PointLightComponent0) //將基類中的PointLightComponent0對象從Components數組中刪除 LightComponent=DominantPointLightComponent0 //將LightComponent指向創建的DominantPointLightComponent0對象 Components.Add(DominantPointLightComponent0) //將DominantPointLightComponent0對象添加到Components數組中 // 會為當前類型創建一個SkeletalMeshComponent0對象 // 由當前類管理,所有當前類創建出來實例都指向同一份SkeletalMeshComponent0的內存 // 改寫基類中SkeletalMeshComponent0對象的屬性 Begin Object Name=SkeletalMeshComponent0 SkeletalMesh=SkeletalMesh'WP_LinkGun.Mesh.SK_WP_LinkGun_3P' Translation=(Z=1) Rotation=(Roll=-400) Scale=0.9 End Object // 創建一個類型為ParticleSystemComponent PoweredUpComponent對象,並賦值給成員變量PoweredUpEffect // 由當前類管理,所有當前類創建出來實例都指向同一份SkeletalMeshComponent0的內存 Begin Object Class=ParticleSystemComponent Name=PoweredUpComponent Template=ParticleSystem'WP_LinkGun.Effects.P_WP_Linkgun_PoweredUp' bAutoActivate=false SecondsBeforeInactive=1.0f End Object PoweredUpEffect=PoweredUpComponent // PoweredUpEffect被instanced修飾,為實例變量,在進行賦值時會產生ParticleSystemComponent類型拷貝 }
類修飾符
關鍵字 | 說明 |
extends | 繼承某個類 class Actor extends Object |
implements(IAAA,IBBB,...) | 繼承1個或多個接口 |
Inherits(CAAA,CBBB,...) | 用於native類,繼承1個或多個類 |
within XXX | Within修飾符指出這個類的實例僅可以在XXX類的實例的內部進行創建,且必須將當前XXX類的實例作為這個類實例的Outer class AICmd_AD14Hades_Skill_Birth extends AICommand 注:在類中可以直接訪問調用XXX的變量和函數 |
abstract | 抽象類 不能用該類型創建實例 |
native native(XXX) |
native類 native:生成的.h文件名為:當前包名+Classes.h、當前包名+Names.h native(XXX):生成的.h文件名為:當前包名+XXXClasses.h、當前包名+XXXNames.h |
config(XXX) | 指定類的配置文件為DefaultXXX.ini 子類可以重新指定對應的配置文件YYY(DefaultYYY.ini),若沒有指定則往上搜尋其最近父類的config來確定其所在的配置文件名稱 |
PerObjectConfig | 類的每個實例各自存儲在ini特定的tab塊中 [TheWorld:PersistentLevel.TPlayerController_0.TPlayerInput_0 TPlayerInput] |
noexport | 與native一起使用 使得這個類的native聲明排除在自動生成的C++頭文件之外。當使用這個修飾符時,必須在單獨的頭文件中手動地創建native類聲明 |
dependson(CAAA,CBBB,...) | 告訴uc編譯器在編譯當前類之前,先編譯CAAA,CBBB,... |
transient | 該關鍵字會被子類繼承 使得類不能保存到磁盤 |
nontransient | 去除從父類繼承過來的transient特性 |
editinlinenew | 該關鍵字會被子類繼承 EditInlineNew修飾符聲明了這個類可以有一個從編輯器的屬性窗口中直接創建的新的實例。 |
noneditinlinenew | 去除從父類繼承過來的editinlinenew特性 |
placeable | 該關鍵字會被子類繼承 可以把類放置到編輯器中的關卡、UIScene或Kismet中 注1:加粗的類型為placeable,選中一個類型后可以在關卡中右鍵菜單選擇Add XXX Here將該類型的一個實例添加到關卡 注2:Volume類型需要通過右邊工具欄上的Add Volume圖標進行添加 |
NotPlaceable | 去除從父類繼承過來的placeable特性 |
HideDropDown | 使得類不會顯示在編輯器的該類的類型下拉列表中 |
hidecategories(AAA,BBB,...) | 該關鍵字會被子類繼承 在屬性框中隱藏名為AAA,BBB,...的Tab頁內容,使得屬性框免於混亂,妨礙設計人員查看屬性。 |
showcategories(AAA,BBB,...) | 和hideCategories關鍵字完全相反的效果,它會使得父類中已經使用HideCategories修飾符隱藏的特定種類顯示出來。 |
AutoExpandCategories(AAA,BBB,...) | 查看屬性時默認地完全展開AAA,BBB,...的Tab頁內容 |
CollapseCategories | 該關鍵字會被子類繼承 查看屬性框內容時,去掉標簽分類,所有的可編輯變量都會按照字母順序排列為單獨的一列。 |
DontCollapseCategories | 去除從父類繼承過來的CollapseCategories特性 |
NativeReplication | 僅在native類中有用,意味着屬於類中放置在replication塊中變量是通過c++代碼來處理 需要重寫virtual INT* GetOptimizedRepList(BYTE* Recent, FPropertyRetirement* Retire, INT* Ptr, UPackageMap* Map, UActorChannel* Channel)函數 |
udn MasteringUnrealScriptClasses:中文 英文
成員變量修飾符
關鍵字 | 說明 |
private | 私有成員變量,僅能被當前類中的訪問(uc腳本中) |
protected | 保護成員變量,僅能在當前類和子類中訪問(uc腳本中) |
privatewrite | 在當前類中可寫,其他地方只能讀(uc腳本中) |
protectedwrite | 在當前類和子類中可寫,其他地方只能讀(uc腳本中) |
private{private} | 第1個private指明uc腳本中的訪問權限,第2個private導出到c++中訪問權限 var private{private} transient int LODLevel; |
const | 常量,不能在uc腳本中修改(但可在cpp中修改) 如:var(Movement) const vector Location; |
editconst |
var() native const editconst name Name;// 在uc腳本中不可修改,在編輯器屬性框中不可編輯 var(Collision) editconst PrimitiveComponent CollisionComponent;// 在編輯器屬性框中不可編輯 |
() (XXX) |
可以在編輯器屬性框中看到該變量 ():該變量會被分類到當前類名的Tab下 (XXX):該變量會被分類到名為XXX的Tab下 |
native |
通過C++而非uc腳本來初始化和保存 var native const editconst class Class; |
noexport |
該變量不會包含在自動生成的類聲明中 |
pointer pointer(Type)
|
一個指向object或Type類型的指針 在uc中的定義如下: struct pointer var native private const editconst pointer HashNext; // 生成c++:UObject* HashNext; var const transient native Pointer CachedFloatProperty{UFloatProperty}; // 生成c++:UFloatProperty* CachedFloatProperty; |
<> | 在變量上指定元數據以提供額外信息,以供引擎或編輯器使用,從而提供擴展功能。 請參考:unrealscript元數據 屬性窗口 var( Attenuation ) float RadiusMin<ToolTip=The range at which the sound starts attenuating>; // 為RadiusMin變量提供Tips信息,在編輯器中把鼠標放在屬性框該字段上會顯示該Tips var (LightEnvironment) float CharacterLitIndirectBrightness <UIMin=0.1 | UIMax=1.0 | ClampMin=0.0 | ClampMax=5.0>; // CharacterLitIndirectBrightness變量:UI條上最小值為0.1,最大值為1.0;該變量最小值為0.0,最大值為5.0 |
export | 對Object類型的成員變量有效。當對象被復制(復制/粘帖)或導出到T3D中時,不是僅僅輸出對象引用本身,而是將該成員所指向的對象作為一個子對象塊整體地導出。 |
noimport | 與export相反:導入T3D文本時,將跳過這個變量。 換句話說,當導入或者 復制/粘帖 對象時,這個變量的值將不會被傳遞到新的對象實例中。 |
editinline | 允許在屬性框中編輯這個變量所引用的物體屬性。。該變量只能為對象類型或對象數組類型 如ParticleSystemComponent.uc中: var() editinline array<ParticleSysParam> InstanceParameters; |
editoronly | 僅在運行編輯器時會被加載,在游戲中該變量將被丟棄。 |
instanced | 僅用於對象屬性。 當創建當前類的實例時,將用類的默認屬性中定義的對象產生一個副本,並賦值給該變量。 |
init | 用於在native類中聲明的字符串和動態數組 被作為FString或TArray(而不是FStringNoInit 或TArrayNoInit)導出到頭文件中。'Init'屬性不能被賦予默認值,因為當創建對象時,默認值將會被清除。 var init array<byte> VisibilityFactors;
struct native Category structcpptext |
localized | 使用本地化文件中配置文本 語言設置在DefaultEngine.ini的[Engine.Engine]的Language字段(如:INT、CHT等) // UTPlayerReplicationInfo.uc在UTGame包中 class UTPlayerReplicationInfo extends PlayerReplicationInfo; var localized string OrdersString[8];
在Localization\INT\UTGame.int中 [UTPlayerReplicationInfo] |
config | 這個變量在ini中配置,不能在默認屬性中設置,調用SaveConfig會將當前值保存會ini文件 詳細參見udn:中文 英文 class GameInfo extends Info var config string DefaultGameType; struct native GameTypePrefix var config array<GameTypePrefix> DefaultMapPrefixes;
在Config\DefaultGame.ini中配置 [Engine.GameInfo] DefaultGameType="UTGame.UTDeathmatch" +DefaultMapPrefixes=(Prefix="DM",bUsesCommonPackage=FALSE,GameType="UTGame.UTDeathmatch") +DefaultMapPrefixes=(Prefix="CTF",bUsesCommonPackage=TRUE,GameType="UTGameContent.UTCTFGame_Content");bUsesCommonPackage=TRUE 沒有重復項 添加配置成功
注1:config成員變量所在的配置文件由當前類的config(XXX)來指定,若當前類沒指定,則往上搜尋其最近父類的config(XXX)來確定其所在的配置文件名稱 注2:若DefaultMapPrefixes數組在子類中沒有被重新配置,則直接使用父類配置;若DefaultMapPrefixes數組在子類中被配置,則會使用當前配置(丟棄父類DefaultMapPrefixes數組配置) 注3:config變量在運行過程中被修改后,可以通過調用SaveConfig()來保存實例的config變量到T開頭的配置文件中,調用StaticSaveConfig()來保存類的default缺省對象的config變量到T開頭的配置文件中 local TGame tGame; tGame = TGame(WorldInfo.Game); tGame.ConfigVar = 1500; 最后在生成出來的TGame.ini中,ConfigVar為1500 [UTGame.TGame] ConfigVar=1500 |
globalconfig | 這個變量在ini中配置,不能在默認屬性中設置;與config相比,globalconfig不允許派生的子類重新配置該變量(配置了沒有用,始終讀取當前類的配置數值) class UTGame extends UDKGame var globalconfig float EndTimeDelay;
在Config\DefaultGame.ini中配置 [UTGame.UTGame] EndTimeDelay=4.0 GameSpecificMapCycles=(GameClassName="UTDeathmatch",Maps=("DM-Sanctuary","DM-Deck","DM-Gateway"));添加第一個數組元素 |
transient | 這個變量是臨時使用的,且不是對象永久狀態的一部分。Transient變量不會被保存到磁盤。當加載一個對象時,Transient變量被初始化為類的默認值。 var transient bool bNetDirty; |
duplicatetransient | 當創建對象的副本時,該變量的值將被重置為類的默認值。 |
repnotify | 若該變量被放置在replication塊中,則該變量會在ReplicatedEvent事件函數中收到回調通知 var repnotify int PlayLoopEffectRepIdx; replication simulated event ReplicatedEvent(Name VarName) |
input | 在Unreal的輸入系統中是可以訪問的該變量,從而使輸入(比如按鈕的押下和操作桿的運動)能夠和變量直接地進行映射。該變量只能為byte或float類型
如Controller.uc中: // Input buttons. 在Bindings中使用bFire變量 Bindings=(Name="Fire",Command="Button bFire | StartFire | OnRelease StopFire") |
interp | 該變量可以受到Matinee中的浮點或向量屬性軌跡的驅動從而隨時間改變 如CameraActor.uc中: var() interp float AspectRatio; var() interp float FOVAngle; |
deprecated | 該變量在不久的將來將會被刪除,該字段可以被加載,但不能被保存。 |
NonTransactional | 在編輯器中修改該變量不能被Undo或Redo |
databinding | 某個UI控件可以SetDatastorebinding和該變量進行綁定,使得該變量變化時,UI會進行刷新 var databinding int GoalScore;
Lbl = UILabel(FindChild('ServerRules',true)); |
unreal texture variable syntax
成員函數
無論是成員函數還是靜態成員函數,都是虛函數,可以被子類重寫
class UTWeaponAttachment extends Actor;
{
static function string FuncTest() { return "Hello"; } } class TGWeaponAttachment extends UTWeaponAttachment; { static function string FuncTest() { return "Good"; } } local string Text; local class<UTWeaponAttachment> AttachmentClass; AttachmentClass = class'TGWeaponAttachment'; Text = AttachmentClass.static.FuncTest(); //Text="Good"
調用缺省全局狀態函數:Global.StopFiring();
調用直接父類函數:Super.PostBeginPlay();
調用繼承樹某個父類函數:Super(UTWeapon).FireAmmunition();
函數空實現:simulated function vector Test(); // 編譯器會自動添加返回各成員為0的vector代碼
關鍵字 | 說明 |
private | 私有函數,僅能被當前類中的訪問 |
protected | 保護函數,僅能在當前類和子類中訪問 |
public | 公共函數,能在所有類中訪問 |
simulated | 帶該關鍵字的函數:不僅能被ROLE_AutonomousProxy、ROLE_Authority對象執行,還能被Role=ROLE_SimulatedProxy對象執行 不帶該關鍵字的函數:僅能被ROLE_AutonomousProxy、ROLE_Authority對象執行 |
final | 非虛函數,不允許被子類重寫 final native function SetNetUpdateTime(float NewUpdateTime); |
native | 使用C++實現(當前類必須是native的,這也意味着當前腳本包為native包) native function float GetGravityZ(); native(266) final function bool Move( vector Delta ); // native后的圓括號內的數字和在C++中GNatives數組中idx是相對應的 導出的.h文件中生成float GetGravityZ()的定義以及粘合函數execGetGravityZ的實現 另外,開發者必須在某個cpp中實現float GetGravityZ() |
noexport | 與native一起使用,不應該導出這個native函數的C++函數定義,僅導出該函數的在腳本粘合版本的定義。 native final function noexport SetHardAttach(optional bool bNewHardAttach); 在導出的.h文件中不生成void SetHardAttach(optional bool bNewHardAttach)函數,僅僅導出粘合函數execSetHardAttach的定義 另外,開發者必須在cpp中實現void SetHardAttach(optional bool bNewHardAttach)和execSetHardAttach
noexport一般與cpptext塊配合使用: cpptext virtual void SetHardAttach(UBOOL bNewHardAttach); } cpptext會使得導出的.h文件中生成virtual void SetHardAttach(UBOOL bNewHardAttach)函數的定義 然后,開發者在cpp中實現virtual void SetHardAttach(optional bool bNewHardAttach)和execSetHardAttach 在execSetHardAttach中,添加SetHardAttach函數調用,將腳本和cpp的調用關系連接起來 這種方式可以使得uc、cpp的函數(是否為virtual,函數名,參數順序或個數可以不一樣)相互獨立開 |
const | 與native一起使用,使得導出的c++函數定義也是帶有const,不允許在函數內修改成員變量 native final function GetComponentsBoundingBox(out box ActorBox) const; 導出的.h文件中生成void GetComponentsBoundingBox(FBox& ActorBox) const; |
iterator | 與native一起使用,在導出的.h文件中僅僅導出粘合函數execDynamicActors的定義 另外,開發者必須在cpp中實現execDynamicActors 在uc腳本中可以使用foreach調用該函數 local Pawn P; |
static | 類缺省對象函數,也是虛函數 另外,與native一起用時,該關鍵字會忽略,會導出成員函數,而不是靜態成員函數 |
event | 替換function,生成腳本的C++調用函數,實現C++調用腳本的功能 如:腳本event Destroyed()會.h中生成void eventDestroyed()的實現 simulated event SetInitialState() |
latent | 延遲函數(只能在state的label塊中調用) native(256) final latent function Sleep( float Seconds ); |
client | 被server調用的遠程函數,調用后立即返回,無返回值 |
server | 被ROLE_AutonomousProxy客戶端調用的遠程函數,調用后立即返回,無返回值 |
reliable |
修飾client和server遠程函數調用:可靠發送,保證按照順序到達 |
unreliable | 修飾client和server遠程函數調用:不可靠發送,不能保證會以任何特定的順序到達,如果沒有足夠的帶寬它可能會丟棄 |
exec | 控制台命令函數,僅能在某些特定的類中:UIInteraction、UISceneClient、GameViewportClient、GameInfo、PlayerInput、PlayerController、Player、Pawn、InventoryManager、Weapon、HUD、CheatManager |
Operator, PreOperator, PostOperator | native(129) static final preoperator bool ! ( bool A ); // local bool bTest = !bTest2; |
singular | 阻止函數對其本身進行遞歸調用,防止出現死循環。 規則是: 如果某個actor實例已經在一個singular函數中(通過調用棧回溯查找),任何對該actor實例的后續其他singular的調用都將會被跳過。 // ************************ UTPlayerController類 ************************ singular function Test1() Test2(); //Test3(); // 編譯不過 Error, Calling a singular function within a singular function on the same object will always fail UTPawn(Pawn).Func1(); function Test2() singular function Test3() // ************************ UTPawn類 ************************
UTPlayerController(Controller).Test3(); // 運行時跳過 執行ExecTest命令后,打印出: Test1! |
函數參數修飾符
關鍵字 |
說明 |
coerce | 自動進行類型轉換 |
out | 使用引用傳入值類型變量,輸出型參數 |
const | 常量參數,函數中不允許改變參數 |
optional | 可選參數,必須放到函數參數列表的最右邊,傳參的時候不填表示使用缺省參數 native noexport final function coerce actor Spawn 調用示例:Spawn(class'CoverReplicator'); Spawn(class'DebugCameraHUD', self); Spawn(class'DynamicCameraActor', self,,,,, TRUE); Spawn(PlayerControllerClass,,, SpawnLocation, SpawnRotation); |
函數更多信息請參見:
迭代器
① 在uc腳本中迭代器需要與foreach配合來一起使用
local Actor A; local Controller C; foreach AllActors( class 'Actor', A ) { } foreach WorldInfo.AllControllers(class'Controller',C) { }
注1:在非Actor類的函數中使用Actor迭代器時,則須通過某個actor的實例來調用
注2:在非Actor類的函數中使用worldinfo迭代器時,則須通過class'WorldInfo'.static.GetWorldInfo()來調用
② 在c++中可以通過一下方式遍歷不同類型的對象
// 遍歷游戲世界中所有的Object for (FObjectIterator It; It; ++It) {} // 遍歷游戲世界中所有的Actor for(FActorIterator ActorIt;ActorIt;++ActorIt) {} // 遍歷游戲世界中所有會進行網絡同步的Actor for( FNetRelevantActorIterator It; It; ++It ) {} // 遍歷游戲世界中所有bStatic=false的Actor for (FDynamicActorIterator It; It; ++It) {} // 遍歷游戲世界中所有開啟Tick的Actor for (FTickableActorIterator It; It; ++It) {} // 遍歷游戲世界中所有的UObject對象 for( TObjectIterator<UObject> It ; It ; ++It ) // 遍歷游戲世界中所有的UGuidCache對象 for (TObjectIterator<UGuidCache> It; It; ++It) {} // 遍歷游戲世界中所有的UParticleSystemComponent組件 for (TObjectIterator<UParticleSystemComponent> It;It;++It) {} // 遍歷游戲世界中所有的ULevel對象 for( TObjectIterator<ULevel> It; It; ++It ) {} // 遍歷游戲世界中所有的UPackage對象 for( TObjectIterator<UPackage> It; It; ++It ) {} // 遍歷游戲世界中所有的UTexture2D對象 for (TObjectIterator<UTexture2D> It; It; ++It) {} // 遍歷UEngine* GEngine中所有的LocalPlayer對象 for (FLocalPlayerIterator It(GEngine); It; ++It) {} // 遍歷當前對象的Class類型所有float類型成員變量 for (TFieldIterator<UFloatProperty> It(GetClass()); It; ++It) {} // 遍歷當前對象的Class類型所有結構體類型成員變量 for (TFieldIterator<UStructProperty> It(GetClass()); It; ++It) {} // 遍歷所有Class類型 for( TObjectIterator<UClass> It ; It ; ++It ) {}
Actor的迭代器成員函數
//循環處理關卡中的類型為BaseClass的所有actors。如果您指定了可選參數InterfaceClass,那么則僅包含實現了InterfaceClass接口的actors。 AllActors ( class<actor> BaseClass, out actor Actor, optional class InterfaceClass ) //循環處理關卡中的bStatic=false 類型為BaseClass的所有actors。 DynamicActors( class<actor> BaseClass, out actor Actor, optional class InterfaceClass ) //循環處理當前actor具有的類型為BaseClass的所有actors。 ChildActors( class<actor> BaseClass, out actor Actor ) //循環處理以當前actor作為基類的類型為BaseClass的所有actors。 BasedActors( class<actor> BaseClass, out actor Actor ) //循環處理和當前actor相接觸(滲入)的類型為BaseClass的所有actors。 TouchingActors( class<actor> BaseClass, out actor Actor ) //循環處理從 Start 點到 End 點之間使用盒式碰撞范圍 Extent 進行線性跟蹤所觸及的類型為BaseClass的所有actors。 //在每次迭代中, HitLoc 設置為碰撞位置, HitNorm 設置為一個向外指的碰撞法線。 TraceActors( class<actor> BaseClass, out actor Actor, out vector HitLoc, out vector HitNorm, vector End, optional vector Start, optional vector Extent ) //循環處理位置Loc處的指定 Radius(半徑) 內的類型為BaseClass的所有actors(若沒有指定特定位置,則使用當前actor的位置)。 OverlappingActors( class<actor> BaseClass, out actor Actor, float Radius, optional vector Loc, optional bool bIgnoreHidden ) //循環處理Loc位置處可見的類型為BaseClass的所有actors(如果沒有指定位置,則使用當前actor的位置)。 VisibleActors( class<actor> BaseClass, out actor Actor, optional float Radius, optional vector Loc ) //返回從位置Loc處(若沒有指定特定位置,則使用當前actor的位置)指定Radius(半徑)內碰撞到bCollideActors==true 類型為BaseClass的所有可見actors。該函數使用了Hash表,所以它要比 AllActors() 快很多。 VisibleCollidingActors ( class<actor> BaseClass, out actor Actor, float Radius, optional vector Loc, optional bool bIgnoreHidden ) //返回從位置Loc處(若沒有指定特定位置,則使用當前actor的位置)指定Radius(半徑)內碰撞到bCollideActors==true 類型為BaseClass的所有actors。該函數使用了Hash表,所以它要比 AllActors() 快很多。 CollidingActors ( class<actor> BaseClass, out actor Actor, float Radius, optional vector Loc ) //返回當前actor中包含的類型為BaseClass的所有actor組件。 ComponentList( class<ActorComponent> BaseClass, out ActorComponent out_Component ) //返回“直接或間接”附加到當前actor上類型為BaseClass的所有組件。 AllOwnedComponents( class<Component> BaseClass, out ActorComponent OutComponent ) //返回類型為BaseClass的所有本地PlayerControllers。 LocalPlayerControllers( class<PlayerController> BaseClass, out PlayerController PC)
WorldInfo的迭代器成員函數
//迭代關卡中當前具有的所有Controllers (Player 或 AI) 。 AllControllers(class<Controller> BaseClass, out Controller C) //迭代關卡中的類型為BaseClass的所有 Pawns 。可以選擇性地指定迭代某個給定位置(TestLocation)周圍的某個半徑(TestRadius)內的 Pawns 。 AllPawns(class<Pawn> BaseClass, out Pawn P, optional vector TestLocation, optional float TestRadius) //迭代關卡中的類型為BaseClass的所有 NavigationPoint。 AllNavigationPoints(class<NavigationPoint> BaseClass, out NavigationPoint N) //迭代關卡中的類型為BaseClass的所有 NavigationPoint。可以選擇性地指定迭代某個給定位置(Point)周圍的某個半徑(Radius)內的 NavigationPoints。 RadiusNavigationPoints(class<NavigationPoint> BaseClass, out NavigationPoint N, vector Point, float Radius) //迭代關卡中所有網絡連接玩家對象的列表,同時傳回了IP及端口。僅在服務器上運行。 AllClientConnections(out Player ClientConnection, out int ClientIP, out int ClientPort)
代理
接口
聲明形式如下:
interface UIDataStoreSubscriber
DependsOn(UIRoot)
native(UIPrivate);
native function SetDataStoreBinding( string MarkupText, optional int BindingIndex=INDEX_NONE );
① 接口中只能有函數聲明不能有函數體,派生該接口的類必須聲明接口中所有函數。除native關鍵字外,類中的函數聲明必須和接口中的聲明相匹配(接口中的native函數在其派生類中不必聲明為native)
② 接口允許所有的函數類型:正常的函數及事件。
③ 接口中只可以定義代理
④ 接口僅能包含不影響類的內存布局的聲明 – 可以聲明枚舉值、結構體和常量,但是不能聲明變量。
⑤ 接口可以選擇擴展另一個接口。
⑥ 接口體也可以包含cpptext塊(cpptext塊中的函數可以有函數體),它將會同native接口聲明一同被導出。
接口IXXX的成員變量PawnOwner在c++中為:TScriptInterface<class IXXX> PawnOwner;
⑦ 在c++中,使用ScriptInterfaceCast模板函數可以將某個對象安全轉換為接口類型
APawn* Enemy;
//若Enemy不為空且從IInterface_PEPPawn接口派生,則轉換成功,否則返回空
TScriptInterface<IInterface_PEPPawn> IEnemy = ScriptInterfaceCast<IInterface_PEPPawn>(Enemy);
⑧ 在c++中,使用UObject的GetInterfaceAddress成員函數檢查UObject實例是否實現了特定的接口
APawn* Enemy;
//若Enemy從IInterface_PEPPawn接口派生,則IEnemy不為空,否則返回空
IInterface_PEPPawn* IEnemy = (IInterfaceName*)Enemy->GetInterfaceAddress(IInterface_PEPPawn::UClassType::StaticClass());
其他參考
unrealtexture Scripting Topics
unrealtexture Scripting lessons