コード例 #1
0
int32 UBTCompositeNode::GetNextChild(struct FBehaviorTreeSearchData& SearchData, int32 LastChildIdx, EBTNodeResult::Type LastResult) const
{
	FBTCompositeMemory* NodeMemory = GetNodeMemory<FBTCompositeMemory>(SearchData);
	int32 NextChildIndex = BTSpecialChild::ReturnToParent;
	uint16 ActiveInstanceIdx = SearchData.OwnerComp->GetActiveInstanceIdx();

	// newly activated node, search range not reached yet: select search branch for decorator test
	if (LastChildIdx == BTSpecialChild::NotInitialized && SearchData.SearchStart.IsSet() &&
		FBTNodeIndex(ActiveInstanceIdx, GetExecutionIndex()).TakesPriorityOver(SearchData.SearchStart))
	{
		NextChildIndex = GetMatchingChildIndex(ActiveInstanceIdx, SearchData.SearchStart);
	}
	else if (NodeMemory->OverrideChild != BTSpecialChild::NotInitialized && !SearchData.OwnerComp->IsRestartPending())
	{
		NextChildIndex = NodeMemory->OverrideChild;
		NodeMemory->OverrideChild = BTSpecialChild::NotInitialized;
	}
	// or use composite's logic
	else if (OnNextChild.IsBound())
	{
		NextChildIndex = OnNextChild.Execute(SearchData, LastChildIdx, LastResult);
	}

	return NextChildIndex;
}
コード例 #2
0
int32 UBTCompositeNode::GetMatchingChildIndex(int32 ActiveInstanceIdx, struct FBTNodeIndex& NodeIdx) const
{
	const int32 OutsideRange = BTSpecialChild::ReturnToParent;
	const int32 UnlimitedRange = Children.Num() - 1;

	// search ends at the same instance level: use execution index to determine branch containing node index
	if (ActiveInstanceIdx == NodeIdx.InstanceIndex)
	{
		// is composite even in range of search?
		if (GetExecutionIndex() > NodeIdx.ExecutionIndex)
		{
			return OutsideRange;
		}

		// find child outside range
		for (int32 i = 0; i < Children.Num(); i++)
		{
			const UBTNode* ChildNode = GetChildNode(i);
			if (ChildNode->GetExecutionIndex() > NodeIdx.ExecutionIndex)
			{
				return i ? (i - 1) : 0;
			}
		}

		return UnlimitedRange;
	}

	// search ends at higher level: allow every node
	// search ends at lower level: outside allowed range
	return (ActiveInstanceIdx > NodeIdx.InstanceIndex) ? UnlimitedRange : OutsideRange;
}
コード例 #3
0
ファイル: BTNode.cpp プロジェクト: didixp/Ark-Dev-Kit
void UBTNode::InitializeInSubtree(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, int32& NextInstancedIndex, EBTMemoryInit::Type InitType) const
{
    if (bCreateNodeInstance)
    {
        // composite nodes can't be instanced!
        check(IsA(UBTCompositeNode::StaticClass()) == false);

        UBTNode* NodeInstance = OwnerComp.NodeInstances.IsValidIndex(NextInstancedIndex) ? OwnerComp.NodeInstances[NextInstancedIndex] : NULL;
        if (NodeInstance == NULL)
        {
            NodeInstance = NewObject<UBTNode>(&OwnerComp, GetClass(), GetFName(), RF_NoFlags, (UObject*)(this));
            NodeInstance->InitializeNode(GetParentNode(), GetExecutionIndex(), GetMemoryOffset(), GetTreeDepth());
            NodeInstance->bIsInstanced = true;

            OwnerComp.NodeInstances.Add(NodeInstance);
        }
        check(NodeInstance);

        NodeInstance->SetOwner(OwnerComp.GetOwner());

        FBTInstancedNodeMemory* MyMemory = GetSpecialNodeMemory<FBTInstancedNodeMemory>(NodeMemory);
        MyMemory->NodeIdx = NextInstancedIndex;

        NodeInstance->OnInstanceCreated(OwnerComp);
        NextInstancedIndex++;
    }
    else
    {
        InitializeMemory(OwnerComp, NodeMemory, InitType);
    }
}
コード例 #4
0
void UBTNode::InitializeInSubtree(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, int32& NextInstancedIndex, EBTMemoryInit::Type InitType) const
{
	FBTInstancedNodeMemory* SpecialMemory = GetSpecialNodeMemory<FBTInstancedNodeMemory>(NodeMemory);
	if (SpecialMemory)
	{
		SpecialMemory->NodeIdx = INDEX_NONE;
	}

	if (bCreateNodeInstance)
	{
		// composite nodes can't be instanced!
		check(IsA(UBTCompositeNode::StaticClass()) == false);

		UBTNode* NodeInstance = OwnerComp.NodeInstances.IsValidIndex(NextInstancedIndex) ? OwnerComp.NodeInstances[NextInstancedIndex] : NULL;
		if (NodeInstance == NULL)
		{
			NodeInstance = (UBTNode*)StaticDuplicateObject(this, &OwnerComp);
			NodeInstance->InitializeNode(GetParentNode(), GetExecutionIndex(), GetMemoryOffset(), GetTreeDepth());
			NodeInstance->bIsInstanced = true;

			OwnerComp.NodeInstances.Add(NodeInstance);
		}

		check(NodeInstance);
		check(SpecialMemory);

		SpecialMemory->NodeIdx = NextInstancedIndex;

		NodeInstance->SetOwner(OwnerComp.GetOwner());
		NodeInstance->InitializeMemory(OwnerComp, NodeMemory, InitType);
		check(TreeAsset);
		NodeInstance->InitializeFromAsset(*TreeAsset);
		NodeInstance->OnInstanceCreated(OwnerComp);
		NextInstancedIndex++;
	}
	else
	{
		InitializeMemory(OwnerComp, NodeMemory, InitType);
	}
}
コード例 #5
0
void UBTTask_RunBehavior::InjectNodes(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, int32& InstancedIndex) const
{
	if (BehaviorAsset == NULL || BehaviorAsset->RootDecorators.Num() == 0)
	{
		return;
	}

	const int32 NumInjectedDecorators = BehaviorAsset->RootDecorators.Num();
	FBTInstancedNodeMemory* NodeMemoryHeader = (FBTInstancedNodeMemory*)NodeMemory;
	int32 FirstNodeIdx = NodeMemoryHeader->NodeIdx;

	uint8* InjectedMemoryBase = NodeMemory + sizeof(FBTInstancedNodeMemory);

	// initialize on first access
	if (!OwnerComp.NodeInstances.IsValidIndex(InstancedIndex))
	{
		TArray<uint16> MemoryOffsets;
		int32 MemorySize = 0;

		UBehaviorTreeManager::InitializeMemoryHelper(BehaviorAsset->RootDecorators, MemoryOffsets, MemorySize);
		const int32 AlignedInstanceMemorySize = UBehaviorTreeManager::GetAlignedDataSize(sizeof(FBTInstancedNodeMemory));

		// prepare dummy memory block for nodes that won't require instancing and offset it by special data size
		// InitializeInSubtree will read it through GetSpecialNodeMemory function, which moves pointer back 
		FBTInstancedNodeMemory DummyMemory;
		uint8* RawDummyMemory = ((uint8*)&DummyMemory) + AlignedInstanceMemorySize;

		// newly created nodes = full init
		EBTMemoryInit::Type InitType = EBTMemoryInit::Initialize;

		NodeMemoryHeader->NodeIdx = InstancedIndex;
		FirstNodeIdx = InstancedIndex;

		// create nodes
		for (int32 Idx = 0; Idx < NumInjectedDecorators; Idx++)
		{
			UBTDecorator* DecoratorOb = BehaviorAsset->RootDecorators[Idx];

			const bool bUsesInstancing = DecoratorOb->HasInstance();
			if (bUsesInstancing)
			{
				DecoratorOb->InitializeInSubtree(OwnerComp, InjectedMemoryBase + MemoryOffsets[Idx], InstancedIndex, InitType);
			}
			else
			{
				DecoratorOb->ForceInstancing(true);
				DecoratorOb->InitializeInSubtree(OwnerComp, RawDummyMemory, InstancedIndex, InitType);
				DecoratorOb->ForceInstancing(false);

				UBTDecorator* InstancedOb = Cast<UBTDecorator>(OwnerComp.NodeInstances.Last());
				InstancedOb->InitializeMemory(OwnerComp, InjectedMemoryBase + MemoryOffsets[Idx], InitType);
			}
		}

		// setup their properties
		uint16 NewExecutionIdx = GetExecutionIndex() - GetInjectedNodesCount();
		for (int32 Idx = 0; Idx < NumInjectedDecorators; Idx++)
		{
			UBTDecorator* InstancedOb = Cast<UBTDecorator>(OwnerComp.NodeInstances[FirstNodeIdx + Idx]);
			InstancedOb->InitializeNode(GetParentNode(), NewExecutionIdx, GetMemoryOffset() + MemoryOffsets[Idx], GetTreeDepth() - 1);
			InstancedOb->MarkInjectedNode();

			NewExecutionIdx++;
		}
	}
	else
	{
		// restoring existing nodes = partial init
		EBTMemoryInit::Type InitType = EBTMemoryInit::RestoreSubtree;

		// initialize memory for injected nodes
		for (int32 Idx = 0; Idx < NumInjectedDecorators; Idx++)
		{
			UBTDecorator* DecoratorOb = BehaviorAsset->RootDecorators[Idx];
			UBTDecorator* InstancedOb = Cast<UBTDecorator>(OwnerComp.NodeInstances[FirstNodeIdx + Idx]);

			const bool bUsesInstancing = DecoratorOb->HasInstance();
			if (bUsesInstancing)
			{
				InstancedOb->OnInstanceCreated(OwnerComp);
			}
			else
			{
				uint8* InjectedNodeMemory = InjectedMemoryBase + (InstancedOb->GetMemoryOffset() - GetMemoryOffset());
				InstancedOb->InitializeMemory(OwnerComp, InjectedNodeMemory, InitType);
			}
		}

		InstancedIndex += NumInjectedDecorators;
	}

	// inject nodes
	if (GetParentNode())
	{
		const int32 ChildIdx = GetParentNode()->GetChildIndex(*this);
		if (ChildIdx != INDEX_NONE)
		{
			FBTCompositeChild& LinkData = GetParentNode()->Children[ChildIdx];

			// check if link already has injected decorators
			bool bAlreadyInjected = false;
			for (int32 Idx = 0; Idx < LinkData.Decorators.Num(); Idx++)
			{
				if (LinkData.Decorators[Idx] && LinkData.Decorators[Idx]->IsInjected())
				{
					bAlreadyInjected = true;
					break;
				}
			}

			// add decorators to link
			const int32 NumOriginalDecorators = LinkData.Decorators.Num();
			for (int32 Idx = 0; Idx < NumInjectedDecorators; Idx++)
			{
				UBTDecorator* InstancedOb = Cast<UBTDecorator>(OwnerComp.NodeInstances[FirstNodeIdx + Idx]);
				InstancedOb->InitializeFromAsset(*BehaviorAsset);
				InstancedOb->InitializeDecorator(ChildIdx);

				if (!bAlreadyInjected)
				{
					LinkData.Decorators.Add(InstancedOb);
				}
			}

			// update composite logic operators
			if (!bAlreadyInjected && (LinkData.DecoratorOps.Num() || BehaviorAsset->RootDecoratorOps.Num()))
			{
				const int32 NumOriginalOps = LinkData.DecoratorOps.Num();
				if (NumOriginalDecorators > 0)
				{
					// and operator for two groups of composites: original and new one
					FBTDecoratorLogic MasterAndOp(EBTDecoratorLogic::And, LinkData.DecoratorOps.Num() ? 2 : (NumOriginalDecorators + 1));
					LinkData.DecoratorOps.Insert(MasterAndOp, 0);

					if (NumOriginalOps == 0)
					{
						// add Test operations, original link didn't have composite operators
						for (int32 Idx = 0; Idx < NumOriginalDecorators; Idx++)
						{
							FBTDecoratorLogic TestOp(EBTDecoratorLogic::Test, Idx);
							LinkData.DecoratorOps.Add(TestOp);
						}
					}
				}

				// add injected operators
				if (BehaviorAsset->RootDecoratorOps.Num() == 0)
				{
					FBTDecoratorLogic InjectedAndOp(EBTDecoratorLogic::And, NumInjectedDecorators);
					LinkData.DecoratorOps.Add(InjectedAndOp);

					for (int32 Idx = 0; Idx < NumInjectedDecorators; Idx++)
					{
						FBTDecoratorLogic TestOp(EBTDecoratorLogic::Test, NumOriginalDecorators + Idx);
						LinkData.DecoratorOps.Add(TestOp);
					}
				}
				else
				{
					for (int32 Idx = 0; Idx < BehaviorAsset->RootDecoratorOps.Num(); Idx++)
					{
						FBTDecoratorLogic InjectedOp = BehaviorAsset->RootDecoratorOps[Idx];
						if (InjectedOp.Operation == EBTDecoratorLogic::Test)
						{
							InjectedOp.Number += NumOriginalDecorators;
						}

						LinkData.DecoratorOps.Add(InjectedOp);
					}
				}
			}

#if USE_BEHAVIORTREE_DEBUGGER
			if (!bAlreadyInjected)
			{
				// insert to NextExecutionNode list for debugger
				UBTNode* NodeIt = GetParentNode();
				while (NodeIt && NodeIt->GetNextNode() != this)
				{
					NodeIt = NodeIt->GetNextNode();
				}

				if (NodeIt)
				{
					NodeIt->InitializeExecutionOrder(OwnerComp.NodeInstances[FirstNodeIdx]);
					NodeIt = NodeIt->GetNextNode();

					for (int32 Idx = 1; Idx < NumInjectedDecorators; Idx++)
					{
						NodeIt->InitializeExecutionOrder(OwnerComp.NodeInstances[FirstNodeIdx + Idx]);
						NodeIt = NodeIt->GetNextNode();
					}

					NodeIt->InitializeExecutionOrder((UBTNode*)this);
				}
			}
#endif
		}
	}
}