WeaponFiringMode:我只要路径,接口,优化Weapon和AttackInterface
Posted on 2012-12-28 10:35 neocsl 阅读(383) 评论(0) 编辑 收藏 举报
让我们来终结AIController所要解决的全部问题。我们是一群酷家伙。
1.平滑的调整转向的问题
function Tick(float DeltaTime) { local rotator DesiredRotation; super.Tick(DeltaTime); if(Pawn!=none&&Pawn.Health>0) { DesiredRotation=Rotator(GetFocalPoint()-Pawn.Location); Pawn.FaceRotation(RLerp(Pawn.Rotation,DesiredRotation,3.125f*DeltaTime,true),DeltaTime); } }
2.使用一种低性能的寻路方式
先使用FastTrace检测Pawn和目标之间的直线有没有障碍,如果有CanReachDestination直接返回false。检测的线体积是角色的碰撞圆柱。
function bool CanReachDestination(vector CheckDestination) { local Actor HitActor; local vector HitLocation,HitNormal,pathCollisionExtent; }
使用FastTrace这种方式高效检测,然后使用TraceActors
3.刚才收到新华社的最新消息,强制类型转换是一种慢节奏的运行效率。因此使用Interface可以高效的减少该方面导致的性能损耗。在Controller中声明一个变量,这个变量在Possess中指代正在占用的pawn。
要研究一个机制,往往他会和外部一些事物有一些牵连。就像青豆和天吾在冥冥之中有所联系。因此一个类如果和另外的内容有牵连,最好的方法是将这些内容连根拔起看个究竟。
Factory和Route是重要的一环,其次Interface这个抽象内容也有联系。Interface知道的是划定一下敌人范围,这可能在玩家死亡时剔除场景中的所有敌人有很大的帮助 。我使用的方法是,只要玩家在一个区域内达成一定的要素,再次死亡就不会激活该区域的敌人触发,而敌人是生成器的方式产生的。将生成器通过一种事件来作废,什么事件呢?最后一个敌人或是“看门人”是最好的方法。
可以看到这里的方法并不难,获取Route的位置。
4.接口
Pawn中实现接口,需要实现他们能不能攻击或者被攻击。 、
FireMode.uc使用一个圆柱检测敌人伤害,它最大化的节省了性能,继承自Object而非Projectile。他使用VisibleCollidingActors来遍历碰撞。碰撞遍历的Actor和武器的发射方向。
有一个AntAttackInterface是这个武器的拥有者,WeaponOwner。
class AntWeaponFireMode extends Object; var AntAttackInterface WeaponOwner; function SetOwner(AntAttackInterface NewWeaponOwner) { if(NewWeaponOwner==none) return; WeaponOwner=NewWeaponOwner; }
武器的射击角度
function float GetAttackingAngle() { return 0.95f; }
毁灭之,也许我之前的很多代码都造成了内存泄露,在Debug的时候一定要执行清空动作
function Destroy() { StopFire(); WeaponOwner=none; }
StopFire中WeaponOwner接口能一窥GetActo的东西。GetActor推测应该和武器有很大的关系。
function StopFire() { if(WeaponOwner!=none) { WeaponOwner.GetActor().ClearTimer('Fire'),self); } }
StartFire也是一个重要的部分,该函数内部有发弹频率和pawn的描述,一会看看具体内容。
function StartFire() { local float FiringRate; local AntPawn AntPawn; if(WeaponOwner!=none) { Fire(); //what he is doing here?Wait Down There AntPawn=AntPawn(WeaponOwner); if(AntPawn!=none) { FiringRate=AntPawn.BaseAttackTime; //`SinceTime kind if(AntPawn.AttackSpeed>-1) { FiringRate/=(1.f+AntPawn.AttackSpeed); } WeaponOwner.GetActor().SetTimer(FiringRate,true,'Fire',self); } } }
有一个检索武器是否处于开火的函数,其实就是检测Timer函数是否在执行,用IsTimerActive?
function bool IsFiring() { if(WeaponOwner!=none) { return WeaponOwner.GetActor().IsTimerActive('Fire',self); } }
开火函数Fire,在StartFire中被调用。并且在子类中不被继承
final function Fire() { local vector FireLocation; local Rotator FireRotation; local Actor CurrentEnemy; if(WeaponOwner==none) return; CurrentEnemy=WeaponOwner.GetEnemy(); if(CurrentEnemy==none) { StopFire(); return; } WeaponOwner.GetWeaponFiringLocationAndRotation(FireLocation,FireRotation); BeginFire(FireLocation,Rotator(currentEnemy.Location-FireLocation),CurrentEnemy); }
BeginFire到底是怎么一回事?这要影响到每一种武器的详细射击模式了,如果他们再次回到了Projectile那就叫人不高兴了