初学者,自用笔记
黑板
可根据需要对节点添加黑板的初始化
namespace theBehaviourTrees
{
// 黑板系统,用于全局共享数据
public class Blackboard
{
private Dictionary<string, object> data = new Dictionary<string, object>();
// 设置值
public void SetValue(string key, object value)
{
if (data.ContainsKey(key))
{
data[key] = value;
}
else
{
data.Add(key, value);
}
}
// 获取值
public T GetValue<T>(string key)
{
if (data.TryGetValue(key, out object value))
{
return (T)value;
}
return default(T);
}
// 检查是否存在键
public bool HasKey(string key)
{
return data.ContainsKey(key);
}
// 移除键值对
public void RemoveKey(string key)
{
if (data.ContainsKey(key))
{
data.Remove(key);
}
}
// 清空黑板
public void Clear()
{
data.Clear();
}
}
}
节点
Node父类
namespace theBehaviourTrees
{
// 列表扩展类,提供洗牌功能
public static class ListExtensions
{
private static System.Random rng;
// 洗牌算法(Fisher-Yates)
public static IList<T> Shuffle<T>(this IList<T> list)
{
if (rng == null) rng = new System.Random();
int count = list.Count;
while (count > 1)
{
--count;
int index = rng.Next(count + 1);
(list[index], list[count]) = (list[count], list[index]); // 交换元素
}
return list;
}
}
// 行为树节点基类
public class Node
{
// 节点状态
public enum State
{
Success, // 成功
Failure, // 失败
Running // 运行中
}
protected State state;
public readonly string name; // 节点名称
public readonly int priority; // 优先级
public readonly List<Node> children = new List<Node>(); // 子节点列表
protected int currentChild; // 当前执行的子节点索引
protected Blackboard blackboard; // 黑板引用
// 构造函数
public Node(string name = "Node", int priority = 0, Blackboard blackboard = null)
{
this.name = name;
this.priority = priority;
this.blackboard = blackboard ?? new Blackboard();
}
// 添加子节点
public void AddChild(Node child)
{
children.Add(child);
child.blackboard = this.blackboard; // 子节点共享黑板
}
// 处理节点逻辑(默认执行当前子节点)
public virtual State Process() => children[currentChild].Process();
// 重置节点状态
public virtual void Reset()
{
currentChild = 0;
foreach (var child in children)
child.Reset();
}
}
}
行为树根节点
// 行为树根节点
public class BehaviourTree : Node
{
public BehaviourTree(string name = "BehaviourTree",Blackboard blackboard) : base(name,0,blackboard) { }
// 依次执行子节点,全部成功则返回成功
public override State Process()
{
while (currentChild < children.Count)
{
var state = children[currentChild].Process();
if (state != State.Success) return state;
currentChild++;
}
return State.Success;
}
}
序列节点
// 序列节点(依次执行,任一失败则整体失败)
public class Sequence : Node
{
public Sequence(string name = "Sequence", int priority = 0,Blackboard blackboard) : base(name, priority,blackboard) { }
public override State Process()
{
if (currentChild < children.Count)
{
switch (children[currentChild].Process())
{
case State.Running: return State.Running;
case State.Failure:
Reset();
return State.Failure;
case State.Success:
currentChild++;
return currentChild == children.Count ? State.Success : State.Running;
}
}
Reset();
return State.Success;
}
}
选择节点
// 选择节点(依次顺序执行,任一成功则整体成功)
public class Selector : Node
{
public Selector(string name = "Selector", int priority = 0,Blackboard blackboard) : base(name, priority,blackboard) { }
public override State Process()
{
if (currentChild < children.Count)
{
switch (children[currentChild].Process())
{
case State.Running: return State.Running;
case State.Success:
Reset();
return State.Success;
case State.Failure:
currentChild++;
return State.Running;
}
}
Reset();
return State.Failure;
}
}
// 优先级选择节点(按优先级执行)
public class PrioritySelector : Node
{
List<Node> sortedChildren;
List<Node> SortedChildren => sortedChildren ??= SortChildren();
// 按优先级排序子节点(降序)
protected virtual List<Node> SortChildren() => children.OrderByDescending(child => child.priority).ToList();
public PrioritySelector(string name = "PrioritySelector",Blackboard blackboard) : base(name,0,blackboard) { }
public override State Process()
{
if (currentChild < children.Count)
{
switch (children[currentChild].Process())
{
case State.Running: return State.Running;
case State.Success:
Reset();
return State.Success;
case State.Failure:
currentChild++;
return State.Running;
}
}
Reset();
return State.Failure;
}
public override void Reset()
{
base.Reset();
sortedChildren = null; // 重置排序结果
}
}
// 随机选择节点(随机顺序执行子节点)
public class RandomSelector : PrioritySelector
{
// 洗牌子节点(随机排序)
protected override List<Node> SortChildren() => children.Shuffle().ToList();
public RandomSelector(string name = "RandomSelector",Blackboard blackboard) : base(name,blackboard) { }
}
并行节点
// 并行节点的完成条件
public enum ParallelPolicy
{
// 所有子节点成功才返回成功,任一失败则整体失败
RequireAllSuccess,
// 任一子节点成功就返回成功,所有失败才整体失败
RequireAnySuccess
}
// 并行节点(同时执行多个子节点)
public class Parallel : Node
{
private readonly ParallelPolicy policy;
private Dictionary<Node, State> childStates; // 记录每个子节点的状态
public Parallel(string name = "Parallel",ParallelPolicy policy = ParallelPolicy.RequireAllSuccess,int priority = 0,Blackboard blackboard) : base(name, priority,blackboard)
{
this.policy = policy;
childStates = new Dictionary<Node, State>();
}
public override State Process()
{
// 初始化子节点状态记录
if (childStates.Count == 0)
{
foreach (var child in children)
{
childStates[child] = State.Running;
}
}
// 处理所有子节点
foreach (var child in children)
{
if (childStates[child] == State.Running)
{
childStates[child] = child.Process();
}
}
// 根据策略判断结果
switch (policy)
{
case ParallelPolicy.RequireAllSuccess:
return EvaluateRequireAllSuccess();
case ParallelPolicy.RequireAnySuccess:
return EvaluateRequireAnySuccess();
default:
return State.Failure;
}
}
// 评估"所有成功"策略
private State EvaluateRequireAllSuccess()
{
bool allSucceeded = true;
// 检查是否有子节点失败
foreach (var state in childStates.Values)
{
if (state == State.Failure)
{
Reset();
return State.Failure;
}
if (state == State.Running)
{
allSucceeded = false;
}
}
// 所有子节点都成功
if (allSucceeded)
{
Reset();
return State.Success;
}
// 还有子节点在运行中
return State.Running;
}
// 评估"任一成功"策略
private State EvaluateRequireAnySuccess()
{
bool allFailed = true;
// 检查是否有子节点成功
foreach (var state in childStates.Values)
{
if (state == State.Success)
{
Reset();
return State.Success;
}
if (state == State.Running)
{
allFailed = false;
}
}
// 所有子节点都失败
if (allFailed)
{
Reset();
return State.Failure;
}
// 还有子节点在运行中
return State.Running;
}
public override void Reset()
{
base.Reset();
childStates.Clear();
foreach (var child in children)
{
child.Reset();
}
}
}
子树节点
// 子树节点,封装一个完整的行为树作为子节点
public class SubtreeNode : Node
{
private readonly BehaviourTree subtree; // 子树行为树
public SubtreeNode(BehaviourTree subtree, string name = "SubtreeNode", int priority = 0,Blackboard blackboard = null) : base(name, priority,blackboard)
{
this.subtree = subtree;
}
public override State Process()
{
// 执行子树的逻辑
return subtree.Process();
}
public override void Reset()
{
base.Reset();
subtree.Reset(); // 重置子树
}
}
策略
策略接口
// 策略接口(叶子节点执行逻辑),包含黑板引用
public interface IStrategy
{
Node.State Process(); // 执行逻辑
void Reset(); // 重置状态
Blackboard Blackboard { get; set; } // 黑板引用
}
动作策略
// 动作策略(执行委托,使用黑板)
public class ActionStrategy : IStrategy
{
readonly System.Action<Blackboard> action; // 要执行的动作,带黑板参数
public Blackboard Blackboard { get; set; } // 黑板引用
public ActionStrategy(System.Action<Blackboard> action) => this.action = action;
public Node.State Process()
{
action(Blackboard);
return Node.State.Success;
}
public void Reset() { }
}
条件策略
// 条件策略(判断布尔条件,使用黑板)
public class Condition : IStrategy
{
readonly System.Func<Blackboard, bool> condition; // 条件函数,带黑板参数
public Blackboard Blackboard { get; set; } // 黑板引用
public Condition(System.Func<Blackboard, bool> condition) => this.condition = condition;
public Node.State Process()
{
return condition(Blackboard) ? Node.State.Success : Node.State.Failure;
}
public void Reset() { }
}
简单巡逻策略
// 巡逻策略(沿指定点巡逻,使用黑板)
public class PatrolStrategy : IStrategy
{
readonly Transform entity; // 巡逻实体
readonly NavMeshAgent agent; // 导航组件
readonly List<Transform> patrolPoints; // 巡逻点
readonly float patrolSpeed; // 巡逻速度
int currentIndex; // 当前巡逻点索引
bool isPathCalculated; // 路径是否计算完成
public Blackboard Blackboard { get; set; } // 黑板引用
public PatrolStrategy(Transform entity, NavMeshAgent agent, List<Transform> patrolPoints, float patrolSpeed = 2f)
{
this.entity = entity;
this.agent = agent;
this.patrolPoints = patrolPoints;
this.patrolSpeed = patrolSpeed;
agent.speed = patrolSpeed;
}
// 执行巡逻逻辑
public Node.State Process()
{
// 可以从黑板中获取目标等数据
// 例如:Transform target = Blackboard.GetValue<Transform>("CurrentTarget");
if (currentIndex == patrolPoints.Count)
return Node.State.Success; // 巡逻完成
var target = patrolPoints[currentIndex];
agent.SetDestination(target.position);
entity.LookAt(target);
// 到达当前巡逻点
if (isPathCalculated && agent.remainingDistance < 0.1f)
{
currentIndex++;
isPathCalculated = false;
}
if (agent.pathPending)
isPathCalculated = true;
return Node.State.Success;
}
// 重置巡逻(从头开始)
public void Reset() => currentIndex = 0;
}
叶子与装饰器
叶子
// 叶子节点(执行具体策略,传递黑板)
public class Leaf : Node
{
readonly IStrategy strategy; // 执行策略
// 构造函数
public Leaf(IStrategy strategy, string name, int priority = 0) : base(name, priority)
{
this.strategy = strategy;
strategy.Blackboard = this.blackboard; // 设置策略的黑板引用
}
// 执行策略逻辑
public override State Process() => strategy.Process();
// 重置策略
public override void Reset() => strategy.Reset();
}
反转修饰器
// 反转装饰器(反转子节点结果)
public class Inverter : Node
{
public Inverter(string name = "Inverter") : base(name) { }
public override State Process()
{
switch (children[0].Process())
{
case State.Running: return State.Running;
case State.Failure: return State.Success; // 失败→成功
default: return State.Failure; // 成功→失败
}
}
}
重复直到失败装饰器
// 重复直到失败装饰器
public class UntilFail : Node
{
public UntilFail(string name = "UntilFail") : base(name) { }
public override State Process()
{
if (children[0].Process() == State.Failure)
{
Reset();
return State.Failure;
}
return State.Running; // 成功则继续运行
}
}
限制器
// 限制器,限制子节点执行次数或时长
public class Limiter : Node
{
private readonly Node child;
private readonly int maxExecutions; // 最大执行次数
private readonly float maxDuration; // 最大执行时长
private int executionCount; // 当前执行次数
private float startTime; // 开始执行时间
// 构造函数:可选择限制次数或时长
public Limiter(Node child, string name = "Limiter", int maxExecutions = -1, float maxDuration = -1) : base(name)
{
this.child = child;
this.maxExecutions = maxExecutions;
this.maxDuration = maxDuration;
AddChild(child);
}
public override State Process()
{
// 检查是否达到执行次数限制
if (maxExecutions > 0 && executionCount >= maxExecutions)
return State.Failure;
// 检查是否达到执行时长限制
if (maxDuration > 0 && Time.time - startTime >= maxDuration)
return State.Failure;
// 执行子节点
var state = child.Process();
// 记录执行次数和时间
if (state == State.Success || state == State.Failure)
{
executionCount++;
if (executionCount == 1)
startTime = Time.time;
}
return state;
}
public override void Reset()
{
base.Reset();
executionCount = 0;
startTime = 0;
child.Reset();
}
}
延迟器
// 延迟器,延迟执行子节点
public class Delay : Node
{
private readonly Node child;
private readonly float delayTime; // 延迟时间
private float startTime; // 开始延迟的时间
private bool isDelaying = false; // 是否正在延迟
public Delay(Node child, string name = "Delay", float delayTime = 2f) : base(name)
{
this.child = child;
this.delayTime = delayTime;
AddChild(child);
}
public override State Process()
{
// 开始延迟
if (!isDelaying)
{
startTime = Time.time;
isDelaying = true;
return State.Running;
}
// 检查延迟是否结束
if (Time.time - startTime >= delayTime)
{
isDelaying = false;
return child.Process();
}
return State.Running;
}
public override void Reset()
{
base.Reset();
isDelaying = false;
child.Reset();
}
}
概率器
// 概率器,按概率执行子节点
public class RandomDecorator : Node
{
private readonly Node child;
private readonly float probability; // 执行概率 (0-1)
private bool hasDecided = false; // 是否已经决定是否执行
private bool shouldExecute = false; // 是否应该执行子节点
public RandomDecorator(Node child, string name = "Random", float probability = 0.5f) : base(name)
{
this.child = child;
this.probability = probability;
AddChild(child);
}
public override State Process()
{
// 决定是否执行子节点
if (!hasDecided)
{
shouldExecute = UnityEngine.Random.value < probability;
hasDecided = true;
}
// 执行或跳过子节点
if (shouldExecute)
return child.Process();
else
return State.Failure;
}
public override void Reset()
{
base.Reset();
hasDecided = false;
shouldExecute = false;
child.Reset();
}
}
打断器
// 打断器,监测外部条件并打断子节点
public class Interruptor : Node
{
private readonly Node child;
private readonly System.Func<bool> interruptCondition; // 打断条件
private readonly State returnState; // 打断后返回的状态
public Interruptor(Node child, System.Func<bool> interruptCondition,
string name = "Interruptor", State returnState = State.Failure) : base(name)
{
this.child = child;
this.interruptCondition = interruptCondition;
this.returnState = returnState;
AddChild(child);
}
public override State Process()
{
// 检查是否需要打断
if (interruptCondition())
{
child.Reset();
return returnState;
}
// 执行子节点
return child.Process();
}
public override void Reset()
{
base.Reset();
child.Reset();
}
}