SkillAgentSearch skills...

MistreevousSharp

Deterministic, lightweight behaviour trees for C#. JSON & DSL support. Built for game AI, real-time agents, and rapid iteration.

Install / Use

/learn @guinhx/MistreevousSharp
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

logo MistreevousSharp

NuGet version

MistreevousSharp is a lightweight, C# behaviour tree library for .NET 9.0 and .NET Standard 2.1, ported from the original mistreevous TypeScript library. Define complex AI behaviours using either JSON or a clean, minimal DSL (MDSL). Built for modularity, clarity, and fast iteration — perfect for games, simulations, and interactive agents.

Sorting Lunch

✨ Key Features

🔹 Minimal DSL or JSON-based definitions – define behaviours clearly and concisely
🔹 Built-in composite, decorator & leaf nodes – model complex logic using a toolbox of predefined node types
🔹 Async & promise-based actions – handle long-running behaviours and actions asynchronously
🔹 Lifecycle callbacks – define callbacks to invoke when tree nodes start, resume, or finish processing
🔹 Global functions & subtrees – reuse logic and subtree definitions across multiple agents
🔹 Guards – dynamically interrupt or cancel long-running behaviours
🔹 Randomised behaviour – weighted choices, random delays, seedable RNG for deterministic tree processing
🔹 Debugging tools – inspect the state of running tree instances and track node state changes
🔹 Optimized for performance – reduced memory allocations, perfect for Unity, Godot, or game servers
🔹 Cross-platform – works on .NET 9.0, .NET Standard 2.1, Unity, and more

🌳 What are Behaviour Trees?
Behaviour trees are hierarchical structures designed to model decision-making processes and are used to create complex AI via the modular composition of individual tasks, making it easy to sequence actions, handle conditions, and control flow in a readable and maintainable way.

🛠️ There is an in-browser editor and tree visualiser for the original TypeScript library that you can try HERE (MDSL definitions are compatible!)

Install

NuGet Package Manager

Install-Package MistreevousSharp

.NET CLI

dotnet add package MistreevousSharp

PackageReference

<PackageReference Include="MistreevousSharp" Version="1.0.0" />

Example

using Mistreevous;

// Define some behaviour for an agent.
var definition = @"root {
    sequence {
        action [Walk]
        action [Fall]
        action [Laugh]
    }
}";

// Create an agent that we will be modelling the behaviour for.
var agent = new MyAgent();

// Create the behaviour tree, passing our tree definition and the agent.
var behaviourTree = new BehaviourTree(definition, agent);

// Step the tree.
behaviourTree.Step();

// Output:
// 'walking!'
// 'falling!'
// 'laughing!'

Agent Implementation

public class MyAgent : IAgent
{
    public object? this[string propertyName] => 
        GetType().GetProperty(propertyName)?.GetValue(this);

    public State Walk()
    {
        Console.WriteLine("walking!");
        return State.Succeeded;
    }

    public State Fall()
    {
        Console.WriteLine("falling!");
        return State.Succeeded;
    }

    public State Laugh()
    {
        Console.WriteLine("laughing!");
        return State.Succeeded;
    }
}

Behaviour Tree Methods

IsRunning()

Returns true if the tree is in the RUNNING state, otherwise false.

GetState()

Gets the current tree state of SUCCEEDED, FAILED, READY or RUNNING.

Step()

Carries out a node update that traverses the tree from the root node outwards to any child nodes, skipping those that are already in a resolved state of SUCCEEDED or FAILED. After being updated, leaf nodes will have a state of SUCCEEDED, FAILED or RUNNING. Leaf nodes that are left in the RUNNING state as part of a tree step will be revisited each subsequent step until they move into a resolved state of either SUCCEEDED or FAILED, after which execution will move through the tree to the next node with a state of READY.

Calling this method when the tree is already in a resolved state of SUCCEEDED or FAILED will cause it to be reset before tree traversal begins.

Reset()

Resets the tree from the root node outwards to each nested node, giving each a state of READY.

GetTreeNodeDetails()

Gets the details of every node in the tree, starting from the root. This will include the current state of each node, which is useful for debugging a running tree instance.

Behaviour Tree Options

The BehaviourTree constructor can take an options object as an argument, the properties of which are shown below.

| Option | Type | Description | | :--------------------|:- |:- | | GetDeltaTime | Func<double> | A function returning a delta time in seconds that is used to calculate the elapsed duration of any wait nodes. If this function is not defined then DateTime.UtcNow is used instead by default. | | Random | Func<double> | A function returning a floating-point number between 0 (inclusive) and 1 (exclusive). If defined, this function is used to source a pseudo-random number to use in operations such as the selection of active children for any lotto nodes as well as the selection of durations for wait nodes, iterations for repeat nodes and attempts for retry nodes when minimum and maximum bounds are defined. If not defined then Random.NextDouble() will be used instead by default. This function can be useful in seeding all random numbers used in the running of a tree instance to make any behaviour completely deterministic. | | OnNodeStateChange | Action<NodeStateChange> | An event handler that is called whenever the state of a node changes. The change object will contain details of the updated node and will include the previous state and current state. |

Nodes

States

Behaviour tree nodes can be in one of the following states:

  • READY A node is in the READY state when it has not been visited yet in the execution of the tree.
  • RUNNING A node is in the RUNNING state when it is still being processed, these nodes will usually represent or encompass a long-running action.
  • SUCCEEDED A node is in a SUCCEEDED state when it is no longer being processed and has succeeded.
  • FAILED A node is in the FAILED state when it is no longer being processed but has failed.

Composite Nodes

Composite nodes wrap one or more child nodes, each of which will be processed in a sequence determined by the type of the composite node. A composite node will remain in the RUNNING state until it is finished processing the child nodes, after which the state of the composite node will reflect the success or failure of the child nodes.

Sequence

This composite node will update each child node in sequence. It will move to the SUCCEEDED state if all of its children have moved to the SUCCEEDED state and will move to the FAILED state if any of its children move to the FAILED state. This node will remain in the RUNNING state if one of its children remains in the RUNNING state.

MDSL

root {
    sequence {
        action [Walk]
        action [Fall]
        action [Laugh]
    }
}

JSON

{
    "type": "root",
    "child": {
        "type": "sequence",
        "children": [
            {
                "type": "action",
                "call": "Walk"
            },
            {
                "type": "action",
                "call": "Fall"
            },
            {
                "type": "action",
                "call": "Laugh"
            }
        ]
    }
}

Selector

This composite node will update each child node in sequence. It will move to the FAILED state if all of its children have moved to the FAILED state and will move to the SUCCEEDED state if any of its children move to the SUCCEEDED state. This node will remain in the RUNNING state if one of its children is in the RUNNING state.

MDSL

root {
    selector {
        action [TryThis]
        action [ThenTryThis]
        action [TryThisLast]
    }
}

JSON

{
    "type": "root",
    "child": {
        "type": "selector",
        "children": [
            {
                "type": "action",
                "call": "TryThis"
            },
            {
                "type": "action",
                "call": "ThenTryThis"
            },
            {
                "type": "action",
                "call": "TryThisLast"
            }
        ]
    }
}

Parallel

This composite node will update each child node concurrently. It will move to the SUCCEEDED state if all of its children have moved to the SUCCEEDED state and will move to the FAILED state if any of its children move to the FAILED state, otherwise it will remain in the RUNNING state.

MDSL

root {
    parallel {
        action [RubBelly]
        action [PatHead]
    }
}

JSON

{
    "type": "root",
    "child": {
        "type": "parallel",
        "children": [
            {
                "type": "action",
                "call": "RubBelly"
            },
            {
                "type": "action",
                "call": "PatHead"
            }
        ]
    }
}

Race

This composite node will update each child node concurrently. It will move to the SUCCEEDED state if any of its children have moved to the SUCCEEDED state and will move to the FAILED state if all of its children move to the FAILED state, otherwise it will remain in the RUNNING state.

MDSL

root {
    race {
        action [UnlockDoor]
        action [FindAlternativePath]
    }
}

JSON

{
    "type": "root",
    "child": {
        "type": "race",
        "children": [
            {
                "type": "

Related Skills

View on GitHub
GitHub Stars11
CategoryDevelopment
Updated12d ago
Forks2

Languages

C#

Security Score

80/100

Audited on Mar 18, 2026

No findings