Как реализовать патрулирование для ИИ в Unreal Engine?
ИИ-бот должен патрулировать упорядоченный список actor-точек патруля по кругу: дойти до точки, сделать паузу, затем перейти к следующей и так бесконечно. Реализуйте это через Behavior Tree, а не через рукописную логику в Tick.
Требования:
выбранную локацию в ключ Blackboard; затем MoveTo идёт туда по NavMesh.
- Выбор следующей точки живёт в кастомной BT-задаче
Task, которая пишет - Индекс должен зацикливаться, чтобы патруль повторялся бесконечно.
- Возвращайте
Failed, если точек патруля нет, чтобы дерево могло отреагировать.
Допишите ExecuteTask кастомной задачи, которая сдвигается к следующей точке и публикует её в ключ Blackboard PatrolLocation:
EBTNodeResult::Type UBTTask_NextPatrolPoint::ExecuteTask(
UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory)
{
// ваш код здесь: сдвиньте циклический индекс на pawn патруля и запишите
// локацию следующей точки в ключ "PatrolLocation"
}
Допишите реализацию.
Расставьте actor-точки патруля, выставьте их на pawn и используйте Sequence в Behavior Tree: кастомный Task кладёт следующую точку в Vector/Object-ключ Blackboard, MoveTo идёт туда, затем Wait делает паузу, после чего индекс сдвигается и цикл повторяется.
- ✗Считать, что Behavior Tree не зацикливается —
Sequenceпод циклящим родителем умеет - ✗Класть координаты waypoint в дерево вместо ключа Blackboard
- ✗Забыть задачу
Wait, из-за чего ИИ дёргается между точками без паузы
- →Как переключиться с патруля на погоню, когда perception видит игрока?
- →Должны ли точки патруля идти по кругу, маятником или случайно — и как это сделать?
Идея
Патруль — это цикл: выбрать точку → дойти → подождать → следующая точка. Behavior Tree зацикливается сам, если поместить Sequence под композит, который перезапускает потомков (корень дерева делает это по умолчанию).
Шаг 1. Кастомная задача — выбор следующей точки
EBTNodeResult::Type UBTTask_NextPatrolPoint::ExecuteTask(
UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory)
{
auto* AICon = OwnerComp.GetAIOwner();
auto* Bot = Cast<APatrolBot>(AICon->GetPawn());
if (!Bot || Bot->PatrolPoints.Num() == 0)
return EBTNodeResult::Failed;
// циклический индекс
Bot->PatrolIndex = (Bot->PatrolIndex + 1) % Bot->PatrolPoints.Num();
AActor* Next = Bot->PatrolPoints[Bot->PatrolIndex];
OwnerComp.GetBlackboardComponent()
->SetValueAsVector(TEXT("PatrolLocation"), Next->GetActorLocation());
return EBTNodeResult::Succeeded;
}
Шаг 2. Behavior Tree
Sequence (перезапускается корнем → бесконечный цикл)
├─ Task: BTTask_NextPatrolPoint → пишет ключ PatrolLocation
├─ Task: MoveTo (Blackboard Key = PatrolLocation)
└─ Task: Wait (3 сек — пауза в точке)
MoveTo строит путь по NavMesh. После Wait Sequence завершается успехом, корень перезапускает её — индекс сдвигается, и бот идёт к следующей точке.