我目前正在用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的崩溃报告。
访问冲突-代码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 :: WaitUntilTasksComplete() [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
答案 0 :(得分:0)
您需要检查nullptr。
if (OtherActor != nullptr)
{
// Your code here
}
编辑:不仅在第13行,还在第18、23行(还有更多行,因为我在屏幕截图上看不到整个代码)
如果您需要详细的说明,为什么需要使用nullptr以及在哪里可以编辑此问题
EDIT2:我没有注意到它是虚幻代码,您能否在线为我们提供代码:
ATankAIController::GetClosestEnemyTank()
第70行,以及
ATankAIController::Tick()
第37行。如果可能的话,基本上是整个方法。问题仍然是nullptr。
答案 1 :(得分:0)
GetDistanceTo
的定义中,建议您使用IsValid()
检查OtherActor
是否有效。更安全,这是检查Actors验证的推荐方法。TActorIterator
,而不要使用TObjectIterator
。 Because it provides the safety of not accessing actors that are pending kill。PossessedTank
或/和PendingTarget
在此处可能是无效的指针。我没有看到完整的代码,但是根据调用堆栈,我认为PendingTarget
在这里无效,这就是程序崩溃的原因。