【问题标题】:UE4 Closest enemy targetingUE4 最近的敌人瞄准
【发布时间】:2019-01-05 23:08:21
【问题描述】:

我目前正在使用 UE4 制作游戏,其中有 AI 玩家和 1 名本地玩家。我正在尝试制作团队死亡竞赛游戏模式。我已经完成了所有工作,但我有一个问题。我需要我的AIController 班级来瞄准最近的“敌人”(敌人的棋子上有团队),所以基本上我的棋子班级中最接近的演员不在AIController 的团队中。什么是优雅的实现方式?

到目前为止,我所做的是在游戏模式类中生成所有控制器和 pawn,并在每个生成的 pawn 上存储对这些控制器和 pawn 的引用。然后,一旦一个人死了,一个代表就会从所有还活着的 pawn 中删除被杀死的 pawn 引用。反之亦然,用于重新产卵。然后每个滴答声(这很严重,我知道这是错误的)所有的 pawn 都会遍历它们各自的敌人 pawn 引用,并获取到引用 pawn 的距离并返回具有最近距离的 pawn。

在这里问这个之前。我在网上进行了很多搜索以寻找解决此问题的方法,但我能找到的最接近的是一个标签定位系统,您可以在研讨会上购买。

我对整个游戏开发还很陌生(2 个月前开始学习 C++ 和 UE4)。所以如果有明显的解决办法,我很抱歉。

编辑:

我采用了一种新方法。我每帧遍历ATank 类的所有对象并获取它们的距离并将其与先前计算的距离进行比较。当距离较小时,它会设置新的待定目标。这很好。问题是当坦克的 hp 达到 0 时它会被摧毁。

ATank* ATankAIController::GetClosestEnemyTank()
{
    ATank* PendingTarget = TargetTank;
    for (TObjectIterator<ATank> Itr; Itr; ++Itr) //for all tanks in the world
    {
        if (Itr->GetTeam() != Team)
        {
            if (PendingTarget == nullptr) { PendingTarget = *Itr; continue; }
            if (Itr->GetDistanceTo(PossessedTank) < PendingTarget->GetDistanceTo(PossessedTank))
            {
                PendingTarget = *Itr;
            }
        }
    }
    return PendingTarget;
}


float ATank::TakeDamage(float DamageAmount, FDamageEvent const & DamageEvent, AController * EventInstigator, AActor * DamageCauser)
{
    int32 DamagePoints = FPlatformMath::RoundToInt(DamageAmount);
    int32 DamageToApply = FMath::Clamp<int32>(DamagePoints, 0, TankCurrentHealth);

    TankCurrentHealth -= DamageToApply;

    if (TankCurrentHealth == 0) 
    { 
        OnTankDeathEvent.Broadcast(this); 
    }
    return DamageToApply;
}

void ATankAIController::OnTankDeath(AActor* TankThatDied)
{
    UnPossess();
    Spawnpoint->bInUse = false;
    Cast<ATeamDeatmatchGameMode>(GetWorld()->GetAuthGameMode())->OnRespawnRequestEvent.Broadcast(this);
    TankThatDied->Destroy();
}

问题是总共有 12 个坦克。当一个人在迭代中计算距离的那个分裂时刻死亡时,我得到一个异常并且游戏崩溃。至少我认为是这样的……

这里是 Visual Studio 的异常捕获和 Unreal 的崩溃报告。

访问冲突 - 代码 c0000005(第一次/第二次机会不可用)

UE4Editor_Engine!AActor::GetDistanceTo() [d:\build++ue4+release-4.19+compile\sync\engine\source\runtime\engine\private\actor.cpp:4413] UE4Editor_BattleTank_727!ATankAIController::GetClosestEnemyTank() [f:\不真实 项目\battle-tank\battletank\source\battletank\private\tankaicontroller.cpp:70] UE4Editor_BattleTank_727!ATankAIController::Tick() [f:\unreal 项目\battle-tank\battletank\source\battletank\private\tankaicontroller.cpp:37] UE4Editor_Engine!AController::TickActor() [d:\build++ue4+release-4.19+compile\sync\engine\source\runtime\engine\private\leveltick.cpp:408] UE4Editor_Engine!FActorTickFunction::ExecuteTick() [d:\build++ue4+release-4.19+compile\sync\engine\source\runtime\engine\private\actor.cpp:134] UE4Editor_Engine!FTickFunctionTask::DoTask() [d:\build++ue4+release-4.19+compile\sync\engine\source\runtime\engine\private\ticktaskmanager.cpp:273] UE4Editor_Engine!TGraphTask::ExecuteTask() [d:\build++ue4+release-4.19+compile\sync\engine\source\runtime\core\public\async\taskgraphinterfaces.h:829] UE4Editor_Core!FNamedTaskThread::ProcessTasksNamedThread() [d:\build++ue4+release-4.19+compile\sync\engine\source\runtime\core\private\async\taskgraph.cpp:665] UE4Editor_Core!FNamedTaskThread::ProcessTasksUntilQuit() [d:\build++ue4+release-4.19+compile\sync\engine\source\runtime\core\private\async\taskgraph.cpp:574] UE4Editor_Core!FTaskGraphImplementation::WaitUntilTask​​sComplete() [d:\build++ue4+release-4.19+compile\sync\engine\source\runtime\core\private\async\taskgraph.cpp:1355] UE4Editor_Engine!FTickTaskSequencer::ReleaseTickGroup() [d:\build++ue4+release-4.19+compile\sync\engine\source\runtime\engine\private\ticktaskmanager.cpp:542] UE4Editor_Engine!FTickTaskManager::RunTickGroup() [d:\build++ue4+release-4.19+compile\sync\engine\source\runtime\engine\private\ticktaskmanager.cpp:1449] UE4Editor_Engine!UWorld::RunTickGroup() [d:\build++ue4+release-4.19+compile\sync\engine\source\runtime\engine\private\leveltick.cpp:770] UE4Editor_Engine!UWorld::Tick() [d:\build++ue4+release-4.19+compile\sync\engine\source\runtime\engine\private\leveltick.cpp:1429] UE4Editor_UnrealEd!UEditorEngine::Tick() [d:\build++ue4+release-4.19+compile\sync\engine\source\editor\unrealed\private\editorengine.cpp:1693] UE4Editor_UnrealEd!UUnrealEdEngine::Tick() [d:\build++ue4+release-4.19+compile\sync\engine\source\editor\unrealed\private\unrealedengine.cpp:401] UE4Editor!FEngineLoop::Tick() [d:\build++ue4+release-4.19+compile\sync\engine\source\runtime\launch\private\launchengineloop.cpp:3339] UE4Editor!GuardedMain() [d:\build++ue4+release-4.19+compile\sync\engine\source\runtime\launch\private\launch.cpp:166] UE4Editor!GuardedMainWrapper() [d:\build++ue4+release-4.19+compile\sync\engine\source\runtime\launch\private\windows\launchwindows.cpp:144] UE4Editor!WinMain() [d:\build++ue4+release-4.19+compile\sync\engine\source\runtime\launch\private\windows\launchwindows.cpp:223] UE4Editor!__scrt_common_main_seh() [f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl:253] kernel32 ntdll

【问题讨论】:

  • 这个问题太宽泛了。鉴于我们从您的描述中所知道的只是我们需要一些最近邻算法,因此我们什么也不能提供。您至少需要大致说明问题的规模、时间和空间的限制以及存在的任何其他怪癖。
  • 编辑了帖子以尝试更好的解释@PasserBy
  • 似乎您正在尝试访问空指针。您需要查看您使用的 UObject 引用是否为空。如果指针在使用时总是应该有值,则可以用 ensure() 断言包围指针。只需确保在调试后将其删除。我个人更喜欢用 if 语句来保护我的指针。
  • @Balgy 嗨,感谢您的评论!我用 if 语句保护它,更不用说确保语句了。 UObject 只是在确保发生后并且它是有效指针时被销毁。就像: if ensure fires --> UObject 被破坏 --> 它试图获取距离,但它试图从被破坏的 uobject 中获取距离。问题是没有确切的“时间”对象被破坏可以防止错误。所以我正在研究环境查询和黑板以寻求解决方案。
  • 如果你想要一个非常粗略和临时的解决方法,虚幻允许你将对象添加到垃圾收集的根集。

标签: c++ unreal-engine4 targeting


【解决方案1】:

您需要检查 nullptr。

if (OtherActor != nullptr)
{    
         // Your code here    
} 

编辑:不仅在第 13 行,也在第 18、23 行(可能还有更多行,因为我在屏幕截图上看不到整个代码)

如果您需要详细说明为什么需要使用 nullptr 以及我可以在哪里编辑此问题

EDIT2:没注意到是虚幻代码,能否在线提供代码:

ATankAIController::GetClosestEnemyTank() 第 70 行,以及 ATankAIController::Tick() 第 37 行。如果可能的话,基本上是整个方法。问题仍然是 nullptr。

【讨论】:

  • 你指的代码是引擎代码(AActor类),不是OP的代码。
  • @Rotem 你是对的,我没注意到。我编辑了答案
【解决方案2】:
  1. 由于这里只有12个坦克,所以可以迭代所有坦克并直接计算距离。在这种情况下我也会这样做。
  2. GetDistanceTo的定义中,我建议你使用IsValid()来检查OtherActor是否有效。它更安全,并且是检查 Actor 验证的推荐方法。
  3. 我还建议您使用TActorIterator,而不是TObjectIteratorBecause it provides the safety of not accessing actors that are pending kill
  4. 关于此处的崩溃,PossessedTank 或/和PendingTarget 在此处可能是无效指针,具体取决于您如何定义和操作它们。我没有看到完整的代码,但是根据调用堆栈,我认为PendingTarget在这里无效,这就是程序崩溃的原因。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-20
    • 2011-07-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多