当前位置:   article > 正文

【Unity插件】 BehaviorTree 原理_unity行为树bt

unity行为树bt

在这里插入图片描述

行为树网站

链接: link
https://opsive.com/support/documentation/behavior-designer/overview/

什么是行为树

行为树或有限状态机

安装

行为树组件

在这里插入图片描述

1、API接口来开启和关闭行为树
public void EnableBehavior();
public void DisableBehavior(bool pause = false);

2、查找Task节点
TaskType FindTask<TaskType>();
List<TaskType> FindTasks<TaskType>();
Task FindTaskWithName(string taskName);
List<Task> FindTasksWithName(string taskName);

3、获取行为树的当前执行状态
behaviorTree.ExecutionStatus

4、注册行为树事件
OnBehaviorStart
OnBehaviorRestart
OnBehaviorEnd

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

从脚本创建行为树

using UnityEngine;
using BehaviorDesigner.Runtime;

public class CreateTree : MonoBehaviour
{
	public ExternalBehaviorTree behaviorTree;

	private void Start()
	{
		var bt = gameObject.AddComponent<BehaviorTree>();
		bt.StartWhenEnabled = false;
		bt.ExternalBehavior = behaviorTree;
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

公共变量 behaviorTree 包含外部行为树的引用。
当新创建的树加载时,它将为其所有任务加载外部行为树。
为了防止树立即运行,我们将 StartWhenEnabled 设置为 false。
然后可以使用 bt.EnableBehavior() 手动启动树。

行为管理器BehvaiorManager

在这里插入图片描述
该组件管理场景中所有行为树。
更改UpdateInterval属性:更新间隔属性来控制行为树的跳动tick频率。
—“Every Frame每一帧”将在更新循环中的每一帧中tick。
—“Specify Seconds指定秒数”在给定的秒数内tick。
—“Manual手动”,通过脚本来调用Tick。

BehaviorManager.instance.Tick();
BehaviorManager.instance.Tick(BehaviorTree) //指定行为树
  • 1
  • 2

栗子
在这里插入图片描述
Repeater节点设置为重复 5 次。
如果 Task Execute Type 设置为 No Duplicates,则 Play Sound 任务将仅在单个 tick 中执行一次。
如果任务执行类型设置为 Count ,则可以指定单次Tick最大执行计数。
如果指定值为 5,则 Play Sound 任务将在单个Tick中执行所有 5 次。

任务Tasks节点

行为树就是各个任务的集合
Task具有与 Unity 的 MonoBehaviour 类似的 API

// OnAwake 在行为树启用时调用一次。将其视为构造函数。
void OnAwake ();
 
// OnStart 在执行前立即调用。它用于设置需要从上一次运行中重置的任何变量。
TaskStatus OnUpdate();
 
// OnUpdate 运行实际任务。
TaskStatus OnUpdate();
 
// OnFixedUpdate 在 FixedUpdate 循环期间执行。TaskStatus 必须在 OnUpdate 中返回。
void OnFixedUpdate ();
 
// OnEnd 在执行成功或失败后调用。
void OnEnd ();
 
// 当行为暂停或恢复时调用 OnPause。
void OnPause ( bool paused );

// 返回任务的优先级,由优先级选择器使用。
float GetPriority ();
 
// 返回任务的效用,由效用理论的效用选择器使用。
float GetUtility ();
 
// OnBehaviorComplete 在行为树完成执行后被调用。
void OnBehaviorComplete ();
 
// 检查器调用 OnReset 来重置公共属性
void OnReset ();
 
// 允许从任务中调用 OnDrawGizmos。
void OnDrawGizmos ();
 
// 保留对拥有此任务的行为的引用。
Behavior Owner;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

Tasks公开三个属性: name, comment, and instant.
instant属性,取消勾选,会在下个任务之前等待更新Tick

Task执行流程
在这里插入图片描述

父任务ParentTasks

父任务 是 Composite复合task和Decorator装饰task

// 父任务可以拥有的最大子任务数。通常会是 1 或 int.MaxValue 
public virtual int MaxChildren ();

// 判断当前任务是否为并行任务的布尔值。
public virtual bool CanRunParallelChildren();
   
// 当前活动子节点的索引。
public virtual int CurrentChildIndex ();
   
// 判断当前任务是否可以执行的布尔值。
public virtual bool CanExecute ();   

// 对执行状态应用装饰器。
公共虚拟TaskStatus装饰(TaskStatus状态);

// 通知父任务子任务已经执行,状态为childStatus。
public virtual void OnChildExecuted ( TaskStatus childStatus );   

// 通知父任务index处的childIndex处的子任务已经执行,状态为childStatus。
public virtual void OnChildExecuted ( int childIndex , TaskStatus childStatus );   

// 通知子任务已经开始运行。
public virtual void OnChildStarted ();
   
// 通知并行任务索引处的子节点 childIndex 已开始运行。
public virtual void OnChildStarted ( int childIndex );
   
// 一些父任务需要能够覆盖状态,例如并行任务。
public virtual TaskStatus OverrideStatus (TaskStatus状态);
   
// 如果中断节点已经被中断,中断节点将覆盖状态。
public virtual TaskStatus OverrideStatus ();

// 通知复合任务已触发条件中止并且应重置子索引。
public virtual void OnConditionalAbort ( int childIndex );
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

调试Debugger

在task节点上可以设置断点
可以禁用一组Tasks

在这里插入图片描述
如果在BT面板上的Behavior选项上勾选了Log Task Changes,可以在控制台上看到日志输出

GameObject - Behavior: Push task Sequence (index 0) at stack index 0
GameObject - Behavior: Push task Wait (index 1) at stack index 0
GameObject - Behavior: Pop task Wait (index 1) at stack index 0 with status Success
GameObject - Behavior: Push task Wait (index 2) at stack index 0
GameObject - Behavior: Pop task Wait (index 2) at stack index 0 with status Success
GameObject - Behavior: Pop task Sequence (index 0) at stack index 0 with status Success
Disabling GameObject - Behavior
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

{game object name } - {behavior name}: {task change} {task type} (index {task index}) at stack index {stack index} {optional status}

{game object name} 是行为树附加到的游戏对象的名称。
{behavior name} 是行为树的名称。
{task change} 表示任务的新状态。例如,一个任务在开始执行时将被压入堆栈,并在执行完成时弹出。
{task type} 是任务的类类型。
{task index} 是深度优先搜索中任务的索引。
{stack index} 是任务被推送到的堆栈的索引。如果您有一个并行节点,那么您将使用多个堆栈。
{optional status} 是该特定更改的任何额外状态。pop任务会输出任务状态。

变量Variables

动态变量

在这里插入图片描述
动态变量允许您使用范围有限的临时变量。
如果您想在有限数量的任务之间共享数据并且不需要访问这些任务之外的变量,这些变量非常有用。

动态变量现在将在您的树中使用。
对于引用相同动态变量名称的任何字段,动态变量将具有相同的值。该名称区分大小写,不应与树中的局部变量相同。

全局变量

在这里插入图片描述
在这里插入图片描述
全局变量类似于局部变量,只是任何行为树都可以访问同一变量的实例。
首次添加全局变量时,会创建一个存储所有全局变量的资产文件。该文件在 /Behavior Designer/Resources/BehaviorDesignerGlobalVariables.asset 中创建。
全局变量的赋值方式与局部变量非常相似。

创建共享变量

要创建共享变量,请将 SharedVariable 类型子类化并实现以下方法。关键字 OBJECT_TYPE 应替换为您要创建的共享变量的类型。

    [System.Serializable]
    public class CustomClass
    {
        public int myInt;
        public Object myObject;
    }

    [System.Serializable]
    public class SharedCustomClass : SharedVariable<CustomClass>
    {
        public static implicit operator SharedCustomClass(CustomClass value) { return new SharedCustomClass { Value = value }; }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

从非任务对象访问变量

通常通过将变量名称分配给行为设计器检查器面板中的任务字段来引用变量。
非Task派生类(例如MonoBehaviour)也可以通过调用该方法来访问局部变量:
可以使用 SharedVariable.Value 属性获取和设置变量的值。
同样,可以通过获取对 GlobalVariable 实例的引用来访问全局变量:

behaviorTree.GetVariable("MyVariable");
behaviorTree.SetVariable("MyVariable", value);
behaviorTree.SetVariableValue("MyVariableName", value);

using UnityEngine;
using BehaviorDesigner.Runtime;

public class AccessVariable : MonoBehaviour
{
   public BehaviorTree behaviorTree;

   public void Start()
   {
      var myIntVariable = (SharedInt)behaviorTree.GetVariable("MyVariable");
      myIntVariable.Value = 42;
   }
}

GlobalVariables.Instance.GetVariable("MyVariable");
GlobalVariables.Instance.SetVariable("MyVariable", value);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

有条件的终止Conditional Abort

Conditional Abort允许您的行为树动态响应更改,防止必须重新运行整个树

有四种不同的中止类型:None、Self、Lower Priority 和 Both。

在这里插入图片描述

本文内容由网友自发贡献,转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/110554
推荐阅读
相关标签
  

闽ICP备14008679号