UDN
Search public documentation:
UnrealScriptFunctionsCH
English Translation
日本語訳
한국어
Interested in the Unreal Engine?
Visit the Unreal Technology site.
Looking for jobs and company info?
Check out the Epic games site.
Questions about support via UDN?
Contact the UDN Staff
日本語訳
한국어
Interested in the Unreal Engine?
Visit the Unreal Technology site.
Looking for jobs and company info?
Check out the Epic games site.
Questions about support via UDN?
Contact the UDN Staff
UnrealScript函数
概述
声明函数
// Function to get the team a player is on
function byte GetTeam(Pawn PlayerPawn)
{
return PlayerPawn.Controller.Team;
}
函数签名
函数声明的第一行定义了如何识别函数及处理函数的方式。这称为函数的 签名 。该签名指出了函数的名称、它可以通过函数参数取入的值、它可以输出的 返回值(如果存在)、及可以通过函数修饰符指定的其他函数相关信息。 大部分基本的函数签名都以function
关键字开始(特殊的 事件函数以 event
关键字开始)。后面可以跟随任意的函数 返回类型,然后是函数名及在括号里所包含的函数参数。
从上面的函数声明示例来看,它的签名部分是:
function byte GetTeam(Pawn PlayerPawn)
GetTeam
,该函数取入到 Pawn
函数也可以具有某些属性,通过在声明中使用函数修饰符来决定。这些属性在函数签名中通常位于 function
(或 event
)关键字的前面,但是某些属性必须放置到其他位置处。
函数体
函数签名后面是一组花括号,它包含了属于该函数的所有命令。这称为函数的 主体 。当调用函数时,将会按照自上而下的顺序执行函数体中的代码。在函数体内部,您可以声明局部变量(使用关键字local
),并且可以执行任何UnrealScript代码。当遇到 返回语句或结束花括号时函数体执行结束。
从上面的函数声明示例来看,函数体部分是:
{ return PlayerPawn.Controller.Team; }
Bool
型变量初始化为 FALSE
,对象引用初始化为 None
,等)。
返回类型和返回值
function int GetHealth(Pawn PlayerPawn)
int
型值的函数。任何UnrealScript类型都可以用作为返回类型。
为了从函数中返回一个值,需要在要返回的值的后面使用 return
关键字。这称为一个 返回语句 ,它会导致函数立即停止执行并返回指定的值。如果函数声明了返回类型,那么它必须使用返回语句来返回一个值。
function int GetHealth(Pawn PlayerPawn) { return PlayerPawn.Health; }
Pawn
的 Health
变量的值。
一个函数可以有多个返回语句,但是每次函数执行时仅使用一个返回语句。如果函数体包含了多个代码执行路径(比如,当使用控制语句时),那么每个语句都必须包含一个返回值,或者必须在函数体尾部添加捕获所有情况的返回语句。
function bool IsAlive(Pawn PlayerPawn) { if(PlayerPawn.Health > 0) { return true; } else { return false; } }
Bool
值而言,函数都有一个返回语句,但是显然根据 Pawn
是否存活每次仅能执行其中一个。
函数参数
function int GetHealth(Pawn PlayerPawn)
PlayerPawn
的值,该值是到一个 Pawn
的引用。函数参数可以是任何UnrealScript类型。
在函数体中访问参数和访问任何其他变量一样;通过使用参数的名称进行访问。
函数参数修饰符
- Out
- 通常当您的调用一个函数时,UnrealScript会制作一个您传入函数的参数的一个本地副本。如果函数修改了某些参数,这对您传入的参数没有任何影响。比如,以下的代码:
function int DoSomething( int x ) { x = x * 2; return x; } function int DoSomethingElse() { local int a, b; a = 2; log( "The value of a is " $ a ); b = DoSomething( a ); log( "The value of a is " $ a ); log( "The value of b is " $ b ); }
The value of a is 2 The value of a is 2 The value of b is 4
out
修饰符告诉函数它应该修改传递给它的变量,而不是修改一个本地副本。这是有用的,比如,如果您有一个需要返回给调用者几个值的函数。你可以让调用者传递几个带有out
的变量给函数。比如:// Compute the minimum and maximum components of a vector. function VectorRange( vector V, out float Min, out float Max ) { // Compute the minimum value if ( V.X<V.Y && V.X<V.Z ) Min = V.X; else if( V.Y<V.Z ) Min = V.Y; else Min = V.Z; // Compute the maximum value. if ( V.X>V.Y && V.X>V.Z ) Max = V.X; else if( V.Y>V.Z ) Max = V.Y; else Max = V.Z; }
out
,那么尝试写出必须返回多个函数值的函数是个令人痛苦的事情。Out参数是通过引用传入的,所以在函数中修改参数的值将会立即影响原始值。这也可以用于多个值的优化,类似于C++中通过指定"const out"类型来实现。 - Optional
- 使用
optional
关键字,你可以使某些函数的参数是可选的,这为调用者提供了便利。在UnrealScript函数中,调用者没有指定的可选参数的值时,将被设置为在函数声明是指定的默认值或如果在函数声明时没有指定值时则设置它为0(也就是 0、false、""、none)。对于native函数,可选参数的默认值依赖于函数。比如,Spawn函数有一个可选的参数location 和 rotation,它们默认为actor的位置和旋转度。可选参数的默认值可以通过添加= value
来指定。比如,function myFunc(optional int x = -1)
。 - Coerce
- 关键字
coerce
强制使调用函数的参数转换为指定的类型(即使通常情况下UnrealScript将不会执行自动转换)。这对处理字符串的函数是有用的,函数将为您自动地将参数转换为字符串。(请参照虚幻字符串)。
函数参数修饰符
- Static
- 静态函数就像C语言中的全局函数一样,因为你可以在没有类的对象的引用的情况下来调用它。静态函数可以调用其它的静态函数,并且可以访问变量的默认值。静态函数不能调用非静态函数并且他们不能访问实例变量(因为它们的执行不是针对于对象的实例的)。和C++语言不一样,静态函数是虚函数并且可以在子类中重载。这在当您想在一个变量类(在编译时不能确定的但是通过变量或者表达式来引用的类)中调用一个静态函数时是有用的.
- Singular
-
singular
关键字,紧接在函数声明的前面出现,可以阻止函数对其本身进行递归调用。规则是: 如果某个actor已经在一个singular函数中,任何对这个singular的后续调用将会被跳过。这在某些情况下来避免无限的递归循环bug是有利的。例如,如果你尝试着在您的 Bump 函数中移动一个actor, 那个actor将会在移动中撞击另一个actor是有很大的可能的,从而导致了另一个对 Bump 函数的调用等等。你必须细心地避免这种行为,但是如果您没有足够的信心来通过书写代码避免这种潜在的递归情况,那么请使用singular
关键字。注意,这不仅限制于标记于sigular的特定函数 - 如果你当前位于一个正在执行的singular函数中,那么一个单独对象中的所有singular函数都将不会被执行。 - Native
- 你可以声明UnrealScript函数为
native
,这意味着该函数是可以从UnrealScript中调用的,但是事实上是在C++中实现的。比如,Actor类包含着许多native函数定义,比如:native(266) final function bool Move( vector Delta );
native
后的圆括号内的数字和在C++(使用AUTOREGISTER_NATIVE=
宏)中定义的函数编号是相对应的,并且这仅在运算符函数中有要求。Native函数将存在于DLL文件中,该DLL文件的名称和包含了UnrealScript定义的类的包的名称是一致的。 - NoExport
- 仅用于native函数。说明不应该导出这个native函数的C++函数定义。仅导出该函数的在脚本粘合版本的定义。
- Exec
- 意味着这个函数可以通过在控制台输入函数的名称来执行。仅在某些类中有效。
- Latent
- 说明了一个native函数是latent,意味着它仅能从状态代码中被调用,并且可能在游戏过去一段时间后返回。
- Iterator
- 说明了一个native函数是一个iterator,它可以通过使用
foreach
命令来在一系列的actors中循环。 - Simulated
- 不管一个actor是simulated(仿真)代理或一个autonomous(自治)代理时,函数可以在客户端执行。所有native函数也会进行自动仿真处理。(注意: 如果您使用非native函数重载一个native虚函数,那么除非指定该关键字,否则该非native函数重载将不会进行仿真处理。)
- Server
- 说明这个函数必须被发送到服务器上执行,而不是在本地客户端运行。
- Client
- 说明这个函数必须被发送到客户端执行,而不是在服务器上运行。这个标志也隐含着为该函数设置了
simulated
标记。 - Reliable
- 说明了一个复制(replicated)函数(标记为 server(服务器) 或 client(客户端))是可靠发送,意味着相对于那个Actor上的其它复制来说,它将最终地按照顺序到达另一端。
- Unreliable
- 说明了一个复制函数(标记为 服务器 或 客户端)是不可靠发送,意味着它将不能保证会以任何特定的顺序到达另一端并且如果没有足够的带宽它可能会被完全地跳过。
- Private, Protected
- 这些关键字作为相应的变量关键字时具有同样的意思。
- Operator, PreOperator, PostOperator
- 这些关键字用于声明一个称为运算符重载函数(operator)的特殊函数(和C++中的运算符函数类似)。这是UnrealScript如何知道所有的内置运算符像"+", "-", "==", 和 "||"的方式。我将不会在这篇文档中详细说明运算符函数是如何工作的,但是运算符函数的概念和C++中是类似的,所以你可以像声明UnrealScript函数或native函数一样来声明一个新的运算符重载函数。
- Event
- 当声明可以从C++引擎代码中执行的函数时,使用该关键字替换
function
关键字。请参照 事件部分获得更多信息。 - Const
- 仅用在声明为native的函数中,并且这个修饰符加在函数声明的 后面 。这个修饰符决定了这个函数是否应该在生成的头文件中作为'const'导出。示例应用:
native function int doSomething(string myData) const;
函数重载
SeePlayer
函数,您可以将以下代码添加到您的新类Demon中。
// New Demon class version of the Touch function. function SeePlayer( actor SeenPlayer ) { log( "The demon saw a player" ); // Add new custom functionality here... }
final
。=final=关键字(在关键字 function
后出现)是说:”这个函数不能被子类重载”。这可以在没有人重载的函数中使用,因为它可以提供更快的脚本代码执行速度。比如,你有一个 VectorSize 函数用于计算一个向量的大小。因为绝对没有原因导致任何人来重载它,所以声明它为 final
。另一方面,像 Touch 这样的函数是非常依赖于情境的,所以不能声明它为final。
执行函数
function SetCollision( optional bool bNewColActors, optional bool bNewBlockActors, optional bool bNewIgnoreEncroachers );
SetCollision(true, true, true);
Trace()
函数有几个可选参数:
/**
* 进行线性跟踪并查看第一个碰到的物体。
* 考虑这个actor的碰撞属性。
* 返回碰到的actor,如果碰到了关卡则返回Level,如果没有碰到任何东西则返回None。
*/
function Actor Trace
(
out vector HitLocation,
out vector HitNormal,
vector TraceEnd,
optional vector TraceStart,
optional bool bTraceActors,
optional vector Extent,
optional out TraceHitInfo HitInfo,
optional int ExtraTraceFlags
);
TraceStart
和 bTraceActors
参数但包含 Extent
参数,那么函数调用是类似于这样的(假设先前声明了 HitLocation
、 HitNormal
和 End
都为局部 Vector
型变量):
Trace(HitLocation, HitNormal, End,,,vect(4,4,4));
函数调用修饰符
- Global
- 调用最子类的全局(非状态) 函数版本
- Super
- 调用函数在父类中的相应的版本, 根据特定的情境被调用的函数可以是一个状态或者非状态函数。
- Super(classname)
- 调用指定类中的相应的函数, 根据特定的情境被调用的函数可以是一个状态或者非状态函数。
class MyClass extends Pawn; function MyExample( actor Other ) { Super(Pawn).Touch( Other ); Global.Touch( Other ); Super.Touch( Other ); }
BeginPlay()
函数在一个actor将要进入一个要播放的游戏时被调用。BeginPlay()函数在Actor类中实现而且它包含着需要执行的某些重要的功能。现在,假如您想在新类MyClass中重载BeginPlay()函数,来增加某些新的功能。为了安全地实现上述功能,您需要调用父类的BeginPlay()函数。
class MyClass extends Pawn; function BeginPlay() { // Call the version of BeginPlay in the parent class (important). Super.BeginPlay(); // Now do custom BeginPlay stuff. //... }
事件
event
关键字声明的而不是通常的 function
关键字。
比如,当一个actor和另一个actor接触,引擎会调用它的 Touch 函数来告诉它是谁正在接触它。
event Touch( Actor Other, PrimitiveComponent OtherComp, vector HitLocation, vector HitNormal );
Touch
函数,你可以在接触事件发生时采取特殊的行动:
// Called when something touches this actor.
function Touch( actor Other )
{
`log( "I was touched!")
Other.Message( "You touched me!" );
}
`log
命令向日志文件中写入了一个消息(除了格式规则以外,这和Basic语言的"print"及C语言的"printf"是类似的)。第二,它调用了在Other actor中的"Message"函数。调用在其它actors中的函数在UnrealScript是一个常用的操作,大体上和面向对象的语言比如Java是一致的,因为它为actors间彼此的交流提供了一个简单的方法。
函数递归
// Function to compute the factorial of a number.
function int Factorial( int Number )
{
if( Number <= 0 )
return 1;
else
return Number * Factorial( Number - 1 );
}
静态函数
var class C; var classPC; class'SkaarjTrooper'.static.SomeFunction(); // Call a static function // in a specific class. PC.static.SomeFunction(); // Call a static function in a variable class. class (C).static.SomeFunction(); // Call a static function in a //casted class expression.
Timers(计时器)
Timer()
函数被调用或者一次、或者重新发生。
UnrealScript计时器仅是在每个Actor内部作为一个structs数组来实现的(一个Actor可以有多个还没有被触发的计时器) 。这个struct包含了在计时器过期前所剩余的时间的数量、计时器到期时所要调用的函数等。
一般游戏主循环每帧ticks(更新)每个Actor一次,并且每个Actor的 Tick()
函数包含一个调用函数 UpdateTimers()
,它会检查任何将要过期的计时器并调用它们适当的UnrealScript代码。
时间间隔大小限于每个帧之间的时间间隔长度,但是对硬件和OS资源没有要求。所有的这些是在C++代码中实现的,所以您可以在不必担心可能引起的任何后果的情况下安全地更新成百个UnrealScript计时器。当然,您不会想使所有的计时器同时地过期或者在每一个帧过期,因为当这是计时器被激活时要以较慢的速度执行脚本代码。
计时器函数仅在Actor的子类中存在。
您可以创建具有不同时间量的多个计时器。每个计时器有一个唯一的目标函数(默认为 Timer() )。
- function SetTimer(float inRate, optional bool inbLoop, optional Name inTimerFunc)
- 启动
inRate
秒后触发的计时器。如果 inbLoop 为真则计时器将会循环。==inTimerFunc== 定义了要调用的函数,默认情况下这个函数是 Timer() ,这个值也用于识别多个计时器。 - ClearTimer(optional Name inTimerFunc)
- 停止一个正在运行的计时器。
- bool IsTimerActive(optional Name inTimerFunc)
- 如果给定的计时器处于激活状态,则返回true。
- float GetTimerCount(optional Name inTimerFunc)
- 返回计时器的计数器的值,也就是自从上一次执行计时器开始所过的秒数。如果计时器没有启动,则返回-1。
- float GetTimerRate(optional name TimerFuncName = 'Timer')
- 返回计时器的量,
GetTimerRate('SomeTimer') - GetTimerCount('SomeTimer')
将返回计时器的剩余时间。
内置函数
Object
、 Actor
等),当使用UnrealScript创建新类以便在游戏中使用时知道这些函数是非常有用且方便的。
创建对象
为了在UnrealScript中创建一个新的对象,您将会根据这个对象是否是一个Actor来使用这两个函数其中的一个。对于Actors,您将会使用Spawn函数,声明在Actor.uc
文件中。对于不是从Actor类派生的类,您必须使用 new
操作符。New操作符的语法和其它的函数不同。除了一个可选择的参数列表,你必须指定新的对象的类及可选择的模板对象。new操作符没有UnrealScript声明,但是这里是函数声明的样子:
native final operator function coerce Object new ( object InOuter, name InName, int InFlags, class InClass, object InTemplate );
- InOuter
- (可选的) 用于作为新创建的对象的
Outer
的对象 。如果没有指定,则此对象的Outer将被设置为一个仅当游戏运行时存在特殊包,该包被称为"临时包"的。 - InName
- (可选的)新对象的名称。如果没有指定,此对象将以
ClassName_##
的形式给定一个唯一的名称,每次创建一个这个类的实例,这里的##会不断增加。 - InFlags
- (可选的,目前还不能使用,因为对象标志是64位的)创建对象时所要使用的对象标志。有效值是:
-
0x0000000100000000
- 支持编辑器的 取消/恢复 操作。(RF_Transactional) -
0x0000000400000000
- 可以被外部文件引用。(RF_Public) -
0x0000400000000000
- 不能保存到磁盘中。(RF_Transient) -
0x0010000000000000
- 不能在游戏客户端加载对象。(RF_NotForClient) -
0x0020000000000000
- 不能在游戏服务器上加载对象。(RF_NotForServer) -
0x0040000000000000
- 不能在编辑器中加载对象。(RF_NotForEdit) -
0x0008000000000000
- 即使对象没有被引用,也要保持对象以便编辑。(RF_Standalone)
-
- InClass
- 用于创建一个实例的类。
- InTemplate
- 用于初始化新的对象的属性值的object。
ObjectVar = new[(InOuter, InName, InFlags)] <class'InClass'>[(InTemplate)];
function CreateALight() { local LightFunction NewObj; NewObj = new class'Engine.LightFunction'; }
function CreateALight() { local LightFunction NewObj; NewObj = new(Self,'NewLight') class'Engine.LightFunction'; }
var LightFunction LightFunctionTemplate; function CreateALight() { local LightFunction NewObj; NewObj = new(None,'NewLight') class'Engine.LightFunction' (LightFunctionTemplate); } defaultproperties { Begin Object Class=LightFunction Name=MyLightFunctionArchetype End Object LightFunctionTemplate=MyLightFunctionArchetype }
整型函数
- int Rand( int Max )
- 返回0到Max-1之间的一个随机值。
- int Min( int A, int B )
- 返回两个值中的最小值。
- int Max( int A, int B )
- 返回两个值中的最大值。
- int Clamp( int V, int A, int B )
- 返回区间限定到A与B之间的第一个数值。
浮点型函数
- float Abs( float A )
- 返回该数值的绝对值。
- float Sin( float A )
- 返回以弧度表示的数值的正弦值。
- float Cos( float A )
- 返回以弧度表示的数值的余弦值。
- float Tan( float A )
- 返回以弧度表示的数值的正切值。
- float ASin( float A )
- 返回以弧度表示的数值的反正弦值。
- float ACos( float A )
- 返回以弧度表示的数值的反余弦值。
- float Atan( float A )
- 返回以弧度表示的数值的反正切值。
- float Exp( float A )
- 返回常量“e”的A次幂。
- float Loge( float A )
- 返回A的对数(底数为“e”)。
- float Sqrt( float A )
- 返回A的平方根。
- float Square( float A )
- 返回A的平方 A*A。
- float FRand()
- 返回0.0到Max1.0之间的一个随机值。
- float FMin( float A, float B )
- 返回两个值中的最小值。
- float FMax( float A, float B )
- 返回两个值中的最大值。
- float FClamp( float V, float A, float B )
- 返回区间限定到A与B之间的第一个数值。
- float Lerp( float A, float B, float Alpha )
- 返回A与B之间的线性插值。
- float Smerp( float Alpha, float A, float B )
- 返回A与B之间的Alpha平滑非线性插值。
- float Ceil ( float A )
- 向上舍入
- float Round ( float A )
- 正常舍入
字符串函数
- int Len( coerce string S )
- 返回字符串的长度。
- int InStr( coerce string S, coerce string t)
- 第二个字符串在第一个字符串中的偏移量;如果不存在,则返回值为-1. string Mid ( coerce string S, int i, optional int j ) 返回字符串S的中间部分,即从字符i开始后连续j个字符的字符串(或者如果没有指定j,则返回字符i后面的所有字符)。
- string Left ( coerce string S, int i )
- 返回字符串S的i个最左侧字符。
- string Right ( coerce string] S, int i )
- 返回字符串S的i个最右侧字符。
- string Caps ( coerce string S )
- 将字符串S转换为大写。
- string Locs ( coerce string S)
- 返回字符串S的小写表示(v3323及以上)。
- string Chr ( int i )
- 返回ASCII表中的一个字符。
- int Asc ( string S )
- 返回一个字符的ASCII码值(仅使用字符串的第一个字符)
- string Repl ( coerce string Src, coerce string Match, coerce string With, optional bool bCaseSensitive )
- 在源字符串中使用字符串
With
替换字符串Match
。(v3323及以上) - string Split(coerce string Text, coerce string SplitStr, optional bool bOmitSplitStr)
- 在第一次出现字符串
SplitStr
处分割字符串Text
,并返回字符串Text
的剩余部分。如果=bOmitSplitStr=为true,=SplitStr=将会从返回的字符串中被忽略。 - array<string> SplitString( string Source, optional string Delimiter=",", optional bool bCullEmpty )
- 通过使用一个单独的表达式将一个字符串分割为一个字符串数组的封装函数。
- JoinArray(array<string> StringArray, out string out_Result, optional string delim = ",", optional bool bIgnoreBlanks = true)
- 通过使用指定的分隔符从一个字符串数组创建一个单独的字符串,可以选择是否忽略空格。
- ParseStringIntoArray(string BaseString, out array<string> Pieces, string Delim, bool bCullEmpty)
- 分解一个具有分界符的字符串为一个字符串数组的多个元素。
- A == B
- 比较,如果两个字符串相同则返回true(区分大小写)。
- A ~= B
- 比较,如果两个字符串相同则返回true(大小写不敏感)。
- A != B
- 比较,如果两个字符串不同则返回true(区分大小写)。
Vector函数
- vector vect( float X, float Y, float Z )
- 使用给定分量创建一个新的向量。
- float VSize( vector A )
- 返回向量的欧几里得大小(元素开平方后值的总和的平方根)
- vector Normal( vector A )
- 返回一个大小为1.0的向量,面向指定向量的方向。
- Invert ( out vector X, out vector Y, out vector Z )
- 反转由三个坐标轴向量指定的坐标系统。
- vector VRand ( )
- 返回一个均匀分布的随机向量。
- vector MirrorVectorByNormal( vector Vect, vector Normal )
- 围绕指定的正规向量镜像一个向量。
调试函数
以下函数可以帮助您调试代码。- LogEx( ELoggingSeverity Severity, name Category, coerce string Msg )
- 使用给定的严重级别和类别来记录一个消息。这个函数比标准的 log() 函数提供了更多的控制。它允许您在运行时根据严重级别和目录来过滤日志信息。
- LogFatal( name Category, coerce string Msg )
- 用于调用
LogEx(LOG_FATAL, Category, Msg)
函数的缩写。 - LogError( name Category, coerce string Msg )
- 稍后完成
- function LogWarn( name Category, coerce string Msg )
- 稍后完成
- LogInfo( name Category, coerce string Msg )
- 稍后完成
- LogDebug( name Category, coerce string Msg )
- 稍后完成
- LogTrace( name Category, coerce string Msg )
- 稍后完成
- ScriptTrace()
- 转存当前的脚本调用堆栈到一个日志文件中
- Name GetFuncName()
- 返回当前正在调用的函数的名称
- DumpStateStack()
- 记录当前的状态栈