行为树
作者:追风剑情 发布于: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
日历
最新文章
随机文章
热门文章
分类
存档
- 2024年11月(3)
- 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
交流QQ群
-
Flash游戏设计: 86184192
Unity游戏设计: 171855449
游戏设计订阅号