4 releases
0.1.3 | Mar 7, 2024 |
---|---|
0.1.2 | Mar 7, 2024 |
0.1.1 | Mar 7, 2024 |
0.1.0 | Jan 19, 2024 |
#54 in Robotics
94 downloads per month
13KB
88 lines
Simple Behavior Tree for Rust
This Rust crate provides a straightforward implementation of behavior trees, offering a compact yet powerful tool for developing AI behaviors and decision-making systems in games and robotics. Behavior trees are a popular and highly effective technique for modeling complex behaviors through a combination of simple tasks.
Features
- Sequence Nodes: Execute children nodes sequentially, stopping at the first failure.
- Selector Nodes: Execute children nodes until one succeeds.
- Parallel Nodes: Execute children nodes in parallel, supporting both "all must succeed" and "any can succeed" modes.
- Action Nodes: Execute custom logic through Rust closures or functions.
Getting Started
Prerequisites
Ensure you have Rust and Cargo installed on your machine. Visit The Rust Programming Language website for installation instructions if needed.
Installation
Add simple_behavior_tree
to your project's Cargo.toml
:
[dependencies]
simple_behavior_tree = "0.1.3"
Basic Usage
This crate allows you to construct behavior trees using sequence nodes, selector nodes, parallel nodes, and action nodes. Below are quick examples demonstrating how to create a simple behavior tree with these node types:
Sequence Node Example
Sequence nodes execute their children sequentially, stopping at the first failure. Here's how to create and execute a sequence node:
use simple_behavior_tree::{BTNode, BTStatus};
fn main() {
let action_success = || {
println!("Action success executed");
BTStatus::Success
};
let action_failure = || {
println!("Action failure executed");
BTStatus::Failure
};
// Create a sequence node
let sequence_node = BTNode::Sequence(vec![
BTNode::Action(action_success),
BTNode::Action(action_failure),
]);
// Execute the sequence node
println!("Executing Sequence Node:");
match sequence_node.tick() {
BTStatus::Success => println!("Sequence Node succeeded"),
BTStatus::Failure => println!("Sequence Node failed"),
BTStatus::Running => println!("Sequence Node is still running"),
}
}
Selector Node Example
Selector nodes execute their children until one succeeds. Here's how to create and execute a selector node:
use simple_behavior_tree::{BTNode, BTStatus};
fn main() {
let action_success = || {
println!("Action success executed");
BTStatus::Success
};
let action_failure = || {
println!("Action failure executed");
BTStatus::Failure
};
// Create a selector node
let selector_node = BTNode::Selector(vec![
BTNode::Action(action_failure),
BTNode::Action(action_success),
]);
// Execute the selector node
println!("\nExecuting Selector Node:");
match selector_node.tick() {
BTStatus::Success => println!("Selector Node succeeded"),
BTStatus::Failure => println!("Selector Node failed"),
BTStatus::Running => println!("Selector Node is still running"),
}
}
Parallel Node Example
Parallel nodes execute all children in parallel and succeed based on the configured mode (e.g., AnySuccess). Here's how to create and execute a parallel node with AnySuccess mode:
use simple_behavior_tree::{BTNode, BTStatus, ParallelMode};
fn main() {
let action_success = || {
println!("Action success executed");
BTStatus::Success
};
let action_failure = || {
println!("Action failure executed");
BTStatus::Failure
};
// Create a parallel node with AnySuccess mode
let parallel_node = BTNode::Parallel(
ParallelMode::AnySuccess,
vec![
BTNode::Action(action_success),
BTNode::Action(action_failure),
],
);
// Execute the parallel node
println!("\nExecuting Parallel Node:");
match parallel_node.tick() {
BTStatus::Success => println!("Parallel Node succeeded"),
BTStatus::Failure => println!("Parallel Node failed"),
BTStatus::Running => println!("Parallel Node is still running"),
}
}
Condition Node Example
Condition nodes are used to evaluate whether a specific condition is met. They return Success
if the condition is true, and Failure
otherwise. Here's how to create and use a condition node:
use simple_behavior_tree::{BTNode, BTStatus};
// Condition function
fn is_player_in_range() -> BTStatus {
// Here, you would have logic to determine if the player is in range
println!("Checking if player is in range...");
BTStatus::Success // or BTStatus::Failure based on your condition
}
// Action function
fn attack_player() -> BTStatus {
println!("Attacking player!");
BTStatus::Success // or BTStatus::Failure based on the action outcome
}
fn main() {
// Create a sequence node with a condition and an action
let mut bt = BTNode::Sequence(vec![
BTNode::Condition(is_player_in_range),
BTNode::Action(attack_player),
]);
// Execute the behavior tree
println!("Executing Behavior Tree:");
match bt.tick() {
BTStatus::Success => println!("Behavior Tree succeeded."),
BTStatus::Failure => println!("Behavior Tree failed."),
BTStatus::Running => println!("Behavior Tree is still running."),
}
}
This example demonstrates the basic setup for sequence, selector, parallel, and condition nodes within a behavior tree. Each type of node has its own unique behavior:
- Sequence Nodes: Execute their children sequentially, stopping at the first failure.
- Selector Nodes: Execute their children until one succeeds.
- Parallel Nodes: Execute all children in parallel and succeed based on the configured mode (e.g., AnySuccess).
- Condition Nodes: Evaluate a specific condition and return success if the condition is met, otherwise return failure.
By combining these nodes, including conditions for decision-making, you can build complex behavior trees for AI systems in games, robotics, and more. This flexibility allows for sophisticated decision processes, where actions can be taken based on the evaluation of conditions, and tasks can be organized in sequences, selections, or parallel executions.
Contributing
Contributions to simple_behavior_tree
are welcome! Whether it's bug reports, feature requests, or pull requests, all contributions help make this project better. To contribute:
- Fork the repository.
- Create a new branch for each feature or improvement.
- Send a pull request from each feature branch to the main branch for review.
License
simple_behavior_tree
is distributed under the MIT License, see LICENSE for more information.
Acknowledgments
- Thanks to the Rust community for providing excellent documentation and resources.
- Inspired by various behavior tree implementations and discussions in the game development community.