Download

Behavior Tree not recognizing the player

The problem I’m having is my AI I constructed will not recognize neither the player nor the Vector of the player.

superError.jpg

the above image is the behavior tree simulating and by the bottom right all the values are zeroed out or set to None :(. I also have blackboard variables for the behavior tree as well.

.h



// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved.

#pragma once

#include "GameFramework/AIController.h"
#include "CorruptAI.generated.h"

/**
 * 
 */
UCLASS()
class ACorruptAI : public AAIController
{
	GENERATED_UCLASS_BODY()

	UPROPERTY(transient)
	TSubobjectPtr<class UBlackboardComponent> BlackboardComp;

	UPROPERTY(transient)
	TSubobjectPtr<class UBehaviorTreeComponent> BehaviorComp;

	virtual void Possess(class APawn* InPawn);
	virtual void Tick(float DeltaTime);

	void SetEnemy(class APawn* InPawn);
	class ASideScrollerConceptCharacter *GetEnemy() const;

	UFUNCTION(BlueprintCallable, Category = Behavior)
	void SearchForEnemy();

protected:
	int32 EnemyKeyID;
	int32 EnemyLocationID;
	
};



.cpp



// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved.

#include "SideScrollerConcept.h"
#include "CorruptAI.h"
#include "CorruptBot.h"
#include "SideScrollerConceptCharacter.h"


ACorruptAI::ACorruptAI(const class FPostConstructInitializeProperties& PCIP)
	: Super(PCIP)
{
	BlackboardComp = PCIP.CreateDefaultSubobject<UBlackboardComponent>(this, TEXT("BlackBoardComp"));

	BehaviorComp = PCIP.CreateDefaultSubobject<UBehaviorTreeComponent>(this, TEXT("BehaviorComp"));
}

void ACorruptAI::Possess(class APawn* InPawn)
{
	Super::Possess(InPawn);
	ACorruptBot* Bot = Cast<ACorruptBot>(InPawn);
	if (Bot && Bot->BotBehavior)
	{
		BlackboardComp->InitializeBlackboard(Bot->BotBehavior->BlackboardAsset);

		EnemyKeyID = BlackboardComp->GetKeyID("Enemy");
		EnemyLocationID = BlackboardComp->GetKeyID("Destination");

		BehaviorComp->StartTree(Bot->BotBehavior);
	}
	
}

void ACorruptAI::Tick(float DeltaTime)
{


}

void ACorruptAI::SearchForEnemy()
{
	APawn* MyBot = GetPawn();
	if (MyBot == NULL)
	{
		return;
	}

	const FVector MyLoc = MyBot->GetActorLocation();
	float BestDistSq = MAX_FLT;
	ASideScrollerConceptCharacter* BestPawn = NULL;

	for (FConstPawnIterator It = GetWorld()->GetPawnIterator(); It; ++It)
	{
		ASideScrollerConceptCharacter* TestPawn = Cast<ASideScrollerConceptCharacter>(*It);
		if (TestPawn)
		{
			const float DistSq = (TestPawn->GetActorLocation() - MyLoc).SizeSquared();
			if (DistSq < BestDistSq)
			{
				BestDistSq = DistSq;
				BestPawn = TestPawn;
			}
		}
	}
	if (BestPawn)
	{
		SetEnemy(BestPawn);
	}
}

void ACorruptAI::SetEnemy(class APawn* InPawn)
{
	BlackboardComp->SetValueAsObject(EnemyKeyID, InPawn);
	BlackboardComp->SetValueAsVector(EnemyLocationID, InPawn->GetActorLocation());
	SetFocus(InPawn);
}

class ASideScrollerConceptCharacter* ACorruptAI::GetEnemy() const
{
	if (BlackboardComp)
	{
		return Cast<ASideScrollerConceptCharacter>(BlackboardComp->GetValueAsObject(EnemyKeyID));
	}

	return NULL;
}


Most of this code is from the ShooterGame code for testing and template usage.

Any ideas??

From your code and behavior tree setup image, it looks like you have the parts from the shooter game example to find the player but still need to use them. Shooter game calls the equivalent of the SearchForEnemy function from a blueprint service. That is why the function is declared as BlueprintCallable. If you look at the shooter game behavior tree you will notice the following service that I outlined in red:

If you double click on this service you will find that it is a blueprint derived from the class BTService_BlueprintBase with the following in its event graph:

In the shooter game example, this service is set to tick every 2 seconds. So every 2 seconds the service blueprint will get the Event Receive Tick which will call the controller function to set an enemy. You could create a similar setup that calls your SearchForEnemy from a blueprint service. You could also write this service in code instead by deriving from UBTService and overriding the TickNode function to do the same thing that the shooter game blueprint service does except in code. Finally, you could do all of this entirely in blueprint if you wanted. Your SearchForEnemy function could be implemented in blueprint. You can check out an example of how to set up a blueprint service in a response I wrote for someone who was trying to do this entirely in blueprint: here You will also find a few other points about behavior tree services later in that thread.

If this does not answer your question just let me know.

@Stephen

I did those corrections and it still wont find the vector nor the player itself still :frowning:

5cc67fa56002d1e6f12dbfe9fa2b682443ff4d25.jpeg

2d7b1db76554a969170a2d171e8b74504951085d.jpeg

f8d80e7d5d1ff3cd0ac5cce0622224c6e8e6a644.jpeg

there is also a nav mesh as well for the AI too.

[EDIT] The AI is the tall block thing

I even tried it in blueprint… still wont get the player’s position nor the player object itself :frowning:

Is it hitting a breakpoint at the SetEnemy(BestPawn); function?

What have you tried to debug this problem?

Ill try to make a tutorial tomorrow of my investigations into the behaviour tree system. I managed to make a monster spider AI that runs around, targets the player when it sees or hears it, shoots ba lls of goo and you, and from time to time, it burrows on the floor, spawning in a random place after a few secs alongside lots of small spiders that go and bite you.
Once you get how the system works, is tremendously easy to create new behaviours and stuff. But i truly miss some kind of event firing in the behavior tree.

@mikepurvis: I just tried putting a breakpoint on my “Search for Enemy” function in my blueprint. It does not snap to that breakpoint on starting the game. :confused:

a425dd0ae9a6ef9745862cf03abb1d38564fbac3.jpeg

@vblanco: That would be fantastic! monster spiders = awesome ^_^!

[EDIT]
Soooo i just had a realization while I was screenshoting my blueprint… for some reason it’s a custom event tick??? so i switched it to be Event Tick… and now it identify’s the player… bleeeh little mistakes make a big difference to fix

Well, put a breakpoint up in the previous function where it was supposed to be set. Test whether SearchForEnemy() is being called then, is it?

You can also put a breakpoint on the Tree to make sure the service is getting called.

It now shows the vector and the player itself now :)… only problem now is it will not move :(.

here’s the nav mesh layout test

nav_mesh.jpg

and here is the behavior tree

cf110746864a7d2aa952ba5b8f56c695d571c3b1.jpeg

everything is working now… just not the movement :confused:

I think there are some things missing, like event based trees (think, i launch an event of Burrow to the spider, and when it detects it it overrides all to do that.Im doing that by setting a bool value in the blackboard, but a better way would be fine.
I also miss some kind of “switch on enum” selector node to make it be like a state machine, maiby i create that one myself.
Also, a selector node wich gets a random task and executes it, maiby i also make that one myself.

Good news!! I have it working!! honestly, I just reloaded the editor and it worked with the properties i saved. I have the AI moving to the player and it’s all good. Thank you guys!

That feature is included already, but the documentation is non-existent. There is a thread I started on BehaviorTrees in the tutorials section and some of the Epic Devs responded back, they go over that feature in one of their responses. It’s called Observer Aborts. https://forums.unrealengine.com/showthread.php?130-Behavior-Tree-Tutorial

The random feature you want would be best as decorator, it might want to try random childs until one succeeds then return success so it keeps integraty of the BehaviorTree model.