Pre-release - APIs are more likely to change during the pre-release period.
A fresh take on Goal oriented action planning.
In GOAP, actions have preconditions, effects, and a cost. Boilerplate? Have a look.
public Cost ChopLog(){
    if(!hasAxe) return false;  // Precondtion
    hasFirewood = true;        // Effect
    return 4;                  // Cost
}Use A* or, if no cost function available, BFS.
- Engine agnostic models - test without pain.
- .NET Core compatible
- Unity integration with UPM support
- Demo project to help you get started
- [COMING SOON] integration with the BT Framework of Awesome, Active Logic 🚀
Clone the repository and add the package to your project as normal.
For Unity 3D:
- Add xgoap/package.jsonvia package manager > + > add package from disk.
- Alternatively, add "com.activ.goap": "https://github.com/active-logic/xgoap.git"to Packages/manifest.json
Planning requires a model and a goal; if available, also provide a heuristic. I will borrow Brent Owens' woodcutter example.
A woodcutter has the GetAxe, ChopLog and CollectBranches actions. Here is our implementation of the woodcutter planning model:
using Activ.GOAP;
public class WoodChopper : Agent, Clonable<WoodChopper>{
    public bool hasAxe, hasFirewood;
    Option[] opt;  // Caching reduces array alloc overheads
    public Option[] Options()
    => opt = opt ?? new Option[]{ ChopLog, GetAxe, CollectBranches };
    public Cost GetAxe(){
        if(hasAxe) return false;
        hasAxe = true;
        return 2;
    }
    public Cost ChopLog() => hasAxe ? (Cost)(hasFirewood = true, 4f) : (Cost)false;
    public Cost CollectBranches() => (hasFirewood = true, 8);
    // Clonable<WoodChopper>
    public WoodChopper Allocate() => new WoodChopper();
    public WoodChopper Clone(WoodChopper x){
        x.hasAxe      = hasAxe;
        x.hasFirewood = hasFirewood;
        return x;
    }
    // Override for correctness (don't compare refs) and faster hashes
    override public bool Equals(object other) => other is WoodChopper that
        && hasAxe == that.hasAxe && hasFirewood == that.hasFirewood;
    override public int GetHashCode() => (hasAxe ? 1 : 0)
                                       + (hasFirewood ? 2 : 0);
}Run the model and get the next planned action:
var chopper = new WoodChopper();
var solver  = new Solver<WoodChopper>();
var next    = solver.Next(chopper, goal: (x => x.hasFirewood, null));Parametric actions are supported; they are concise and type safe. Check the Baker example.
Quick and simple Unity integration via GameAI.cs - for details, read here.
Ready to GOAP? Follow the guide.
If you'd like to get involved, consider opening (or fixing) an issue. Your support is appreciated!
