赞
踩
组件下方的行为会平行执行
分别为下方的三个组件添加了三个输出到Console的Action,可以发现Console中在同一时间做了三个输出
组件下方的行为会按照从左到右的顺序依次执行
可以从输出的时间发现,Sequence下方的行为是依次执行的
当所有子节点都返回Success时,它才返回Success
当某个子节点返回Failure时,顺序节点就会立刻返回Failure
组件下方的行为会选择执行
组件下方的行为会按照选择的次序执行,类似于if else…,一旦前面的执行成功,后面的就不会再执行
如果所有子节点都返回Failure,选择节点才返回Failure
使用Log Value行为,输出刚刚创建的RandomNumer
可以发现,最终生成了一个随机数3,并输出了出来
namespace BehaviorTreeVariable { // 书写一个自己的变量类 public class Student { public string name; public int age; public override string ToString() { return $"name: {name}, age: {age}"; } } } namespace BehaviorDesigner.Runtime { // 除了需要书写一个自己的变量类以外,还需要写一个Shared类,只有Shared类的变量才能显示在Behavior Tree的Inspector面板中 [System.Serializable] public class SharedStudent : SharedVariable<Student> { public static implicit operator SharedStudent(Student stu) { return new SharedStudent { mValue = stu }; } } }
在 BehaviorDesigner.Runtime 中写 Shared 类需要遵循以下格式
namespace BehaviorDesigner.Runtime
{
[System.Serializable]
public class SharedT : SharedVariable<T>
{
public static implicit operator SharedT(T value)
{
return new SharedT { mValue = value };
}
}
}
这样就可以在变量类型列表中看到我们拓展的 Student 变量类型了
通过代码获取变量:
public SharedVariable GetVariable(string name); // 获取变量值
public void SetVariable(string name, SharedVariable item); // 为变量赋值
var bt = GetComponent<BehaviorTree>(); // 访问成员变量 var stu = (SharedStudent)bt.GetVariable("Ousun"); Debug.Log(stu.Value.ToString()); // 修改变量值 stu.Value.name = "Ousun"; // 修改变量值内的成员变量内容 bt.SetVariable("Ousun", stu); // 将stu变量赋值给Ousun // 构建新的成员对象 SharedStudent newSharedStu = new SharedStudent(); Student newStu = new Student(); newStu.name = "Ousun"; newStu.age = 20; newSharedStu.SetValue(newStu); // 赋值成员变量 bt.SetVariable("Ousun", newSharedStu);
using System.Collections; using System.Collections.Generic; using UnityEngine; // 需要包含额外的头文件 using BehaviorDesigner.Runtime; using BehaviorDesigner.Runtime.Tasks; public class MyRandomInt : Action // 继承Action { public SharedInt randomNum; // Sharedxxx类型的变量即为可以显示在BehaviorDesigner-Inspector中的变量 // 如果不需要在Inspector中显示,则不用加Shared,直接定义即可 // 重写OnUpdate()方法,注意OnUpdate()方法有返回值,返回值为TaskStatus类型 public override TaskStatus OnUpdate() { randomNum.Value = Random.Range(5, 10); // 生成随机数,注意使用.Value return TaskStatus.Success; // 返回成功 // Action类型一般不会返回Failure } }
测试:自定义相加的行为,并输出结果
定义行为如下
public class MyAdd: Action
{
public SharedFloat num1;
public SharedFloat num2;
public SharedFloat result;
public override TaskStatus OnUpdate()
{
result.Value = num1.Value + num2.Value;
return TaskStatus.Success;
}
}
Behavior Tree如下:
输出结果如下:
using System.Collections; using System.Collections.Generic; using UnityEngine; // 同样需要包含额外的头文件 using BehaviorDesigner.Runtime; using BehaviorDesigner.Runtime.Tasks; public class MyBiggerThan : Conditional // 继承Conditional { public SharedInt num1; // Inspector中的num1 public SharedInt num2; // Inspector中的num2 // 重写OnUpdate()方法,注意OnUpdate()方法有返回值,返回值为TaskStatus类型 public override TaskStatus OnUpdate() { if (num1.Value > num2.Value) return TaskStatus.Success; else return TaskStatus.Failure; } }
测试:输出比较结果
MyBiggerThan类不变,Behavior Tree如下:
输出结果:
交换num1和num2的值后的输出结果
其他需要override的函数参考:
//This is the agent for whom the action will take place. public Component agent {get;} //This is the blackboard that you can use to read/write variables manualy if needed. public IBlackboard blackboard {get;} //This is the time in seconds the action is running. public float elapsedTime {get;} //Called only the first time the action is executed and before anything else. //Return null if everything is OK. Return an info string if there is a problem. virtual protected string OnInit() //Called once when the action is executed. virtual protected void OnExecute() //Called every frame while the action is running. virtual protected void OnUpdate() //Called when the action stops for any reason. //Either because you called EndAction or cause the action was interrupted. virtual protected void OnStop() //Called when the action is paused comonly when it was still running while the behaviour graph gets paused. virtual protected void OnPause() //Send an event to the behaviour graph. Use this along with the CheckEvent condition. protected void SendEvent(string) //Similar to above, but sends a value along with the event. protected void SendEvent<T>(string, T) //You can use coroutines from within action task as normal. protected Coroutine StartCoroutine(IEnumerator) //You must call this to end the action. You can call this from wherever you want, //although typicaly is done in either OnExecute or OnUpdate public void EndAction(bool)
选中Behavior Designer的右上角Export导出
为行为树添加外部资源文件
在行为树中添加Action -> Behavior Tree Reference
设置其Externel Behaviour为1,并将资源文件拖拽进去即可
使用Has Received Event来监听事件,当它检测收到事件时才会返回Success
设置监听:定义一个字符串即可
抛出监听事件有以下两种方法:
behaviorTree.SendEvent("LogEvent"); // 其中behaviorTree是行为树的对象
测试时出现了问题,不知道为啥
如果其中有一个执行成功(返回Success)就会立即返回Success,其他节点返回Failure
当所有的子节点都执行失败时,Parallel Seclector才会返回Failure
Priority Selector会将子节点按照优先级进行排序,选择优先级高的(优先级数字大的)执行
想要设置节点的优先级,需要创建一个脚本重写Task的GetPriority方法,返回一个浮点类变量即可
public class PriorityLog : Action { public SharedFloat priority; public SharedString logString; public override TaskStatus OnUpdate() { Debug.Log(logString.Value); return TaskStatus.Success; } public override float GetPriority() { return priority.Value; } }
从子节点中随机选择一个执行,如果有字节点返回Success,则立即返回Suceess,否则继续随机选择执行下一个子节点
只有所有的子节点都返回Failure时,随机选择节点才会返回Failure
将子节点按照随机的顺序执行,当其中的某个子节点返回Failure时,会立刻返回Failure
所有的子节点并行执行,只要有一个子节点先返回了结果,就结束,并返回这个子节点执行的结果
从左到右执行子节点,
复合节点有中断的权利,选中某个复合节点,然后点击 Inspector 即可设置它的中断模式,Behavior Tree 的中断是通过运行是创建的 Behavior Manager 控制的
如图中的行为树,先执行 Wait 5s 的状态,如果在这 5s 内按下了 A 键,则执行 Self 中断,中断 Selector 下方的逻辑,Selector 左边返回 Success,继续执行Sequence逻辑
如图中的行为树,Selector 左侧没有返回结果,执行右边的 wait 10s 的操作,此时按下 A 键,立即中断了右方的 Wait 逻辑,输出 Get A Down
如图中的行为树,Get A Down 可以同时中断 Selector 下方和右侧的 Wait 操作。需要注意的是,由于按下 A 键可以同时中断右侧和下方的操作,一旦按下 A 键松开后,Selector 下方的 Wait 操作会重新执行。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。