欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 文旅 > 文化 > UE中通过AAIController::MoveTo函数巡逻至目标点后没法正常更新巡逻目标点

UE中通过AAIController::MoveTo函数巡逻至目标点后没法正常更新巡逻目标点

2025/4/19 17:57:00 来源:https://blog.csdn.net/qq_38785599/article/details/147315807  浏览:    关键词:UE中通过AAIController::MoveTo函数巡逻至目标点后没法正常更新巡逻目标点

敌人巡逻的逻辑如下:

 敌人在游戏一开始的时候就通过moveto函数先前往首先设定的patroltarget目标,在距离patroltarget距离为patroradius(200unit)之内时就可以通过checkpatroltarget函数更新新的patroltarget目标,随后前往新的patroltarget

---------------------伪代码-----------------

BeginPlay()

        MoveToTarget(PatrolTarget);

MoveToTarget(PatrolTarget)
    FAIMoveRequest MoveRequest;
    MoveRequest.SetGoalActor(Target);
    MoveRequest.SetAcceptanceRadius(AcceptanceRadius); 
    EnemyController->MoveTo(MoveRequest);

Tick(float DeltaTime)
        //每一帧检查是否可以更新patroltarget,在与原本的patroltarget距离在patrolradius之内时就可以更新patroltarget
        CheckPatrolTarget();
CheckPatrolTarget

        if (InTargetRange(PatrolTarget, PatrolRadius))

        //更新新的patroltarget
             PatrolTarget = ChoosePatrolTarget();

        GetWorldTimerManager().SetTimer(PatrolTimer, this, &AEnemy::PatrolTimerFinished,         WaitTime);
InTargetRange(AActor* Target, double Radius):
    const double DistanceToTarget = (Target->GetActorLocation() - GetActorLocation()).Size();
    return DistanceToTarget <= Radius;

AEnemy::PatrolTimerFinished()

            //PatrolTimer倒数完就可以前往新的patroltarget
    MoveToTarget(PatrolTarget);

可是在实现过程中,发现敌人没法更新patroltarget。

随后在InTargetRange()中加上日志

bool AEnemy::InTargetRange(AActor* Target, double Radius)
{if (Target == nullptr) return false;const double DistanceToTarget = (Target->GetActorLocation() - GetActorLocation()).Size();FVector EnemyLocation = GetActorLocation();FVector TargetLocation = Target->GetActorLocation();UE_LOG(LogTemp, Warning, TEXT("Enemy Location: %s"), *EnemyLocation.ToString());UE_LOG(LogTemp, Warning, TEXT("Target Location: %s"), *TargetLocation.ToString());float Distance3D = FVector::Dist(EnemyLocation, TargetLocation);float Distance2D = FVector::Dist2D(EnemyLocation, TargetLocation); // 忽略Z轴UE_LOG(LogTemp, Warning, TEXT("3D Distance: %f"), Distance3D);UE_LOG(LogTemp, Warning, TEXT("2D (Horizontal) Distance: %f"), Distance2D);return DistanceToTarget <= Radius;
}

 

发现敌人在距离目标点2d平面距离为155unit,3d矢量距离为205unit的时候就停下了,205> patrolradius(200)就无法更新patroltarget。这不对劲啊,我前面通过设置MoveRequest.SetAcceptanceRadius(AcceptanceRadius); AcceptanceRadius=50.f代码,就预期敌人会在距离patroltarget 50unit的时候停下,而不是在155unit的时候停下。

于是问了chatgpt。

结果它回答我

✅【AIController::MoveTo 的到达逻辑:】

AI 到达目标的判断规则 roughly 是这样的(简化版):

ActualDistance <= (AcceptanceRadius + TargetCapsuleRadius + SelfCapsuleRadius)

也就是说,如果目标和自身的胶囊体比较大,即使你设置的 AcceptanceRadius 很小,也可能提前“到达”了目标。

并且给了我验证的日志代码

float SelfRadius = GetCapsuleComponent()->GetScaledCapsuleRadius();
float TargetRadius = 0.f;if (Target->IsA<ACharacter>())
{ACharacter* TargetChar = Cast<ACharacter>(Target);TargetRadius = TargetChar->GetCapsuleComponent()->GetScaledCapsuleRadius();
}UE_LOG(LogTemp, Warning, TEXT("SelfRadius: %f, TargetRadius: %f, AcceptanceRadius: %f, TotalEffectiveRadius: %f"),SelfRadius, TargetRadius, AcceptanceRadius,SelfRadius + TargetRadius + AcceptanceRadius);

于是我在movetotarget中加上代码

void AEnemy::MoveToTarget(AActor* Target)
{if (EnemyController == nullptr || Target == nullptr) return;float SelfRadius = GetCapsuleComponent()->GetScaledCapsuleRadius();float TargetRadius = 0.f;if (Target->IsA<ACharacter>()){ACharacter* TargetChar = Cast<ACharacter>(Target);TargetRadius = TargetChar->GetCapsuleComponent()->GetScaledCapsuleRadius();}UE_LOG(LogTemp, Warning, TEXT("SelfRadius: %f, TargetRadius: %f, AcceptanceRadius: %f, TotalEffectiveRadius: %f"),SelfRadius, TargetRadius, AcceptanceRadius,SelfRadius + TargetRadius + AcceptanceRadius);FAIMoveRequest MoveRequest;MoveRequest.SetGoalActor(Target);MoveRequest.SetAcceptanceRadius(AcceptanceRadius);EnemyController->MoveTo(MoveRequest);}

日志显示:

我的敌人在2d距离为155的时候停下了, AcceptanceRadius + TargetCapsuleRadius + SelfCapsuleRadius=149,和155也很接近,看来要使3d距离小于200,则就应该缩减AcceptanceRadius或者增大patrolradius,所以将AcceptanceRadius缩减至30之后,敌人又能正常更新patroltarget了。

这个说明了,不同体型的敌人, 其attackradius, combatradius, acceptanceradius,patrolradius都应该根据体型变化。

还有就是思考chatgpt的回答我是不是不应该写博客上,这样可能会导致数据污染,chatgpt之后爬网搜集数据搜集到的又是它自己生成的,自产自销了

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词