当前位置: 首页 > news >正文

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之后爬网搜集数据搜集到的又是它自己生成的,自产自销了

http://www.xdnf.cn/news/3223.html

相关文章:

  • 力扣349 == 两个数组交集的两种解法
  • selenium 实现模拟登录中的滑块验证功能
  • 【文献笔记】LLM-based control code generation using image recognition
  • 详细讲解一下Java中的Enum
  • Missashe考研日记-day22
  • AI与物联网的深度融合:开启智能生活新时代
  • 写书的三驾马车
  • 【Unity】UI点击事件处理器
  • 文件系统 软硬连接
  • 类和对象(下篇)(详解)
  • 2025.4.20机器学习笔记:文献阅读
  • 【前端】跟着maxkb学习流程图画法
  • Qt QML实现Windows桌面歌词动态播放效果
  • Win10如何一键切换IP地址教程
  • ubtuntu安装docker拉取iwebsec镜像
  • 关于STM32G030和G070未初始化看门狗,程序里面喂狗会导致擦除Flash失败或进入‘HardFault_Handler’
  • WebSocket 实现数据实时推送原理
  • GPT,Bert类模型对比
  • 4.17---实现商铺和缓存与数据库双写一致以及宕机处理
  • 2025.04.17【Dendrogram】生信数据可视化:Dendrogram图表详解
  • 网络编程 - 1
  • Genspark:重新定义AI搜索与代理的全能型工具
  • 私人笔记:动手学大模型应用开发llm-universe项目环境创建
  • 【前端vue生成二维码和条形码——MQ】
  • 【随身WIFI】随身WiFi Debian系统优化教程
  • AUTOSAR图解==>AUTOSAR_SWS_DefaultErrorTracer
  • 计算机网络 - UDP协议
  • 4.15BUUCTF Ez_bypass,HardSQL,AreUSerialz,BabyUpload,CheckIn
  • 【Docker】运行错误提示 unknown shorthand flag: ‘d‘ in -d ----详细解决方法
  • jQuery入门和选择器