Hello. Again, it’s been a while since the last blog update, all I can say is life gets in the way. But I am back.
PhD is going well, next month is the first major milestone where I must have everything ready to go up for review, after that it will be drumming down into the code and setting up some basic agents.
Code wise this is coming along as well; I almost have the flow based programming node backend done. Its simple but it should allow me to get things up and running feature wise quite quickly.
For this entry I wanted to get back into the unreal engine, as I really enjoy using it.
Today I did what I like to think of as the Hello World of AI, getting an actor to move to a random point, wait and repeat.
This time I wanted to do it in two stages, first get it running using UE blueprint system, then take that blueprint and convert it to code.
So first the behaviour tree

As you can see, it’s simple, it picks a random point (this is a blueprint) and then moves to that point and waits for 3.0seconds.
The task blueprint allows for two values, the position it picks and how far it should look. Below is the blueprint that gets a random spot to move to.

Now to make the AI do the same thing in code. First, we need to create a class that inherits from UE task node system

We need to set the header file up so it exposes the same parameters in the blueprint and includes an override for ExecuteTask (this is where all the logic will go).
#pragma once
#include "CoreMinimal.h"
#include "BehaviorTree/BTTaskNode.h"
#include "TaskNode_GetRndPoint.generated.h"
/**
*
*/
UCLASS()
class BRAWL_API UTaskNode_GetRndPoint : public UBTTaskNode
{
GENERATED_BODY()
public:
UPROPERTY(EditAnywhere, BlueprintReadWrite)
FBlackboardKeySelector Position;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
float Radius;
public:
virtual EBTNodeResult::Type ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) override;
};
And finally our logic
#include "BehaviorTree\BlackboardComponent.h"
#include "NavigationSystem/Public/NavigationSystem.h"
EBTNodeResult::Type UTaskNode_GetRndPoint::ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory)
{
UBlackboardComponent* pxBlackboard = OwnerComp.GetBlackboardComponent();
if (!pxBlackboard)
{
return EBTNodeResult::Failed;
}
UNavigationSystemV1* pxNavSystem = FNavigationSystem::GetCurrent<UNavigationSystemV1>(GetWorld());
if (!pxNavSystem)
{
return EBTNodeResult::Failed;
}
const AActor* pxMe = OwnerComp.GetOwner();
if (!pxMe)
{
return EBTNodeResult::Failed;
}
const FVector xMyPosition = pxMe->GetActorLocation();
FNavLocation xRandomPoint;
pxNavSystem->GetRandomPointInNavigableRadius(xMyPosition, Radius, xRandomPoint);
pxBlackboard->SetValueAsVector(Position.SelectedKeyName, xRandomPoint);
return EBTNodeResult::Succeeded;
}
And that’s it, don’t forget to swap the task that uses the bp to our new task now added into ue.

See you next time 😛
