行为树
作者:追风剑情 发布于:2016-2-17 15:46 分类:Unity3d
=====================行为树(Behavior Tree)框架代码======================
父节点:
using UnityEngine;
using System.Collections.Generic;
/// <summary>
/// 父节点
/// </summary>
public class BehaviorTreeNode : MonoBehaviour, IBehaviourTreeNode
{
public int weight; //加权
[HideInInspector]
protected RunStatus runStatus = RunStatus.Success;
public virtual RunStatus Run()
{
return runStatus;
}
public void Success()
{
runStatus = RunStatus.Success;
}
public void Failure()
{
runStatus = RunStatus.Failure;
}
public void Running()
{
runStatus = RunStatus.Running;
}
public RunStatus GetRunStatus()
{
return runStatus;
}
protected static void RandSortList(List<BehaviorTreeNode> list)
{
int size = list.Count;
int seed = 10000;
System.Random rand = new System.Random();
for (int i = 0; i < size; i++)
{
int randIndex = (int)(rand.Next(seed) % (size - i)) + i;
BehaviorTreeNode j = list[i];
list[i] = list[randIndex];
list[randIndex] = j;
}
}
}
根节点:
using UnityEngine;
using System.Collections.Generic;
/// <summary>
/// 根结点
/// </summary>
public class BehaviorTreeRoot : MonoBehaviour {
public List<BehaviorTreeNode> childList;
// 每隔多少帧驱动一次行为树
public int updatePerFrame = 0;
private int frame = 0;
void Update () {
if (updatePerFrame <= 0)
{
Run();
}
else
{
frame = frame++ % updatePerFrame;
if(frame == 0)
Run();
}
}
void Run()
{
for (int i = 0; i < childList.Count; i++)
{
childList[i].Run();
}
}
}
组合节点:
(1) 顺序节点
using UnityEngine;
using System.Collections.Generic;
/// <summary>
/// 决策节点: 顺序结点 (逻辑与)
/// </summary>
public class SequenceNode : BehaviorTreeNode
{
public enum SequenceType
{
NormalSequence, //按标准顺序迭代子节点
RandomSequence //按随机顺序迭代子节点
}
public SequenceType sequenceType;
public List<BehaviorTreeNode> childList;
private int currentIndex = 0;
public override RunStatus Run()
{
if (null == childList)
return RunStatus.Success;
if (sequenceType == SequenceType.RandomSequence)
{
if (runStatus != RunStatus.Running)
RandSortList(childList);
}
IterateChilds();
return runStatus;
}
private void IterateChilds()
{
for (int i = currentIndex; i < childList.Count; i++)
{
runStatus = childList[i].Run();
if (runStatus == RunStatus.Success)
{
currentIndex = 0;
}
else if (runStatus == RunStatus.Failure)
{
currentIndex = 0;
break;
}
else if (runStatus == RunStatus.Running)
{
currentIndex = i;
break;
}
}
}
}
(2) 选择节点
using UnityEngine;
using System.Collections.Generic;
/// <summary>
/// 决策节点: 选择结点 (逻辑或)
/// </summary>
public class SelectorNode : BehaviorTreeNode
{
public enum SelectorType
{
NormalSelector, //标准选择器
WeightRandomSelector, //加权随机选择器 (第一个子节点随机选择)
WeightRandomSequence //序列随机选择器 (每次按不同的顺序执行子节点)
}
public SelectorType selectorType;
public List<BehaviorTreeNode> childList;
private int weightSum = -1;
private int currentIndex = 0;
public override RunStatus Run()
{
if (null == childList)
return RunStatus.Success;
switch (selectorType)
{
case SelectorType.NormalSelector:
NormalSelector();
break;
case SelectorType.WeightRandomSelector:
WeightRandomSelector();
break;
case SelectorType.WeightRandomSequence:
WeightRandomSequence();
break;
}
return runStatus;
}
private void WeightRandomSelector()
{
if (CurrentNodeRunning())
return;
if (weightSum == -1)
{
for (int i = 0; i < childList.Count; i++)
weightSum += childList[i].weight;
}
// 按加权随机执行第一个子节点
System.Random rand = new System.Random();
int randWeight = rand.Next(weightSum);
int ignoreIndex = -1;
for (int i = 0; i < childList.Count; i++)
{
if (randWeight <= childList[i].weight)
{
if (runStatus == RunStatus.Success)
{
currentIndex = 0;
return;
}
else if (runStatus == RunStatus.Failure)
{
currentIndex = 0;
ignoreIndex = i;
break;
}
else if (runStatus == RunStatus.Running)
{
currentIndex = i;
return;
}
}
}
// 按顺序执行其他子节点
IterateChilds(ignoreIndex);
}
private void WeightRandomSequence()
{
if (runStatus != RunStatus.Running)
RandSortList(childList);
IterateChilds();
}
private void NormalSelector()
{
IterateChilds();
}
private bool CurrentNodeRunning()
{
// 如果处于Running状态,则继续调用当前节点。
if (runStatus == RunStatus.Running)
{
runStatus = childList[currentIndex].Run();
if (runStatus == RunStatus.Running)
return true;
}
return false;
}
private void IterateChilds(int ignoreIndex = -1)
{
for (int i = currentIndex; i < childList.Count; i++)
{
if (i == ignoreIndex)
continue;
runStatus = childList[i].Run();
if (runStatus == RunStatus.Success)
{
currentIndex = 0;
break;
}
else if (runStatus == RunStatus.Failure)
{
currentIndex = 0;
}
else if (runStatus == RunStatus.Running)
{
currentIndex = i;
break;
}
}
}
}
(3) 并行节点
using UnityEngine;
using System.Collections.Generic;
/// <summary>
/// 决策节点: 并行结点
/// 返回值由返回策略决定
/// </summary>
public class ParallelNode : BehaviorTreeNode
{
// 返回策略
public enum Strategy
{
Sequence, //有一个子节点返回False则返回False,否则返回True。
Selector, //有一个子节点返回True则返回True,否则返回False。
FailureAll, //所有子节点False才返回False,否则返回True。
SuccessAll, //所有子节点True才返回True,否则返回False。
Hybird //指定数量的子节点返回True或False后,才决定结果。
}
public Strategy strategy;
//有hybirdCount个子节点返回hybird,则返回True,否则返回False
public RunStatus hybird = RunStatus.Success;
public int hybirdCount = 1;
public List<BehaviorTreeNode> childList;
public override RunStatus Run()
{
switch (strategy)
{
case Strategy.Sequence: runStatus = Sequence(); break;
case Strategy.Selector: runStatus = Selector(); break;
case Strategy.FailureAll: runStatus = FailureAll(); break;
case Strategy.SuccessAll: runStatus = SuccessAll(); break;
case Strategy.Hybird: runStatus = Hybird(); break;
}
return runStatus;
}
private RunStatus Sequence()
{
RunStatus status = RunStatus.Success;
for (int i = 0; i < childList.Count; i++)
{
if (childList[i].Run() == RunStatus.Failure)
status = RunStatus.Failure;
}
return status;
}
private RunStatus Selector()
{
RunStatus status = RunStatus.Success;
for (int i = 0; i < childList.Count; i++)
{
if (childList[i].Run() == RunStatus.Success)
status = RunStatus.Success;
}
return status;
}
private RunStatus FailureAll()
{
RunStatus status = RunStatus.Success;
for (int i = 0; i < childList.Count; i++)
{
if (childList[i].Run() == RunStatus.Success)
status = RunStatus.Failure;
}
return status;
}
private RunStatus SuccessAll()
{
RunStatus status = RunStatus.Success;
for (int i = 0; i < childList.Count; i++)
{
if (childList[i].Run() == RunStatus.Failure)
status = RunStatus.Failure;
}
return status;
}
private RunStatus Hybird()
{
int num = 0;
for (int i = 0; i < childList.Count; i++)
{
if (childList[i].Run() == hybird)
num++;
}
return num >= hybirdCount ? RunStatus.Success : RunStatus.Failure;
}
}
行为节点:
using UnityEngine;
/// <summary>
/// 行为结点 (叶节点)
/// </summary>
public class ActionNode : BehaviorTreeNode
{
public GameObject eventReceiver;
public string functionName = "OnAction";
public override RunStatus Run()
{
eventReceiver.SendMessage(functionName, this, SendMessageOptions.DontRequireReceiver);
return runStatus;
}
}
条件节点:
(1) 一般条件节点
using UnityEngine;
using System.Collections;
/// <summary>
/// 行为结点 (叶节点)
/// 返回判断结果
/// </summary>
public class ConditionNode : BehaviorTreeNode
{
public GameObject eventReceiver;
public string functionName = "OnCondition";
public override RunStatus Run()
{
eventReceiver.SendMessage(functionName, this, SendMessageOptions.DontRequireReceiver);
return runStatus;
}
}
(2) 前置条件节点
using UnityEngine;
using System.Collections;
/// <summary>
/// 前置条件 (只有当前置条件返回Success时,下面的行为结点才会被调用)
/// </summary>
public class WithPrecondition : BehaviorTreeNode
{
public GameObject eventReceiver;
public string functionName = "OnWithPrecondition";
public BehaviorTreeNode actionNode;
public override RunStatus Run()
{
runStatus = RunStatus.Failure;
eventReceiver.SendMessage(functionName, this, SendMessageOptions.DontRequireReceiver);
if (runStatus == RunStatus.Success)
runStatus = actionNode.Run();
return runStatus;
}
}
装饰结点: 这类节点有很多,可根据项目需要自行增加。
(1) 等待节点
using UnityEngine;
using System.Collections;
/// <summary>
/// 等待结点
/// </summary>
public class WaitNode : BehaviorTreeNode
{
public float waitSecond;//等待时间(单位: 秒)
public BehaviorTreeNode node;
private float lastTime;
public override RunStatus Run()
{
if (Time.time - lastTime < waitSecond)
return RunStatus.Failure;
lastTime = Time.time;
runStatus = node.Run();
return runStatus;
}
}
(2) 逻辑非节点
using UnityEngine;
using System.Collections;
/// <summary>
/// 装饰节点
/// 逻辑非
/// </summary>
public class DecoratorNode : BehaviorTreeNode
{
public override RunStatus Run()
{
//TODO:: 待实现
return runStatus;
}
}
(3) 计数节点
using UnityEngine;
using System.Collections;
/// <summary>
/// 装饰节点
/// 计数
/// </summary>
public class DecoratorCounter : BehaviorTreeNode
{
public override RunStatus Run()
{
//TODO:: 待实现
return runStatus;
}
}
(4) 直到失败节点
using UnityEngine;
using System.Collections;
/// <summary>
/// 装饰节点
/// 直到子结点返回失败才返回True
/// </summary>
public class DecoratorFailUtil : BehaviorTreeNode
{
public override RunStatus Run()
{
//TODO:: 待实现
return runStatus;
}
}
NPC示例脚本:
using UnityEngine;
using System.Collections;
public class NPCAction : MonoBehaviour {
#region 巡逻
// 前置条件
void PreconditionPatrol(IBehaviourTreeNode node)
{
if (Input.GetKeyDown(KeyCode.P))
node.Success();
else
node.Failure();
}
// 行为
void Patrol(IBehaviourTreeNode node)
{
node.Running();
Debug.Log("Patrol: RunStatus=" + node.GetRunStatus());
}
#endregion
#region 逃跑
// 前置条件
void PreconditionEscape(IBehaviourTreeNode node)
{
if (Input.GetKeyDown(KeyCode.E))
node.Success();
else
node.Failure();
}
// 行为
void Escape(IBehaviourTreeNode node)
{
node.Running();
Debug.Log("Escape: RunStatus=" + node.GetRunStatus());
}
#endregion
#region 攻击
// 前置条件
void PreconditionAttack(IBehaviourTreeNode node)
{
if (Input.GetKeyDown(KeyCode.A))
node.Success();
else
node.Failure();
}
// 行为
void Attack(IBehaviourTreeNode node)
{
node.Running();
Debug.Log("Attack: RunStatus=" + node.GetRunStatus());
}
#endregion
#region 回血
void AddHP1(IBehaviourTreeNode node)
{
node.Success();
Debug.Log("AddHP1");
}
void AddHP2(IBehaviourTreeNode node)
{
node.Success();
Debug.Log("AddHP2");
}
void AddHP3(IBehaviourTreeNode node)
{
node.Success();
Debug.Log("AddHP3");
}
#endregion
#region 条件检查
// 是否满足死忘条件
void ConditionDie(IBehaviourTreeNode node)
{
if (Input.GetKeyDown(KeyCode.D))
{
node.Success();
Debug.Log("ConditionDie: RunStatus=" + node.GetRunStatus());
}
node.Failure();
}
// 是否满足复活条件
void ConditionRelive(IBehaviourTreeNode node)
{
if (Input.GetKeyDown(KeyCode.R))
{
node.Success();
Debug.Log("ConditionRelive: RunStatus=" + node.GetRunStatus());
}
node.Failure();
}
#endregion
}
附上Demo源文件
360网盘下载
https://yunpan.cn/cxqTN8Ns4syam 访问密码 0079
标签: Unity3d
日历
最新文章
随机文章
热门文章
分类
存档
- 2025年11月(1)
- 2025年9月(3)
- 2025年7月(4)
- 2025年6月(5)
- 2025年5月(1)
- 2025年4月(5)
- 2025年3月(4)
- 2025年2月(3)
- 2025年1月(1)
- 2024年12月(5)
- 2024年11月(5)
- 2024年10月(5)
- 2024年9月(3)
- 2024年8月(3)
- 2024年7月(11)
- 2024年6月(3)
- 2024年5月(9)
- 2024年4月(10)
- 2024年3月(11)
- 2024年2月(24)
- 2024年1月(12)
- 2023年12月(3)
- 2023年11月(9)
- 2023年10月(7)
- 2023年9月(2)
- 2023年8月(7)
- 2023年7月(9)
- 2023年6月(6)
- 2023年5月(7)
- 2023年4月(11)
- 2023年3月(6)
- 2023年2月(11)
- 2023年1月(8)
- 2022年12月(2)
- 2022年11月(4)
- 2022年10月(10)
- 2022年9月(2)
- 2022年8月(13)
- 2022年7月(7)
- 2022年6月(11)
- 2022年5月(18)
- 2022年4月(29)
- 2022年3月(5)
- 2022年2月(6)
- 2022年1月(8)
- 2021年12月(5)
- 2021年11月(3)
- 2021年10月(4)
- 2021年9月(9)
- 2021年8月(14)
- 2021年7月(8)
- 2021年6月(5)
- 2021年5月(2)
- 2021年4月(3)
- 2021年3月(7)
- 2021年2月(2)
- 2021年1月(8)
- 2020年12月(7)
- 2020年11月(2)
- 2020年10月(6)
- 2020年9月(9)
- 2020年8月(10)
- 2020年7月(9)
- 2020年6月(18)
- 2020年5月(4)
- 2020年4月(25)
- 2020年3月(38)
- 2020年1月(21)
- 2019年12月(13)
- 2019年11月(29)
- 2019年10月(44)
- 2019年9月(17)
- 2019年8月(18)
- 2019年7月(25)
- 2019年6月(25)
- 2019年5月(17)
- 2019年4月(10)
- 2019年3月(36)
- 2019年2月(35)
- 2019年1月(28)
- 2018年12月(30)
- 2018年11月(22)
- 2018年10月(4)
- 2018年9月(7)
- 2018年8月(13)
- 2018年7月(13)
- 2018年6月(6)
- 2018年5月(5)
- 2018年4月(13)
- 2018年3月(5)
- 2018年2月(3)
- 2018年1月(8)
- 2017年12月(35)
- 2017年11月(17)
- 2017年10月(16)
- 2017年9月(17)
- 2017年8月(20)
- 2017年7月(34)
- 2017年6月(17)
- 2017年5月(15)
- 2017年4月(32)
- 2017年3月(8)
- 2017年2月(2)
- 2017年1月(5)
- 2016年12月(14)
- 2016年11月(26)
- 2016年10月(12)
- 2016年9月(25)
- 2016年8月(32)
- 2016年7月(14)
- 2016年6月(21)
- 2016年5月(17)
- 2016年4月(13)
- 2016年3月(8)
- 2016年2月(8)
- 2016年1月(18)
- 2015年12月(13)
- 2015年11月(15)
- 2015年10月(12)
- 2015年9月(18)
- 2015年8月(21)
- 2015年7月(35)
- 2015年6月(13)
- 2015年5月(9)
- 2015年4月(4)
- 2015年3月(5)
- 2015年2月(4)
- 2015年1月(13)
- 2014年12月(7)
- 2014年11月(5)
- 2014年10月(4)
- 2014年9月(8)
- 2014年8月(16)
- 2014年7月(26)
- 2014年6月(22)
- 2014年5月(28)
- 2014年4月(15)
友情链接
- Unity官网
- Unity圣典
- Unity在线手册
- Unity中文手册(圣典)
- Unity官方中文论坛
- Unity游戏蛮牛用户文档
- Unity下载存档
- Unity引擎源码下载
- Unity服务
- Unity Ads
- wiki.unity3d
- Visual Studio Code官网
- SenseAR开发文档
- MSDN
- C# 参考
- C# 编程指南
- .NET Framework类库
- .NET 文档
- .NET 开发
- WPF官方文档
- uLua
- xLua
- SharpZipLib
- Protobuf-net
- Protobuf.js
- OpenSSL
- OPEN CASCADE
- JSON
- MessagePack
- C在线工具
- 游戏蛮牛
- GreenVPN
- 聚合数据
- 热云
- 融云
- 腾讯云
- 腾讯开放平台
- 腾讯游戏服务
- 腾讯游戏开发者平台
- 腾讯课堂
- 微信开放平台
- 腾讯实时音视频
- 腾讯即时通信IM
- 微信公众平台技术文档
- 白鹭引擎官网
- 白鹭引擎开放平台
- 白鹭引擎开发文档
- FairyGUI编辑器
- PureMVC-TypeScript
- 讯飞开放平台
- 亲加通讯云
- Cygwin
- Mono开发者联盟
- Scut游戏服务器引擎
- KBEngine游戏服务器引擎
- Photon游戏服务器引擎
- 码云
- SharpSvn
- 腾讯bugly
- 4399原创平台
- 开源中国
- Firebase
- Firebase-Admob-Unity
- google-services-unity
- Firebase SDK for Unity
- Google-Firebase-SDK
- AppsFlyer SDK
- android-repository
- CQASO
- Facebook开发者平台
- gradle下载
- GradleBuildTool下载
- Android Developers
- Google中国开发者
- AndroidDevTools
- Android社区
- Android开发工具
- Google Play Games Services
- Google商店
- Google APIs for Android
- 金钱豹VPN
- TouchSense SDK
- MakeHuman
- Online RSA Key Converter
- Windows UWP应用
- Visual Studio For Unity
- Open CASCADE Technology
- 慕课网
- 阿里云服务器ECS
- 在线免费文字转语音系统
- AI Studio
- 网云穿
- 百度网盘开放平台
- 迅捷画图
- 菜鸟工具
- [CSDN] 程序员研修院
- 华为人脸识别
- 百度AR导航导览SDK
- 海康威视官网
- 海康开放平台
- 海康SDK下载
- git download
- Open CASCADE
- CascadeStudio
交流QQ群
-
Flash游戏设计: 86184192
Unity游戏设计: 171855449
游戏设计订阅号







