博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
UnrealScript语言基础
阅读量:4701 次
发布时间:2019-06-09

本文共 49008 字,大约阅读时间需要 163 分钟。

总体特征

(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
> On`{CallbackName}Delegates;// 增加一个代理对象到数组中`define DefineAddDelegateHandlers(CallbackName) \function Add`{CallbackName}Delegate(delegate
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
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,为宏参数的个数

 

udn 虚幻脚本预处理器(UPP):   

udn 掌握虚幻脚本预处理器(UPP):   

常量

作用范围

1. 常量在运行时不可改变,可以定义在类中、成员函数内、状态块内,但编译器会将其统一调整到类中;好的编码习惯是将常量定义在类的起始处。

2. 定义在结构体中的常量将只能在结构体中使用,外部无法访问。

3. 当前类中定义的常量可直接访问:PI;访问外部类TGTest中定义的常量:class'TGTest'.const.PI   注:TGTest类的工程编译需在使用该常量的工程之前或同处一个工程

4. 对于公共常量,一般会将这些常量集中写入到一个单独的.uci文件中(如:TGConst.uci),然后类的起始处`include(TGConst.uci)

举例

const a = 10; // 十进制 a=10const b = 0x10;  // 十六进制 转成十进制为:b=16const c = 010x;  // 八进制 转成十进制为:c=8const d = true;const f = 3.14;const s = "Hello World!"; // 字符串需加上双引号const n = 'James'; // name需加上单引号const o = none; // 空对象 相当于C/C++中的NULLconst oc = class'UTGame.UTPawn'; // 类模板(引号中不能有空格)  class
const oc2 = class'UTBot'; // 类模板(引号中不能有空格) class
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 / Piconst DegToRad = 0.017453292519943296;        // Pi / 180const UnrRotToRad = 0.00009587379924285;        // Pi / 32768const RadToUnrRot = 10430.3783504704527;        // 32768 / Piconst DegToUnrRot = 182.0444;const UnrRotToDeg = 0.00549316540360483;const INDEX_NONE = -1;// Aspect ratio constantsconst AspectRatio4x3 = 1.33333;const AspectRatio5x4 = 1.25;const AspectRatio16x9 = 1.77778;const InvAspectRatio4x3 = 0.75;const InvAspectRatio5x4 = 0.8;const InvAspectRatio16x9 = 0.56249;

 

变量

更多类型说明请参见:

unreal texture:

unrealscript DefaultProperties:   

udn变量:   

udn表达式& 操作符:   

数值型

类型 长度 范围 举例

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 FFFFb = a>>2;     // b=0xFFFF FFFF=-1b = 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.#INF00b1 = IsNan(f1);//falseb1 = (f1==f1);//trueif (f1 > 1000000000)//true{    `log("f1为极大值");}if (f1 < -1000000000)//false{    `log("f1为极小值");}f1 = -1.0 / f2;// -1.#INF00b1 = IsNan(f1);//falseb1 = (f1==f1);//trueif (f1 > 1000000000)//false{    `log("f1为极大值");}if (f1 < -1000000000)//true{    `log("f1为极小值");}f1 = f2/f2;//-1.#IND00b1 = IsNan(f1);//trueb1 = (f1==f1);//falsef1 = -f2/f2;//-1.#IND00b1 = IsNan(f1);//trueb1 = (f1==f1);//false

 

bool

(1)bool型只能为True或False

(2)bool型与数值型间不支持隐式转换

local int a;local bool b;a = 10; b = a;     // 编译错误b = bool(a);  // b=truea = b;   // 编译错误a = int(b); // a=1

(3)^^ 异或

local bool b1, b2, b3;b1 = true; b2 = false;b3 = b1^^b2; // b3=trueb1 = 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;// 字符串转成namem = name("test"); // m='test' m = name("Hello World!"); // m='Hello World!'// 字符串:整型b = bool("-1"); // b=truea = int("-1");  // a=-1n = byte("-1"); // n=255f = float("-1");// f=-1.000000// 字符串:浮点数b = bool("-300.23"); // b=truea = int("-300.23");  // a=-300n = byte("-300.23"); // n=byte(-300)=212f = float("-300.23");// f=-300.230011// 字符串:布尔值b = bool("True"); // b=truea = int("True");  // a=0n = byte("True"); // n=0f = float("True");// f=0.000000// 字符串:起始为数字子串b = bool("210fAlse300");      // b=truea = int("210fAlse300");       // a=210n = byte("210fAlse300");      // n=210f = float("210fAlse300");     // f=210.000000// 字符串:起始不为数字子串b = bool("True335Test");      // b=falsea = int("True335Test");       // a=0n = byte("True335Test");      // n=0f = 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="trueb1" = "hello">
"hello"; // 大写字母
<小写字母 b1="trueb1" = "hello"!="hello" ; 大小写敏感 "hello"~="hello" "hello" "hello"<="Hello">
="Hello"; // b1=trueb1 = "Hello"!="Hello"; // b1=falseb1 = "Hello"~="Hello"; // b1=true

 

(10)string函数

local int a1;local array
v1, v2, v3, v4;local string s1;// Object函数a1 = Len("Hello"); // a1=5a1 = Instr("THIS is my book!", "is"); // 返回第1个is的位置(大小写敏感) a1=5s1 = 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");

更多请参见:字符串udn     

                     

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_Authoritynr = -1; // nr=INVALIDEnr = 10; // nr=INVALIDEa = 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]=8a[-1] = 2;    // a[0]=2a[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
va;va.Length = 5; // va size=5: 0 0 0 0 0va.Length = 0; // va size=0va.Length = va.Length+3; // va size=3: 0 0 0va.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
va;local array
vb;local color c;va[2] = 10; // va size=3: 0 0 10va[-1] = 5; // 无效语句 va size=3: 0 0 10va[1] = 3; // va size=3: 0 3 10va[2] = va[5]+8; // va size=3: 0 3 8vb[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
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
va;va.AddItem(1); // 末尾增加值为1的元素 size=1 a: 1va.Add(3); // 末尾扩充3个元素 size=4 a: 1 0 0 0va.Insert(2, 2); // 在索引为2处插入2个元素 size=6 a: 1 0 0 0 0 0va.Remove(1, 3); // 从索引为1处起删除3个元素 size=3 a: 1 0 0va.AddItem(5); // 末尾增加值为5的元素 size=4 a: 1 0 0 5va.RemoveItem(0); // 删除所有为0的元素 size=2 a: 1 5va.InsertItem(1, 7); // 在索引为1处插入值为7的元素 size=3 a: 1 7 5

 

(14)defaultproperties中使用函数来追加、删除元素

var Array
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
va;local array
vr;local array
vo;va[0]=1; va[1]=2;va[2]=6; va[3]=2;n = va.Find(2); // n=1 第1个为2的元素的索引值为1n = 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的元素的索引值为1n = vr.Find('Roll', 500); // n=-1 未找到Roll=500的元素n = vr.Find('Yaw', 3000); // n=0 第1个Yaw=3000的元素的索引值为0o1 = 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
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
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

 

(18)静态数组与动态数组拷贝比较

local int i;local int a[3], ac[3];local Array
va, vac;a[0] = 2; a[1] = 5; // a: 2 5// ac = a; // 编译失败,静态数组不能通过赋值方式拷贝// 循环拷贝静态数组a中的值到ac中for (i=0; i

 

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
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

{
    var() float X, Y, Z;
};

immutablewhencooked 在使用cook包时,启用immutable特性
native

native结构体,会导出到.h中

struct native KeyBind

{
    var config name Name;
    var config string Command;
    var config bool Control,
                          Shift,
                          Alt;

    /** if true, the bind will not be activated if the corresponding key is held down */

    var config bool bIgnoreCtrl, bIgnoreShift, bIgnoreAlt;

    structcpptext

    {
        FKeyBind()
        : Name()
        , Control(FALSE), Shift(FALSE), Alt(FALSE)
        , bIgnoreCtrl(FALSE), bIgnoreShift(FALSE), bIgnoreAlt(FALSE)
       {}
    }
};

{XXX}

在导出的c++中类型名为XXX

struct {QWORD} qword  // qword在c++中类型为QWORD

{
    var native const int A, B;
};

struct {WxRect} ViewportDimension // ViewportDimension在c++中类型为WxRect

{
    var config int X, Y, Width, Height;
};

struct {FNavMeshEdgeBase*} EdgePointer  // EdgePointer在c++中类型为FNavMeshEdgeBase*

{
    var native const pointer Dummy{FNavMeshEdgeBase};
};

注1:结构体其他修饰符请参考后文中类修饰符对应关键字

注2:结构体成员的修饰符请参考后文中类成员修饰符对应关键字

结构体更多信息请参见:

udn结构体:   

 

常用结构体 -- 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.0v3 = v1 - v2; // v3.x=0.0  v3.y=-3.0  v3.z=1.0v3 = 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.0v3 = v1; v3 -= v2; // v3.x=0.0  v3.y=-3.0  v3.z=1.0v3 = 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.0v2 = v1*2.0; // v2.x=2.0  v2.y=4.0  v2.z=6.0v2 *= 2.0;   // v2.x=4.0  v2.y=8.0  v2.z=12.0v2 /= 2.0;   // v2.x=2.0  v2.y=4.0  v2.z=6.0v2 = 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.0v2 = 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
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
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
NewClass;NewClass = class
( 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
(Instigator);

缺省属性

var class
GameReplicationInfoClass;var class
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

    within PVEAIController
    dependson(TGAD14Types);

注:在类中可以直接访问调用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]

bInvertMouse=False
bInvertTurn=False

noexport 

与native一起使用

使得这个类的native声明排除在自动生成的C++头文件之外。当使用这个修饰符时,必须在单独的头文件中手动地创建native类声明

dependson(CAAA,CBBB,...) 告诉uc编译器在编译当前类之前,先编译CAAA,CBBB,...
transient

该关键字会被子类继承

使得类不能保存到磁盘

nontransient 去除从父类继承过来的transient特性
editinlinenew

该关键字会被子类继承

EditInlineNew修饰符声明了这个类可以有一个从编辑器的属性窗口中直接创建的新的实例。

这可以用于抽象的基类中,从而允许设计人员为特定的属性选择要在编辑器中使用的对象的类型。
如:SeqAct_ActorFactory允许设计人员根据需要产生的对象类型来选择使用哪种类型的ActorFactory。
ActorFactory是一个声明为EditInlineNew的抽象类,可以通过具有特定功能的几个其它的类来扩展它。
由于EditInlineNew会被子类继承,所以在UnrealEd中可以把属性设置为这些子类中的任何一个,从而使得动作是非常通用的。

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 const int Dummy;
};

var native private const editconst pointer HashNext; // 生成c++:UObject* HashNext;

var const transient native Pointer  CachedFloatProperty{UFloatProperty}; // 生成c++:UFloatProperty* CachedFloatProperty;

<>

在变量上指定元数据以提供额外信息,以供引擎或编辑器使用,从而提供扩展功能。 请参考:   

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

{
    var init string Tag;
    var init string Header;
    var int id;
    var init array<MetaKeyValuePair> KeyValuePairs;
    var init array<Category> SubCategories;

    structcpptext

    {
        FCategory()
        {}
        FCategory(EEventParm)
       {
            appMemzero(this, sizeof(FCategory));
       }
        FCategory(const FString& InTag, const FString& InHeader) : Tag(InTag), Header(InHeader), Id(INDEX_NONE) {}
    }
};

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]

OrdersString(0)="Freelance"
OrdersString(1)="Freelance"
OrdersString(2)="Attacking"
OrdersString(3)="Defending"
OrdersString(4)="Orb Runner"
OrdersString(5)="Special Ops"
OrdersString(6)="Support"
OrdersString(7)="Holding"

config

这个变量在ini中配置,不能在默认属性中设置,调用SaveConfig会将当前值保存会ini文件   详细参见udn:   

class GameInfo extends Info

    config(Game)
    native
    dependson(OnlineSubsystem);

var config string DefaultGameType;

struct native GameTypePrefix

{
    /** map prefix, e.g. "DM" */
    var string Prefix;
    /** if TRUE, generate a common package for the gametype */
    var bool bUsesCommonPackage;
    /** gametype used if none specified on the URL */
    var string GameType;
    /** additional gametypes supported by this map prefix via the URL (used for cooking) */
    var array<string> AdditionalGameTypes;
    /** forced objects (and classes) that should go into the common package to avoid cooking into every map */
    var array<string> ForcedObjects;
};

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=FALSE,GameType="UTGameContent.UTCTFGame_Content")
+DefaultMapPrefixes=(Prefix="VCTF",bUsesCommonPackage=FALSE,GameType="UTGameContent.UTVehicleCTFGame_Content")
+DefaultMapPrefixes=(Prefix="TM",bUsesCommonPackage=FALSE,GameType="UTGame.TGame")

+DefaultMapPrefixes=(Prefix="CTF",bUsesCommonPackage=TRUE,GameType="UTGameContent.UTCTFGame_Content");bUsesCommonPackage=TRUE 没有重复项 添加配置成功

+DefaultMapPrefixes=(Prefix="VCTF",bUsesCommonPackage=FALSE,GameType="UTGameContent.UTVehicleCTFGame_Content");重复项 添加配置失败
.DefaultMapPrefixes=(Prefix="DM",bUsesCommonPackage=FALSE,GameType="UTGame.UTDeathmatch");不管与前面的配置是否重复 均能添加配置成功
.DefaultMapPrefixes=(Prefix="VCTF",bUsesCommonPackage=FALSE,GameType="UTGameContent.UTVehicleCTFGame_Content");不管与前面的配置是否重复 均能添加配置成功
-DefaultMapPrefixes=(Prefix="VCTF",bUsesCommonPackage=FALSE,GameType="UTGameContent.UTVehicleCTFGame_Content");删除前面所有内容为当前行的配置(精确匹配)
!DefaultMapPrefixes=ClearArray ;将DefaultMapPrefixes清空
+DefaultMapPrefixes=(Prefix="DM",bUsesCommonPackage=FALSE,GameType="UTGame.UTDeathmatch");没有重复项 添加配置成功
.DefaultMapPrefixes=(Prefix="VCTF",bUsesCommonPackage=FALSE,GameType="UTGameContent.UTVehicleCTFGame_Content");不管与前面的配置是否重复 均能添加配置成功
DefaultMapPrefixes=(Prefix="TM",bUsesCommonPackage=FALSE,GameType="UTGame.TGame");不管与前面的配置是否重复 使用当前行配置重写DefaultMapPrefixes数组最后一个元素

 

注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);

if( tGame != None )
{

    tGame.ConfigVar = 1500;

    class'TGame'.default.ConfigVar = 1600;
    class'TGame'.StaticSaveConfig(); // 将ConfigVar=1600保存到T配置文件中
    tGame.SaveConfig(); // 将ConfigVar=1500保存到T配置文件中
}

最后在生成出来的TGame.ini中,ConfigVar为1500

[UTGame.TGame]

ConfigVar=1500

globalconfig

这个变量在ini中配置,不能在默认属性中设置;与config相比,globalconfig不允许派生的子类重新配置该变量(配置了没有用,始终读取当前类的配置数值)

class UTGame extends UDKGame

    config(Game)
    dependson(UTCharInfo);

var globalconfig float EndTimeDelay;

struct GameMapCycle
{
    var name GameClassName;
    var array<string> Maps;
};
var globalconfig array<GameMapCycle> GameSpecificMapCycles;

 

在Config\DefaultGame.ini中配置

[UTGame.UTGame]

EndTimeDelay=4.0

GameSpecificMapCycles=(GameClassName="UTDeathmatch",Maps=("DM-Sanctuary","DM-Deck","DM-Gateway"));添加第一个数组元素

GameSpecificMapCycles=(GameClassName="UTTeamGame",Maps=("DM-Sanctuary","DM-Deck","DM-Gateway"));不管与前面的配置是否重复 使用当前行配置重写GameSpecificMapCycles数组最后一个元素
+GameSpecificMapCycles=(GameClassName="UTVehicleCTFGame_Content",Maps=("VCTF-Necropolis","VCTF-SandStorm"));没有重复项 添加配置成功

transient

这个变量是临时使用的,且不是对象永久状态的一部分。Transient变量不会被保存到磁盘。当加载一个对象时,Transient变量被初始化为类的默认值。

var transient bool bNetDirty;

duplicatetransient

当创建对象的副本时,该变量的值将被重置为类的默认值。

repnotify

若该变量被放置在replication块中,则该变量会在ReplicatedEvent事件函数中收到回调通知

var repnotify int PlayLoopEffectRepIdx;

replication

{
    if(Role == ROLE_Authority)
        PlayLoopEffectRepIdx;
}

simulated event ReplicatedEvent(Name VarName)

{
    if (VarName == 'PlayLoopEffectRepIdx')
   {
    }
    else
    {
        super.ReplicatedEvent(VarName);
    }
}

input

在Unreal的输入系统中是可以访问的该变量,从而使输入(比如按钮的押下和操作杆的运动)能够和变量直接地进行映射。该变量只能为byte或float类型

 

如Controller.uc中:

// Input buttons.

var input byte bFire;

在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));

Lbl.SetDatastorebinding( GC.static.GetEndOfMatchRules(GRI.GoalScore, GRI.TimeLimit) );

 

变量修饰符:   

成员函数

 

无论是成员函数还是静态成员函数,都是虚函数,可以被子类重写

 

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
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;

ForEach  DynamicActors(class'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;

native(130) static final operator(30) bool && ( bool A, skip bool B ); // bTest && bTest2
native(163) static final preoperator int ++ ( out int A ); // ++i
native(164) static final preoperator int -- ( out int A ); // --i
native(165) static final postoperator int ++ ( out int A ); // i++
native(166) static final postoperator int -- ( out int A ); // i--

singular

阻止函数对其本身进行递归调用,防止出现死循环。

规则是: 如果某个actor实例已经在一个singular函数中(通过调用栈回溯查找),任何对该actor实例的后续其他singular的调用都将会被跳过。

// ************************ UTPlayerController类 ************************

class  UTPlayerController  extends  UDKPlayerController;
exec function  ExecTest() // 测试命令函数
{
    Test1();
}

singular function Test1()

{
    `log("Test1!");

    Test2();

    //Test3(); // 编译不过 Error, Calling a singular function within a singular function on the same object will always fail

    UTPawn(Pawn).Func1();

}

function Test2()

{
    `log("Test2!");
    Test3(); // 运行时跳过
    Test1(); // 运行时跳过
}

singular function Test3()

{
    `log("Test3!");
}

// ************************ UTPawn类  ************************

class UTPawn extends UDKPawn;
singular function Func1()
{
    `log("Pawn Func1!");

 

    UTPlayerController(Controller).Test3(); // 运行时跳过

    UTPlayerController(Controller).Test1(); // 运行时跳过
}

执行ExecTest命令后,打印出:

Test1!

Test2!
Pawn Func1!

函数参数修饰符

关键字

说明

coerce 自动进行类型转换
out 使用引用传入值类型变量,输出型参数
const 常量参数,函数中不允许改变参数
optional  

可选参数,必须放到函数参数列表的最右边,传参的时候不填表示使用缺省参数

native noexport final function coerce actor Spawn

(
    class<actor> SpawnClass,
    optional actor SpawnOwner,
    optional name SpawnTag,
    optional vector SpawnLocation,
    optional rotator SpawnRotation,
    optional Actor ActorTemplate,
    optional bool bNoCollisionFail
);

调用示例:Spawn(class'CoverReplicator');

              Spawn(class'DebugCameraHUD', self);

              Spawn(class'DynamicCameraActor', self,,,,, TRUE);

              Spawn(PlayerControllerClass,,, SpawnLocation, SpawnRotation);

函数更多信息请参见:

UnrealScript函数       

掌握UnrealScript函数      

迭代器

① 在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++中可以通过一下方式遍历不同类型的对象

// 遍历游戏世界中所有的Objectfor (FObjectIterator It; It; ++It) {}// 遍历游戏世界中所有的Actorfor(FActorIterator ActorIt;ActorIt;++ActorIt) {}// 遍历游戏世界中所有会进行网络同步的Actorfor( FNetRelevantActorIterator It; It; ++It ) {}// 遍历游戏世界中所有bStatic=false的Actorfor (FDynamicActorIterator It; It; ++It) {}// 遍历游戏世界中所有开启Tick的Actorfor (FTickableActorIterator It; It; ++It) {}// 遍历游戏世界中所有的UObject对象for( TObjectIterator
It ; It ; ++It )// 遍历游戏世界中所有的UGuidCache对象for (TObjectIterator
It; It; ++It) {}// 遍历游戏世界中所有的UParticleSystemComponent组件for (TObjectIterator
It;It;++It) {}// 遍历游戏世界中所有的ULevel对象for( TObjectIterator
It; It; ++It ) {}// 遍历游戏世界中所有的UPackage对象for( TObjectIterator
It; It; ++It ) {}// 遍历游戏世界中所有的UTexture2D对象for (TObjectIterator
It; It; ++It) {}// 遍历UEngine* GEngine中所有的LocalPlayer对象for (FLocalPlayerIterator It(GEngine); It; ++It) {}// 遍历当前对象的Class类型所有float类型成员变量for (TFieldIterator
It(GetClass()); It; ++It) {}// 遍历当前对象的Class类型所有结构体类型成员变量for (TFieldIterator
It(GetClass()); It; ++It) {}// 遍历所有Class类型for( TObjectIterator
It ; It ; ++It ) {}

 

Actor的迭代器成员函数

//循环处理关卡中的类型为BaseClass的所有actors。如果您指定了可选参数InterfaceClass,那么则仅包含实现了InterfaceClass接口的actors。AllActors ( class
BaseClass, out actor Actor, optional class InterfaceClass )//循环处理关卡中的bStatic=false 类型为BaseClass的所有actors。DynamicActors( class
BaseClass, out actor Actor, optional class InterfaceClass )//循环处理当前actor具有的类型为BaseClass的所有actors。ChildActors( class
BaseClass, out actor Actor )//循环处理以当前actor作为基类的类型为BaseClass的所有actors。BasedActors( class
BaseClass, out actor Actor )//循环处理和当前actor相接触(渗入)的类型为BaseClass的所有actors。TouchingActors( class
BaseClass, out actor Actor )//循环处理从 Start 点到 End 点之间使用盒式碰撞范围 Extent 进行线性跟踪所触及的类型为BaseClass的所有actors。//在每次迭代中, HitLoc 设置为碰撞位置, HitNorm 设置为一个向外指的碰撞法线。TraceActors( class
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
BaseClass, out actor Actor, float Radius, optional vector Loc, optional bool bIgnoreHidden )//循环处理Loc位置处可见的类型为BaseClass的所有actors(如果没有指定位置,则使用当前actor的位置)。VisibleActors( class
BaseClass, out actor Actor, optional float Radius, optional vector Loc )//返回从位置Loc处(若没有指定特定位置,则使用当前actor的位置)指定Radius(半径)内碰撞到bCollideActors==true 类型为BaseClass的所有可见actors。该函数使用了Hash表,所以它要比 AllActors() 快很多。VisibleCollidingActors ( class
BaseClass, out actor Actor, float Radius, optional vector Loc, optional bool bIgnoreHidden )//返回从位置Loc处(若没有指定特定位置,则使用当前actor的位置)指定Radius(半径)内碰撞到bCollideActors==true 类型为BaseClass的所有actors。该函数使用了Hash表,所以它要比 AllActors() 快很多。CollidingActors ( class
BaseClass, out actor Actor, float Radius, optional vector Loc )//返回当前actor中包含的类型为BaseClass的所有actor组件。ComponentList( class
BaseClass, out ActorComponent out_Component )//返回“直接或间接”附加到当前actor上类型为BaseClass的所有组件。AllOwnedComponents( class
BaseClass, out ActorComponent OutComponent )//返回类型为BaseClass的所有本地PlayerControllers。LocalPlayerControllers( class
BaseClass, out PlayerController PC)

 

WorldInfo的迭代器成员函数

//迭代关卡中当前具有的所有Controllers (Player 或 AI) 。AllControllers(class
BaseClass, out Controller C)//迭代关卡中的类型为BaseClass的所有 Pawns 。可以选择性地指定迭代某个给定位置(TestLocation)周围的某个半径(TestRadius)内的 Pawns 。AllPawns(class
BaseClass, out Pawn P, optional vector TestLocation, optional float TestRadius)//迭代关卡中的类型为BaseClass的所有 NavigationPoint。AllNavigationPoints(class
BaseClass, out NavigationPoint N)//迭代关卡中的类型为BaseClass的所有 NavigationPoint。可以选择性地指定迭代某个给定位置(Point)周围的某个半径(Radius)内的 NavigationPoints。RadiusNavigationPoints(class
BaseClass, out NavigationPoint N, vector Point, float Radius)//迭代关卡中所有网络连接玩家对象的列表,同时传回了IP及端口。仅在服务器上运行。AllClientConnections(out Player ClientConnection, out int ClientIP, out int ClientPort)

UnrealScript迭代器       

 

代理

 

UnrealScript代理     

掌握UnrealScript代理      

接口

声明形式如下: 

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());

 

udn Unrealscript接口:   

udn 掌握Unrealscript接口:   

其他参考

udn UnrealScript:   

udn UnrealScript初级学习:    

 

转载于:https://www.cnblogs.com/kekec/p/4621383.html

你可能感兴趣的文章
caffe的运行create_data.sh前对VOC2007图片格式的更改
查看>>
train_val.prototxt文件和deploy.prototxt文件开头的区别
查看>>
部署 dashboard 插件
查看>>
hdu 2191 (多重背包二进制优化)
查看>>
C#中,当从数据库中查询到数据,以DataTable类型返回后,如果需要对DataTable中的数据进行筛选,可以选择下面的方式...
查看>>
19_01访问权限修饰符
查看>>
HDU1506
查看>>
Linq中常用的方法
查看>>
翻译:TRUNCATE TABLE(已提交到MariaDB官方手册)
查看>>
ASP.NET MVC 5 自动生成的代码框架
查看>>
在ASP.NET Core 2.2 中创建 Web API并结合Swagger
查看>>
新装Windows 2003 + IIS 6.0的问题
查看>>
http基础
查看>>
学习Selenium 自动化从一张藏宝图开始
查看>>
第一次冲刺阶段(五)
查看>>
Android ADB 用法
查看>>
Chaos网络库(三)- 主循环及异步消息的实现
查看>>
Oracle EBS 查看执行计划
查看>>
获取 Transaction Source
查看>>
iOS设计模式汇总
查看>>