void FBehaviorTreeInstance::DeactivateNodes(FBehaviorTreeSearchData& SearchData, uint16 InstanceIndex) { for (int32 Idx = SearchData.PendingUpdates.Num() - 1; Idx >= 0; Idx--) { FBehaviorTreeSearchUpdate& UpdateInfo = SearchData.PendingUpdates[Idx]; if (UpdateInfo.InstanceIndex == InstanceIndex && UpdateInfo.Mode == EBTNodeUpdateMode::Add) { UE_VLOG(SearchData.OwnerComp.GetOwner(), LogBehaviorTree, Verbose, TEXT("Search node update[%s]: %s"), *UBehaviorTreeTypes::DescribeNodeUpdateMode(EBTNodeUpdateMode::Remove), *UBehaviorTreeTypes::DescribeNodeHelper(UpdateInfo.AuxNode ? (UBTNode*)UpdateInfo.AuxNode : (UBTNode*)UpdateInfo.TaskNode)); SearchData.PendingUpdates.RemoveAt(Idx, 1, false); } } for (int32 Idx = 0; Idx < ParallelTasks.Num(); Idx++) { const FBehaviorTreeParallelTask& ParallelTask = ParallelTasks[Idx]; if (ParallelTask.TaskNode && ParallelTask.Status == EBTTaskStatus::Active) { SearchData.AddUniqueUpdate(FBehaviorTreeSearchUpdate(ParallelTask.TaskNode, InstanceIndex, EBTNodeUpdateMode::Remove)); } } for (int32 Idx = 0; Idx < ActiveAuxNodes.Num(); Idx++) { if (ActiveAuxNodes[Idx]) { SearchData.AddUniqueUpdate(FBehaviorTreeSearchUpdate(ActiveAuxNodes[Idx], InstanceIndex, EBTNodeUpdateMode::Remove)); } } }
void UBTCompositeNode::NotifyDecoratorsOnDeactivation(struct FBehaviorTreeSearchData& SearchData, int32 ChildIdx, EBTNodeResult::Type& NodeResult) const { const FBTCompositeChild& ChildInfo = Children[ChildIdx]; for (int32 i = 0; i < ChildInfo.Decorators.Num(); i++) { const UBTDecorator* DecoratorOb = ChildInfo.Decorators[i]; DecoratorOb->ConditionalOnNodeProcessed(SearchData, NodeResult); DecoratorOb->ConditionalOnNodeDeactivation(SearchData, NodeResult); if (DecoratorOb->GetFlowAbortMode() == EBTFlowAbortMode::Self) { SearchData.AddUniqueUpdate(FBehaviorTreeSearchUpdate(DecoratorOb, SearchData.OwnerComp->GetActiveInstanceIdx(), EBTNodeUpdateMode::Remove)); } } }
void UBTCompositeNode::NotifyDecoratorsOnActivation(struct FBehaviorTreeSearchData& SearchData, int32 ChildIdx) const { const FBTCompositeChild& ChildInfo = Children[ChildIdx]; for (int32 i = 0; i < ChildInfo.Decorators.Num(); i++) { const UBTDecorator* DecoratorOb = ChildInfo.Decorators[i]; DecoratorOb->ConditionalOnNodeActivation(SearchData); switch (DecoratorOb->GetFlowAbortMode()) { case EBTFlowAbortMode::LowerPriority: SearchData.AddUniqueUpdate(FBehaviorTreeSearchUpdate(DecoratorOb, SearchData.OwnerComp->GetActiveInstanceIdx(), EBTNodeUpdateMode::Remove)); break; case EBTFlowAbortMode::Self: case EBTFlowAbortMode::Both: SearchData.AddUniqueUpdate(FBehaviorTreeSearchUpdate(DecoratorOb, SearchData.OwnerComp->GetActiveInstanceIdx(), EBTNodeUpdateMode::Add)); break; default: break; } } }
void UBTCompositeNode::OnNodeActivation(struct FBehaviorTreeSearchData& SearchData) const { OnNodeRestart(SearchData); if (bUseNodeActivationNotify) { NotifyNodeActivation(SearchData); } // add services when execution flow enters this composite for (int32 i = 0; i < Services.Num(); i++) { SearchData.AddUniqueUpdate(FBehaviorTreeSearchUpdate(Services[i], SearchData.OwnerComp->GetActiveInstanceIdx(), EBTNodeUpdateMode::Add)); } }
void UBTCompositeNode::NotifyDecoratorsOnFailedActivation(struct FBehaviorTreeSearchData& SearchData, int32 ChildIdx, EBTNodeResult::Type& NodeResult) const { const FBTCompositeChild& ChildInfo = Children[ChildIdx]; const uint16 ActiveInstanceIdx = SearchData.OwnerComp->GetActiveInstanceIdx(); for (int32 i = 0; i < ChildInfo.Decorators.Num(); i++) { const UBTDecorator* DecoratorOb = ChildInfo.Decorators[i]; DecoratorOb->ConditionalOnNodeProcessed(SearchData, NodeResult); if (DecoratorOb->GetFlowAbortMode() == EBTFlowAbortMode::LowerPriority || DecoratorOb->GetFlowAbortMode() == EBTFlowAbortMode::Both) { SearchData.AddUniqueUpdate(FBehaviorTreeSearchUpdate(DecoratorOb, ActiveInstanceIdx, EBTNodeUpdateMode::Add)); } } SearchData.OwnerComp->StoreDebuggerSearchStep(GetChildNode(ChildIdx), ActiveInstanceIdx, NodeResult); }
void UBTCompositeNode::OnNodeDeactivation(struct FBehaviorTreeSearchData& SearchData, EBTNodeResult::Type& NodeResult) const { // replace optional result before calling handler if (NodeResult == EBTNodeResult::Optional) { NodeResult = OptionalDeactivationResult; } if (bUseNodeDeactivationNotify) { NotifyNodeDeactivation(SearchData, NodeResult); } // remove all services if execution flow leaves this composite for (int32 i = 0; i < Services.Num(); i++) { SearchData.AddUniqueUpdate(FBehaviorTreeSearchUpdate(Services[i], SearchData.OwnerComp->GetActiveInstanceIdx(), EBTNodeUpdateMode::Remove)); } }
void UBTComposite_SimpleParallel::NotifyNodeDeactivation(FBehaviorTreeSearchData& SearchData, EBTNodeResult::Type& NodeResult) const { FBTParallelMemory* MyMemory = GetNodeMemory<FBTParallelMemory>(SearchData); const uint16 ActiveInstanceIdx = SearchData.OwnerComp.GetActiveInstanceIdx(); // modify node result if main task has finished if (!MyMemory->bMainTaskIsActive) { NodeResult = MyMemory->MainTaskResult; } // remove main task if (Children.IsValidIndex(EBTParallelChild::MainTask)) { SearchData.AddUniqueUpdate(FBehaviorTreeSearchUpdate(Children[EBTParallelChild::MainTask].ChildTask, ActiveInstanceIdx, EBTNodeUpdateMode::Remove)); } // remove all active nodes from background tree const FBTNodeIndex FirstBackgroundIndex(ActiveInstanceIdx, GetChildExecutionIndex(EBTParallelChild::BackgroundTree, EBTChildIndex::FirstNode)); const FBTNodeIndex LastBackgroundIndex(ActiveInstanceIdx, GetLastExecutionIndex()); SearchData.OwnerComp.UnregisterAuxNodesUpTo(FirstBackgroundIndex); // remove all pending updates "Add" from background tree // it doesn't make sense for decorators to reactivate themselves there for (int32 Idx = SearchData.PendingUpdates.Num() - 1; Idx >= 0; Idx--) { const FBehaviorTreeSearchUpdate& UpdateInfo = SearchData.PendingUpdates[Idx]; if (UpdateInfo.Mode == EBTNodeUpdateMode::Add) { const uint16 UpdateNodeIdx = UpdateInfo.AuxNode ? UpdateInfo.AuxNode->GetExecutionIndex() : UpdateInfo.TaskNode->GetExecutionIndex(); const FBTNodeIndex UpdateIdx(UpdateInfo.InstanceIndex, UpdateNodeIdx); if (FirstBackgroundIndex.TakesPriorityOver(UpdateIdx) && UpdateIdx.TakesPriorityOver(LastBackgroundIndex)) { UE_VLOG(SearchData.OwnerComp.GetOwner(), LogBehaviorTree, Verbose, TEXT("Search node update[canceled]: %s"), *UBehaviorTreeTypes::DescribeNodeHelper(UpdateInfo.AuxNode ? (UBTNode*)UpdateInfo.AuxNode : (UBTNode*)UpdateInfo.TaskNode)); SearchData.PendingUpdates.RemoveAt(Idx); } } } }