UnrealScript语言基础

总体特征

(1)大小写不敏感。关键字、宏、变量名、函数名以及类名不区分大小写;变量名可以与关键字同名

(2)局部变量、成员变量未初始化时,会被编译器初始化

(3)没有全局变量、全局函数,所有东西必须写入类中

(4)一个uc文件中,有且只能写一个类,且文件名与类名要一致

(5)变量和函数默认为public类型,函数默认为虚函数

(6)不支持函数重载,但支持运算符重载和缺省参数

(7)不支持异常处理,不支持模板泛型

(8)无需显示导入外部包,uc文件可以使用当前包及之前编译的包中定义的类型和函数

(9)没有构造函数,没有析构函数,通过引用计数机制进行垃圾回收

(10)没有指针类型;数值型、bool型、名称、字符串、枚举、数组、结构体为值类型;类、接口为引用类型

(11)只支持一维数组

(12)没有静态变量,没有union类型

(13)所有对象都从Object类单根继承,支持接口多继承

(14)解释执行,运行时安全

预处理

编译命令参数

make -intermediate // 编译脚本,并将预处理结果保存到 UDKGame\PreProcessedFiles\<package>\<class>.uc

make -debug    // 定义名为debug的宏变量,启用`logd宏函数,并编译脚本

make -final_release    // 定义名为final_release的宏,禁用`log、`logd、`warn、`assert宏函数,并编译脚本

注:

`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文件后要进行全量编译

条件编译

`if(`notdefined(USE_ASYNCHRONOUS_MOVE))
     // ...
`endif

`if(`isdefined(USE_ASYNCHRONOUS_MOVE))
    // ...
`else
    // ...
`endif

宏定义、宏取消

`define USE_ASYNCHRONOUS_MOVE
`define WEAPON_CONFIG 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)
// 取消宏定义
`undefine(INCLUDE_GAME_STATS)

文件包含

`include(TGOnlineLogicMacros.uci)

特殊宏

`define MyMacro(p1, p2, p3, p4) “This macro contains `# parameters.”// `#为4,为宏参数的个数

常量

作用范围

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

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

3. 当前类中定义的常量可直接访问:PI;访问外部类TGTest中定义的常量:class‘TGTest‘.const.PI

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

变量

数值型

类型 长度 范围 举例

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

1.23E2(不支持科学计数法,编译失败)

1.0/0.0=1.#INF00(比任何浮点数都大)

-1.0/0.0=-1.#INF00(比任何浮点数都小)

数值型间转换规则

1. 自动隐式转换

2. 精度高向精度低转换:

(a) 内存截断   (b) 精度丢失

>>>补零右移运算符

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

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

(2)枚举第一个元素的值为0,后续依次+1;不能随意地指定新的起始值

(3)在defaultproperties中对枚举成员变量初始化时,不能带枚举类型前缀,否则会失效

(4)枚举类型(等于枚举元素的个数)、类型.前缀_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]

(5)整型与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

(6)使用GetEnum函数将enum转换成name

local name m;
m = GetEnum(Enum‘ENetRole‘, ENetRole.ROLE_Authority); // m=‘ROLE_Authority‘

静态数组

(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处起删除2个元素 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;
};

结构体中不能有函数方法,成员的初始化放在structdefaultproperties块中

(2)结构体只能在类中定义

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

(3)支持结构体继承

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

(4)函数中对进行结构体赋值和拷贝

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"

(5)在类的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)
                 )}
}

(6)支持==与!=比较(两个结构体内容完全一致则相等,否则不相等)

常用结构体 -- 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)do...until循环   c++: do...while

(2)新增foreach循环类型

函数

关键字 说明
simulated 能被ENetRole=ROLE_SimulatedProxy的对象执行
final 不允许被子类重写
native 使用C++实现
event 生成脚本的C++调用函数,实现C++调用脚本的功能
latent 延迟函数(只能在state的label块中调用)
client client远程函数,调用后立即返回,无返回值
server server远程函数,调用后立即返回,无返回值

参数

关键字 说明
coerce 自动进行类型转换
out 使用引用传入值类型变量,输出型参数
const 常量参数,函数中不允许改变参数
optional 可选参数,必须放到函数参数列表的最右边
时间: 2024-10-14 05:54:12

UnrealScript语言基础的相关文章

Oracle SQL语言基础及环境准备_超越OCP精通Oracle视频教程培训26

Oracle SQL语言基础及环境准备_超越OCP精通Oracle视频教程培训26 本课程介绍: Oracle视频教程,风哥本套oracle教程培训是<<Oracle数据库SQL语言实战培训教程>>的第1/5套:SQL语言之基础入门及环境准备.主要学习Oracle数据库SQL语言基础介绍.PL/SQL语言介绍.数据库SQL对象与数据类型介绍.SQL语言实战环境准备等. Oracle SQL语言之基础及环境准备,课程内容详细如下: Oracle数据库SQL语言基础介绍Oracle数据

Swift语言指南(一)--语言基础之常量和变量

Swift 是开发 iOS 及 OS X 应用的一门新编程语言,然而,它的开发体验与 C 或 Objective-C 有很多相似之处. Swift 提供了 C 与 Objective-C 中的所有基础类型,包括表示整数的 Int,表示浮点数的 Double 与 Float,表示布尔值的 Bool,以及表示纯文本数据的 String. Swift 还为两个基本集合类型 Array 与 Dictionary 提供了强大的支持,详情可参考 (集合类型)Collection Types. 与 C 语言类

02 java语言基础

常量:字面值常量(字符串,字符,整数,小数,布尔,null),自定义常量,''这个不是字符常量,""这个是字符串常量 进制: 02.01_Java语言基础(常量的概述和使用)(掌握) A:什么是常量 在程序执行的过程中其值不可以发生改变 B:Java中常量的分类 字面值常量 自定义常量(面向对象部分讲) C:字面值常量的分类 字符串常量 用双引号括起来的内容 整数常量 所有整数 小数常量 所有小数 字符常量 用单引号括起来的内容,里面只能放单个数字,单个字母或单个符号 布尔常量 较为特

嵌入式 Linux C语言——C语言基础

嵌入式 Linux C语言--C语言基础 一.数据类型 1.基本数据类型 数据类型是创建变量的模型.变量名是连续存储空间的别名,程序中使用变量命名存储空间,通过变量可以使用存储空间.变量所占的内存大小取决于创建变量的数据类型. 2.有符号和无符号 有符号数中数据类型的最高位用于标识数据的符号,最高位为1表示为负数,最高位为0表示为正数. 计算机中有符号数通常使用补码表示,正数的补码为正数本身,负数的补码为负数的绝对值的各位取反后加1. 计算机中无符号数通常使用原码表示,无符号数默认为正数,没有符

C#语言基础

第一部分 了解C# C#是微软公司在2000年7月发布的一种全新且简单.安全.面向对象的程序设计语言,是专门为.NET的应用而开发的.体现了当今最新的程序设计技术的功能和精华..NET框架为C#提供了一个强大的.易用的.逻辑结构一致的设计环境.其特点: 语言简洁 保留了C++的强大功能: 快速应用开发功能: 语言的的自由性: 强大的Web服务器控件: 支持跨平台: 与XML相融合: 第二部分 C#语言基础: 一.C#项目的组成结构: 1.项目后缀 .config——配置文件(存放配置参数文件)

OC语言基础知识

OC语言基础知识 一.面向对象 OC语言是面向对象的,c语言是面向过程的,面向对象和面向过程只是解决问题的两种思考方式,面向过程关注的是解决问题涉及的步骤,面向对象关注的是设计能够实现解决问题所需功能的类. 术语:OO面向对象.OOP面向对象编程 二.类 (一)关于类 类的设计只关注三个东西:类名.属性和方法 注意:一般名词都是类,拥有相同属性和行为的对象都可以抽象为一个类,类名是标识符的一种,需要符合规范,通常类名的第一个字母大写,且不能有下划线,如果有多个单词则使用驼峰标识.在对方法进行类的

【quick-cocos2d-x】Lua 语言基础

版权声明:本文为博主原创文章,转载请注明出处. 使用quick-x开发游戏有两年时间了,quick-x是cocos2d-Lua的一个豪华升级版的框架,使用Lua编程.相比于C++,lua的开发确实快速便捷了许多,下文只是lua这门语言的一个基础知识点,没有涵盖整个Lua的内容,但是作为对lua入门的初步了解还是可以的,由于内容精简了不少,所以语言上可能会有点跳跃,但是问题不大. 要了解一门语言,首先要了解的是语言的标识符.保留字.常量和变量,命名规范和注释以及数据类型等.然后是运算符.控制流语句

C# 语言基础(简单的输出 输入语句 和 加法运算符)

int a, b; Console.Title = "C# 语言基础-第一堂课";// 标题 Console.BackgroundColor = ConsoleColor.DarkRed;//设置控制台的背景颜色 Console.WriteLine("幼儿园大班第一节课"); Console.WriteLine("请输入a的值,按回车");//输出语句,自动换行 Console.Write("a="); //输出语句,自动不换

R语言基础

##数据获取 x1=round(runif(100,min=80,max=100)) x2=round(rnorm(100,mean=80, sd=7)) x3=round(rnorm(100,mean=80,sd=18)) x3[which(x3>100)]=100 num=seq(2005138101,length=100) x=data.frame(num,x1,x2,x3) write.table(x, "grade.txt") ##数据分析 y=read.table(&