UE4最接近敌人的目标

时间:2018-07-29 14:40:47

标签: c++ unreal-engine4 targeting

我目前正在用UE4制作游戏,在那里我既有AI玩家又有1位本地玩家。我正在尝试制作Team Deathmatch游戏模式。我已完成所有工作,但有一个问题。我需要我的AIController类来瞄准最近的“敌人”(敌人的卒子上有队),因此基本上是我的典当类中距离AIController队中最近的演员。实施此方法的一种优雅方法是什么?

到目前为止,我所做的是在gamemode类中生成所有控制器和棋子,并在每个生成的棋子上存储对它们的引用。然后,一旦死亡,代表将解雇从仍然存在的所有典当中删除被杀死的典当引用。反之亦然。然后每个滴答声(这是完全错误的,我知道这是错误的),所有典当都遍历各自的敌方典当引用,并获取与引用的典当的距离,并返回距离最近的典当。

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

我对整个开发游戏还是比较陌生的(两个月前开始研究C ++和UE4)。因此,如果有一个明显的解决方案,对不起。

编辑:

我采用了一种新方法。我每帧遍历类ATank的所有对象,并获取它们的距离,并将其与先前计算的距离进行比较。当距离较小时,它将设置新的挂起目标。这样很好。问题是当坦克的马力达到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的崩溃报告。

VSException1 VS Callstack and locals

  

访问冲突-代码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:\虚幻   项目\战斗坦克\战斗坦克\源\战斗坦克\私有\ tankaicontroller.cpp:70]   UE4Editor_BattleTank_727!ATankAIController :: Tick()[f:\ unreal   项目\战斗坦克\战斗坦克\源\战斗坦克\私有\ 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

2 个答案:

答案 0 :(得分:0)

您需要检查nullptr。

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

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

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

EDIT2:我没有注意到它是虚幻代码,您能否在线为我们提供代码:

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

答案 1 :(得分:0)

  1. 由于这里只有12个战车,因此可以迭代所有战车并直接计算距离。在这种情况下,我也会这样做。
  2. GetDistanceTo的定义中,建议您使用IsValid()检查OtherActor是否有效。更安全,这是检查Actors验证的推荐方法。
  3. 我还建议您使用TActorIterator,而不要使用TObjectIteratorBecause it provides the safety of not accessing actors that are pending kill
  4. 关于此处的崩溃,根据您定义和操作它们的方式,PossessedTank或/和PendingTarget在此处可能是无效的指针。我没有看到完整的代码,但是根据调用堆栈,我认为PendingTarget在这里无效,这就是程序崩溃的原因。