Skip to content

Instantly share code, notes, and snippets.

@moppius
Last active April 2, 2022 23:58
Show Gist options
  • Save moppius/704141b5b722458fbde968e3e1e04135 to your computer and use it in GitHub Desktop.
Save moppius/704141b5b722458fbde968e3e1e04135 to your computer and use it in GitHub Desktop.
UE4 Angelscript BehaviourTree Nodes

UE4 Angelscript BehaviourTree Nodes

This information is intended for people who use Hazelight's UE4 Angelscript branch and want to work with UE4's AI Behaviour Trees using Angelscript.

Decorators, Tasks and Services

  • Decorators are used to gate or switch BT node logic - inherit from UBTDecorator_BlueprintBase class to make a new one
  • Services can update or change variables and tick at custom rates during task execution - inherit from UBTService_BlueprintBase class
  • Tasks do work until they succeed or fail as indicated by calling FinishExecute, which determines the outcome of branches in the tree - inherit from UBTTask_BlueprintBase class

Tips

  • Use Blackboard Keys for anything you want to be "modular" - if you have direct data entry into a node's properties then you will not be able to make that node behave differently when using the same Behaviour Tree on multiple AIs that might need different properties - Having Acceptance Radius as a float variable is an example of this where Epic have made it hard for people to reuse BTs across different-size enemies!
  • Always add types to the AllowedKeys array of any Blackboard Key property you add to your nodes - this will make it easier for users to select the correct type of key
  • Allow multiple key types if it makes sense - e.g. if your node wants a Direction, you can allow Vector, Object and Rotator key types since these can all be used to get a valid direction vector
/**
* An AI Behavior Tree Decorator written in Angelscript, returns the value of a specified boolean key.
*
* Note that while you can implement TickAI(), in most cases, Decorators rarely need to tick, and
* PerformConditionCheckAI is usually all you need to implement.
*/
class UBTDecorator_ExampleDecorator : UBTDecorator_BlueprintBase
{
default NodeName = "Example Decorator";
// Key that stores the current target location
UPROPERTY(Category=ExampleDecorator)
FBlackboardKeySelector BoolKey;
// Only allow the user to select Bool keys for this property
default BoolKey.AllowedTypes.AddUnique(Cast<UBlackboardKeyType>(UBlackboardKeyType_Bool::StaticClass().DefaultObject));
// Called whenever this Decorator performs a condition check in the Behavior Tree
UFUNCTION(BlueprintOverride)
bool PerformConditionCheckAI(AAIController OwnerController, APawn ControlledPawn)
{
Print("Performing condition check for Example Decorator!");
if (OwnerController == nullptr)
{
return false;
}
return OwnerController.Blackboard.GetValueAsBool(BoolKey.SelectedKeyName);;
}
};
// An AI Behavior Tree Service written in Angelscript
class UBTService_ExampleService : UBTService_BlueprintBase
{
default NodeName = "Example Service";
// Some value we want to expose to the graph
UPROPERTY(Category=ExampleService)
float SomeValue = 50.f;
// Called whenever this Service is activated by the Behavior Tree
UFUNCTION(BlueprintOverride)
void ActivationAI(AAIController OwnerController, APawn ControlledPawn)
{
Print("Activating Example Service!");
}
// Called whenever this Service is ticked by the Behavior Tree
UFUNCTION(BlueprintOverride)
void TickAI(AAIController OwnerController, APawn ControlledPawn, float DeltaSeconds)
{
Print("Ticking Example Service!");
}
};
// An AI Behavior Tree Task written in Angelscript
class UBTTask_ExampleTask : UBTTask_BlueprintBase
{
default NodeName = "Example Task";
// Some value we want to expose to the graph
UPROPERTY(Category=ExampleTask)
float SomeValue = 50.f;
// Called whenever this Task is first executed by the Behavior Tree
UFUNCTION(BlueprintOverride)
void ExecuteAI(AAIController OwnerController, APawn ControlledPawn)
{
Print("Executing Example Task!");
FinishExecute(true); // Pass false here if this node should inform the Behavior Tree that it failed
}
// Called while this Task is active in the Behavior Tree
UFUNCTION(BlueprintOverride)
void TickAI(AAIController OwnerController, APawn ControlledPawn, float DeltaSeconds)
{
Print("Ticking Example Task!");
// Return FinishExecute(true) here if your task succeeded, or FinishExecute(false) if it failed
}
// Called when the Behavior Tree aborts this Task's execution
UFUNCTION(BlueprintOverride)
void AbortAI(AAIController OwnerController, APawn ControlledPawn)
{
Print("Aborting Example Task!");
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment