function Timer() { }
Timers是一种特殊类型的函数,它将会在特定的时间量过去后被调用,并且可以强制不断地执行它。这使得它们是适合我们的目的的理想函数。
3. 现在,我们开始为我们的Timer函数添加新的功能。把鼠标光标放在开始花括号({)的后面,并按下回车键。然后按Table键来缩进这个代码端。输入以下代码:
if (Controller.IsA('PlayerController') && !IsInPain() && Health 这段代码乍一看可能有点复杂,但是实际上它是非常简单的。当把它分为几部分时或许会更加容易理解。 if () { } 开始是一个IF语句。它实质上是说如果圆括号内的表达式为真,那么将会执行放在花括号({})中的代码。 Controller.IsA('PlayerController') 这段代码检测这个Pawn是否是由玩家控制的。如果是,那么我们将会继续执行下一段代码。 IsInPain() 这个表达式是检测这个Pawn是否在引发痛苦的体积中。如果他不在(注意!标记),我们将会继续执行下一段代码。 Health < SuperHealthMax 这个表达式用于检测这个Pawn的Health(生命值)是否小于允许的最大生命值的绝对值。如果是,那么将会执行花括号 ({})间的代码 4. 把光标放在If语句的开始的花括号({)的后面并按下回车键。然后按下Tab键缩放这段代码。输入以下代码: Health = Min(Health+RegenPerSecond, SuperHealthMax); 这里我们取入了Health(生命值)的当前值和添加到它上的重新生成的量。然后把这个值和允许的最大生命值相比较,把两个之中较小的值分配给Pawn的Health(生命值)。从本质上讲,相对于允许的最大生命值,当它超过结果计算得到的生命值时,执行再生功能。 5. 现在已经完成了Timer函数本身,如下所示: function Timer() { if (Controller.IsA('PlayerController') && !IsInPain() && Health { Health = Min(Health+RegenPerSecond, SuperHealthMax); } } 6. 我们需要一种方法来确保这个Timer在每秒都会执行,以便可以真正地执行生命值再生。先前我们讨论了计时器是一种特殊类型的函数。为了启动一个计时器,则必须执行另一个称为SetTimer的函数。唯一需要考虑的问题是我们在哪里放置到这个SetTimer函数的调用,以便当游戏开始时可以执行这个函数?就是这样巧合,在所有的Actors中有一个称为PostBeginPlay的函数,它基本会在游戏启动后立即执行。 以下是RegenPerSecond变量的声明,在Timer函数的上面输入以下代码: simulated function PostBeginPlay() { } 您或许会注意到使用了新的关键字Simulated。暂时请不要担心这个问题。它是一个必须网络交互的关键字,这是一个复杂的主题,我们将在稍后的部分对其进行详细解释。 7. 把光标放在PostBeginPlay函数的开始花括号({)后面并按下回车键。然后按下Tab键来缩放这部分代码。并输入以下代码: Super.PostBeginPlay(); SetTimer(1.0,true); 这个函数中的第一行说明了应该在父类中执行PostBeginPlay函数。这意味着这时将会调用PostBeginPlay的UTPawn版本。然后,第二行启动了Timer,它将会每秒钟执行一次,并且把它设置为循环状态。 8. 随着那段代码的完成,自定义的Pawn类应该也接近完成了。整个Pawn类如下所示: class UTPawn_SuperRegen extends UTPawn; var Int RegenPerSecond; simulated function PostBeginPlay() { Super.PostBeginPlay(); SetTimer(1.0,true); } function Timer() { if (Controller.IsA('PlayerController') && !IsInPain() && Health Health = Min(Health+RegenPerSecond, SuperHealthMax); } } defaultproperties { RegenPerSecond=10 } 9. 在ConTEXT中保存UTPawn_SuperRegen.uc文件,以便保存您的进展。 现在,已经完成了自定义的Pawn类,下一步是开始书写mutator(设置方法)本身的代码。我们将会在下个指南中解决这个问题。 2.4 –mutator(设置方法)的脚本 1. 如果还没有准备好,那么打开ConTEXT。 2. 从File (文件)菜单中选择New(新建)或者按下工具条上的New File(新建文件)按钮。 3. 使用工具条中的Select Active Highlighter(选择激活的轮廓)下拉列表选择UnrealScript。 4. 在新脚本的第一行输入以下代码: class UTMutator_SuperRegen extends UTMutator; 和Pawn类一样,这行命名了这个类UTMutator_SuperRegen并指出了它是一个具有UTMutator类内置的所有功能并且也具有我们添加的功能的mutator(设置方法)。 5. 按下回车键两次并输入以下脚本代码: simulated function PostBeginPlay() { } 正如您在自定义的Pawn类中所看到的,PostBeginPlay将会在早期执行。这个函数内是使用我们的自定义Pawn类替换GameInfo的DefaultPawnClass的地方。 6. 现在,把光标放置在开始花括号({)的后面并按下回车键。然后按下Tab键来缩放这部分代码并输入以下信息: Super.PostBeginPlay(); WorldInfo.Game.DefaultPawnClass = class'MasteringUnrealScript.UTPawn_SuperRegen'; 这段代码的第一行将会导致执行父类的PostBeginPlay函数。这确保了将会执行位于PostBeginPlay函数中的所有潜在的类。第二行包含了我们的mutator(设置方法)的主要信息。WorldInfo.Game是到当前的GameInfo的简单引用。我们正在访问它的DefaultPawnClass变量并设置它使用我们的自定义的Pawn类。 7. 完成mutator编码所剩余的部分便是添加defaultproperties(默认属性)代码块。在PostBeginPlay函数后,添加以下代码: defaultproperties { GroupNames[0] = \} GroupNames数组是一个标记mutators(设置方法)的简单方法,它可以并放置同时加载可能相互冲突的两个mutators。这是很重要的,因为另一个mutator使用它自己的Pawn替换掉Pawns也是很可能的。这将会覆盖我们的mutator的功效,从而使它无用。因为不会同时加载具有相同组名称的两个mutators,所以这可以保证一个mutator不会被另一个所覆盖。我们已经选择了标签PLAYERMOD,因为那是mutator实际做的内容。 8. 现在已经完成了mutator类。整个mutator类如下所示: class UTMutator_SuperRegen extends UTMutator; simulated function PostBeginPlay() { Super.PostBeginPlay(); WorldInfo.Game.DefaultPawnClass = class'MasteringUnrealScript.UTPawn_SuperRegen'; } defaultproperties { GroupNames[0] = \}