diff --git a/README.md b/README.md index c37be32..633eccb 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,9 @@ # UnitaskFBT -UnitaskFBT is the second version of the [Functional Behavior Tree (FBT)](https://github.com/dmitrybaltin/FunctionalBT) project, designed for building sophisticated AI in Unity or C# projects. +UnitaskFBT(or UFBT) is the second generation of the [Functional Behavior Tree (FBT)](https://github.com/dmitrybaltin/FunctionalBT) project, designed for building sophisticated AI in Unity or C# projects. -Unlike classical FBT, this version uses asynchronous functions, allowing you to write compact, readable, and maintainable code for complex AI behaviors involving long-running actions. +Unlike classical FBT, UFBT uses asynchronous functions, allowing you to write compact, readable, and maintainable code for complex AI behaviors involving long-running actions. ## Why UnitaskFBT? @@ -16,7 +16,8 @@ Building complex AI often requires sequences of actions that take several second - Chaining into combos - Reacting to the player’s actions during the attack -Classical behavior trees require multiple state variables and constant checks to manage these sequences, which can make code messy and hard to debug. +Classical BT require state variables and their checks to manage these sequences, which can make code messy and hard to debug. + With **UnitaskFBT**, you can use async/await syntax to handle long-running actions naturally, keeping your code simple, readable, and efficient. ## Key Features @@ -37,7 +38,7 @@ With **UnitaskFBT**, you can use async/await syntax to handle long-running actio static b => b.MeleeAttack()), //Action static b => b.If( static b => b.TargetDistance < 3f, - static b => b.RangeAttack()), //The only continuous function here that can be "running" + static b => b.RangeAttack()), //Continuous function that can be "running" static b => b.If( static b => b.TargetDistance < 8f, static b => b.Move()), @@ -55,3 +56,76 @@ Notes: For a detailed comparison between UnitaskFBT and a classical FBT, see this repository [FbtExample](https://github.com/dmitrybaltin/FbtExample) +## Installation + +You can install Functional Behavior Tree (FBT) in Unity using one of the following methods: + +### 1. Install from GitHub as a Unity Package +1. Open your Unity project. +1. Go to **Window → Package Manager**. +1. Click the **+** button in the top-left corner and choose **Add package from git URL...**. +1. Enter the URL: https://github.com/dmitrybaltin/UnitaskFBT.git +1. Click **Add**. The package will be imported into your project. + +### 2. Install via OpenUPM + +1. Open your Unity project. +2. Go to **Edit → Project Settings → Package Manager → Scoped Registries** +3. Add a new registry for OpenUPM: + - **Name:** OpenUPM + - **URL:** `https://package.openupm.com` + - **Scopes:** `com.baltin` +4. Open the **Package Manager** (`Window → Package Manager`). +5. Click **+ → Add package from git URL...** (or search in the registry if the package appears) and enter: **com.baltin.ufbt** + +### 3. Install as a Git Submodule + +1. Navigate to your Unity project folder in a terminal. +1. Run +``` +git submodule add https://github.com/dmitrybaltin/UnitaskFBT.git Packages/UnitaskFBT +git submodule update --init --recursive +``` + +## Dependencies + +This project depends on **UniTask**, which serves as the foundation because it is the most popular and highly optimized async solution for Unity. + +If you want to avoid this dependency, you can manually replace `UniTask` with `Task`, `ValueTask`, or `Awaitable` in the source; it is not a difficult - the project code is ~200 lines - it is a pattern, not a lib. + +Unfortunately, it is impossible in C# to implement a single, fully generic async solution that works for all Task-like or awaitable types at once — otherwise I would have done it here. + +If there is demand from users, I will provide additional versions of the async FBT based on `Task`, `ValueTask`, or a custom awaitable. + +## Dependency + +This project depends on **UniTask**, which serves as the foundation because it is the most popular and highly optimized async solutions for Unity. + +If you want to avoid this dependency, you can manually replace `UniTask` with `Task`, `ValueTask`, or a custom awaitable type in the source. (All the codebase of teh project is ~200 lines including comments). + +Unfortunately, it's not practical to implement a single, fully generic async solution that works with all Task-like types at once. + +If there is enough demand, I may provide additional versions of the library based on `Task`, `ValueTask`, or custom awaitables. + + +# Async Functional Behavior Tree Philosophy + +My initial idea was to create a debuggable and simple behavior tree using the functional programming features of C#. +That’s how [FunctionalBT](https://github.com/dmitrybaltin/FunctionalBT) was born. By the way, because of its simplicity, the tree turned out to be not only easy to understand, but also zero-allocated and highly performant. + +However, all classic behavior tree implementations — including mine — share one inherent complexity: the **Running ** return value. + +When a node returns Running, it should continue execution on the next tick. But a classic tree always starts from the root, so intermediate nodes may intercept control, and execution never returns to the previously running node automatically. The responsibility of synchronizing node execution falls to the AI developer, who typically introduces flags or state variables. For complex AI the synchronization code grows exponentially and becomes a combinatorial problem. + +Take, for example, an NPC attack. It is not a single short action but a sequence lasting several seconds, with multiple branches: preparation, attack animation, hit reaction, miss reaction, and so on. +You may also have different attack types, such as melee and ranged. Ideally, each such complex sequence should be represented as one branch of the tree and executed until it completes. +But in a classic tree this requires manually storing the current action and its stage. In practice, this means you end up building a kind of a state machine again — the very thing behavior trees were supposed to replace. + +**How to solve it?** + +C# already has asynchronous functions, designed for long-running actions. Combining them with the behavior tree concept solves the synchronization problem: +- less boilerplate code, +- easier AI development, +- and cleaner, more maintainable logic. + +This is the goal of this project. diff --git a/package.json b/package.json index 9d3548d..7fa24c3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "com.baltin.ufbt", - "version": "0.6.1", + "version": "0.6.2", "displayName": "UniTaskFBT", "description": "Async Functional Behavior Tree implementation based on UniTask", "unity": "2021.2",