紧接着Enemy将要查看EnemyController,EnemyController继承自AIController。
一个典型方法让敌人找到玩家
var Pawn Enemy;
event Tick(float DeltaTime)
{
local PlayerController PC;
if(Enemy==none)
{
Foreach LocalPlayerControllers(class'PlayerController',pC)
{
if(PC.Pawn!=none)
Enemy=PC.Pawn;
}
}
}
在foreach中如果找不到玩家的pawn,可以让敌人暂时停下
pawn.Acceleration.x=0;
Pawn.Acceleration.y=0;
有一个官方函数PawnDied(Pawn inpawn),旨在表述pawn死了的执行动作
function PawnDied(pawn inpawn)
{
if(inpawn==pawn)
Enemy=none;
super.PawnDied(inpawn);
}
下来是重点,寻路一直是个有难度的地方。这里提到两个函数
1.MoveTo (vector NewDestination, optional Actor ViewFocus, optional float DestinationOff)
该函数在没有寻路的情况下可以让pawn走到一个坐标位置
2.MoveToward((Actor NewTarget, optional Actor ViewFocus, optional float DestinationOffset)
可以让一个pawn走向一个Actor。
因此最简单的一种方法是在controller中写一个状态
var actor Enemy;
auto state Follow
{
Begin:
Enemy=GetALocalPlayerController().Pawn;
MoveToward(Enemy,Enemy,128);
goto 'Begin'; //因为MoveToward只能执行一次,用该方法循环执行
}
下来这个环节是重要的寻路算法,同时使用了MoveToward和MoveTo两个函数,前者是当寻路成立时可以直接到达目标Actor,后者是在寻路不成立时让该pawn暂时先行前进到临时TempDest目标点。
自动进入Idle然后获取Player.
auto state Idle
{
event SeePlayer(pawn inpawn) //参数是看见的pawn
{
local pawn Player;
if((Player=GetALocalPlayerController().pawn)!=none)
{ super.SeePlayer(Player);
Enemy=Player;
Gotostate('Follow');}
}
Begin:
}
获取了Enemy将进行寻路
state Follow
{
ignores SeePlayer;
//该函数寻路看能否找到目标点
function bool FindNavMeshPath()
{
// Clear cache and constraints (ignore recycling for the moment)
NavigationHandle.PathConstraintList = none;
NavigationHandle.PathGoalList = none;
// Create constraints
class'NavMeshPath_Toward'.static.TowardGoal( NavigationHandle,Enemy ); //寻找Enemy
class'NavMeshGoal_At'.static.AtActor( NavigationHandle, Enemy,32 );
// Find path
return NavigationHandle.FindPath();
}
Begin:
if(NavigationHandle.ActorReachable(Enemy)) //无障碍物,最好的情况就是能找到
{
MoveToward( Enemy,Enemy ); //直接走向敌人 AAAAAAAAAAaaaaAAAAAAAA
}
else if(FindNavMeshPath) //如果有障碍,在寻路状态,则进入临时目标点
{
NavigationHandle.SetFinalDestination(Enemy.Location); //敌人位置
// move to the first node on the path
if( NavigationHandle.GetNextMoveLocation( TempDest, Pawn.GetCollisionRadius()) )
{
MoveTo( TempDest, Enemy ); //先找到临时节点,Enemy是最重要找的对象
}
}
else //最糟的结果是找不到,可能玩家已经死了。也就没必要再找了
{
GotoState('Idle');
}
Goto 'Begin'; //保持了更新查找
}
《求生之路》中有些敌人是在场景中Idle的状态,而有些敌人一生成就会朝玩家涌过来。只要在Idle中不用seePlayer而是直接遍历将会生成涌向玩家的敌人。
在前面的AAAAAAAAAAaaaaAAAAAAAA标记地方修改进入Attacking状态攻击敌人
MoveToward(Enemy,Enemy,300);
if(VSize(Enemy.Location-Location)<500)
GotoState('Attacking');
以下是攻击状态
state Attacking
{
function NotifyTakeHit(Controller InstigatedBy, vector HitLocation, int Damage, class<DamageType> damageType, vector Momentum)
{
PopState();
super.NotifyTakeHit(InstigatedBy, HitLocation, Damage, damageType, Momentum);
}
event BeginState(Name PreviousStateName)
{
super.BeginState(PreviousStateName);
AntEnemy(pawn).StartedAttack();
}
event EndState(Name PreviousStateName)
{
super.EndState(PreviousStateName);
AntEnemy(pawn).EndedAttack();
}
}
攻击状态结束
如果受到伤害将进入受伤状态,在子类中将实现受伤动画播放,在这期间体制所有的latent函数,以及固定敌人角色的位置。这边是硬直的前身。
state Hurt
{
StopLatentExecution(); //停止所有的行为state
Pawn.Acceleration.X=0;
Pawn.Acceleration.Y=0;
Pawn.Acceleration.Z=0;
//播放受伤动画
PopState();
}