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