unfurl

Synapse

Dynamic decision-making framework

A decision-making framework where every possible action is evaluated by a set of considerations


πŸ‘€ Summary

A decision-making framework for Unreal Engine agents where every possible action is evaluated by a set of considerations. The resulting utility score selects which action to execute.

❓ What is Utility AI?

Utility AI evaluates many potential actions and ranks them based on their desirability. Each action gathers scores from considerations (for example health, distance or ammo) and the highest score wins. This approach results in more nuanced behaviour than simple state machines or behaviour trees.

When to use it

Why is it good?

πŸ“¦ Features

βš™οΈ Requirements

Unreal Engine 5.2+

πŸ› οΈ Installation

  1. Download the latest release.
  2. Extract the archive into your project’s Plugins folder: .../UEGame/Plugins/NsSynapse.
  3. Add the plugin to your UEGame.uproject and generate project files.
  4. Open the project and enable NsUtilityAI if prompted.

πŸ”§ Usage / API Reference

Key Classes

Main Functions

Getting Started

  1. In your AI actor, add UNsSynapseBrainComponent.
  2. Create custom UNsSynapseAction subclasses and assign them to the Brain Component’s PossibleActions array.
  3. Implement CalculateScore() in each UNsSynapseConsideration to read your game data.
  4. For each Consideration, adjust the Response Curve to shape decision sensitivity and assign it to the action that you want..
  5. Call ThinkAndReact() whenever the AI should evaluate and execute an action.

Shooter Enemy Example

An enemy might provide actions like:

Each action is scored by its considerations:

Action Considerations
Attack Player Player in sight, Ammo amount, Health percentage
Reload Weapon Ammo amount, Safe to reload
Find Cover Nearby cover points, Under fire
Retreat Health critically low, No cover available

C++ Example

// Actor with brain component
AMyBot::AMyBot()
{
    Brain = CreateDefaultSubobject<UNsSynapseBrainComponent>(TEXT("Brain"));
}

void AMyBot::BeginPlay()
{
    if (Brain != nullptr)
    {
        Brain->ThinkAndReact(); // Chose the best action and execute it
    }
}

// Custom consideration
UCLASS()
class UHealthConsideration : public UNsSynapseConsideration
{
    GENERATED_BODY()

public:
    virtual float CalculateScore_Implementation(AActor* InOwner) const override
    {
        if (const AMyBot* const Bot = Cast<AMyBot>(InOwner))
        {
            const float HealthScore = Bot->GetCurrentHealth() / Bot->GetMaxtHealth(); 
            return HealthScore;
        }
    }
};

// Custom action
UCLASS()
class UAttackAction : public UNsSynapseAction
{
    GENERATED_BODY()

    virtual void ExecuteAction_Implementation(AActor* InActor) override
    {
        UE_LOG(LogTemp, Log, TEXT("Firing at player"));
    }
};

⬇ Download on GitHub


Contact