UE4 Ближайший вражеский прицел

В настоящее время я делаю игру с UE4, где у меня есть AI-игроки и 1 местный игрок. Я пытаюсь сделать игровой режим Team Deathmatch. Я все сделал, но у меня есть одна проблема. Мне нужен мой класс AIController для нацеливания на ближайшего «врага» (у вражеских пешек есть команды), так что в основном это ближайший актер моего класса пешек, которого нет в команде AiController. Каков элегантный способ реализации этого?

Пока что я делаю, это порождаю все контроллеры и пешки в классе gamemode и сохраняю ссылки на них на каждой порожденной пешке. Затем, как только кто-то умирает, делегат выстреливает, удаляя ссылку на убитую пешку со всех живых пешек. И наоборот для повторного нереста. Затем каждый тик (который является полностью грубым, и я знаю, что это неправильно), все пешки перебирают соответствующие ссылки пешек противника и получают расстояние до пешек, на которые ссылаются, и возвращают любую пешку, находившуюся ближе всего.

Прежде чем спросить это здесь. Я много раз в Интернете искал решения этой проблемы, но самое близкое, что я мог получить, — это система таргетинга на вкладки, которую можно купить на семинаре.

Я довольно новичок в разработке игр (начал изучать C ++ и UE4 2 месяца назад). Поэтому, если есть очевидное решение, мне очень жаль.

С нетерпением ждем от вас, спасибо заранее.

Рубен Версавель

Редактировать:

Я выбрал новый подход. Я перебираю все объекты класса 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 и местные жители

Нарушение доступа — код 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: \ нереальным
проекты \ Battletank \ Battletank \ источник \ Battletank \ частное \ tankaicontroller.cpp: 70] UE4Editor_BattleTank_727! ATankAIController :: Tick () [f: \ unreal
проекты \ Battletank \ Battletank \ источник \ Battletank \ частной \ tankaicontroller.cpp: 37] UE4Editor_Engine! АСопЬгоНег :: TickActor ()
[D: \ сборки UE4 ++ + релиз-4.19 + компилировать \ \ синхронизации двигателя \ Source \ \ среда выполнения двигатель \ \ частной 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: \ сборки UE4 ++ + релиз-4.19 + компилировать \ \ синхронизации двигателя \ Source \ \ среда выполнения двигатель \ \ частной ticktaskmanager.cpp: 273] UE4Editor_Engine! TGraphTask :: ExecuteTask ()
[D: \ сборки UE4 ++ + релиз-4.19 + компилировать \ синхронизации \ двигатель \ источник \ среда выполнения \ ядро ​​\ Public \ асинхронной \ taskgraphinterfaces.h: 829] UE4Editor_Core! FNamedTaskThread :: ProcessTasksNamedThread ()
[D: \ сборки UE4 ++ + релиз-4.19 + компилировать \ синхронизации \ двигатель \ источник \ среда выполнения \ ядро ​​\ частный \ асинхронной \ taskgraph.cpp: 665] UE4Editor_Core! FNamedTaskThread :: ProcessTasksUntilQuit ()
[D: \ сборки UE4 ++ + релиз-4.19 + компилировать \ синхронизации \ двигатель \ источник \ среда выполнения \ ядро ​​\ частный \ асинхронной \ taskgraph.cpp: 574] UE4Editor_Core! FTaskGraphImplementation :: WaitUntilTasksComplete ()
[D: \ сборки UE4 ++ + релиз-4.19 + компилировать \ синхронизации \ двигатель \ источник \ среда выполнения \ ядро ​​\ частный \ асинхронной \ taskgraph.cpp: 1355] UE4Editor_Engine! FTickTaskSequencer :: ReleaseTickGroup ()
[D: \ сборки UE4 ++ + релиз-4.19 + компилировать \ \ синхронизации двигателя \ Source \ \ среда выполнения двигатель \ \ частной ticktaskmanager.cpp: 542] UE4Editor_Engine! FTickTaskManager :: RunTickGroup ()
[D: \ сборки UE4 ++ + релиз-4.19 + компилировать \ \ синхронизации двигателя \ Source \ \ среда выполнения двигатель \ \ частной ticktaskmanager.cpp: 1449] UE4Editor_Engine! UWorld :: RunTickGroup ()
[D: \ сборки UE4 ++ + релиз-4.19 + компилировать \ \ синхронизации двигателя \ Source \ \ среда выполнения двигатель \ \ частной 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: \ сборки ++ UE4 + релиз-4.19 + компилировать \ синхронизации \ двигатель \ источник \ редактор \ UnrealEd \ частное \ editorengine.cpp: 1693] UE4Editor_UnrealEd! UUnrealEdEngine :: Tick ()
[D: \ сборки UE4 ++ + релиз-4.19 + компилировать \ синхронизации \ двигатель \ источник \ редактор \ UnrealEd \ частный \ unrealedengine.cpp: 401] UE4Editor! FEngineLoop :: Tick ()
[D: \ сборки UE4 ++ + релиз-4.19 + компилировать \ синхронизации \ двигатель \ источник \ среда \ запуск \ частной \ launchengineloop.cpp: 3339] UE4Editor! GuardedMain ()
[d: \ build ++ ue4 + release-4.19 + compile \ sync \ engine \ source \ runtime \ launch \ private \ launch.cpp: 166] UE4Editor! GuardedMainWrapper ()
[D: \ сборки UE4 ++ + релиз-4.19 + компилировать \ синхронизации \ двигатель \ источник \ среда \ запуск \ частных \ Windows \ launchwindows.cpp: 144] UE4Editor! WinMain ()
[D: \ сборки UE4 ++ + релиз-4.19 + компилировать \ синхронизации \ двигатель \ источник \ среда \ запуск \ частных \ Windows \ launchwindows.cpp: 223] UE4Editor! __ scrt_common_main_seh ()
[f: \ dd \ vctools \ crt \ vcstartup \ src \ startup \ exe_common.inl: 253] kernel32
Ntdll

0

Решение

Вам нужно проверить на nullptr.

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

РЕДАКТИРОВАТЬ: не только в строке 13, а также в строках 18, 23 (и, возможно, больше строк, так как я не вижу весь код на скриншоте)

Если вам нужно подробное объяснение, почему вы должны использовать nullptr и где я могу отредактировать этот вопрос

РЕДАКТИРОВАТЬ 2: Я не заметил, что это был Unreal Code, вы можете предоставить нам код на линии:

ATankAIController::GetClosestEnemyTank() линия 70, и
ATankAIController::Tick() строка 37. В основном, если это возможно, целыми методами. Проблема все еще в nullptr.

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]