untiy 3d结合Brainiac Designer做游戏Ai(二)
来源:互联网 发布:linux断点续传命令py 编辑:程序博客网 时间:2024/05/20 05:09
上一篇已经介绍了怎么用Brainiac Designer做行为树,这一篇将会介绍怎么把生成的ai结合到untiy里
首先导出的ai代码拷到untiy里,然后新建一个行为树框加BehaviorTree.cs,定义各种节点,代码比较简单,根本的注释也有了,就不详细讲了,代码如下
using UnityEngine;using System.Collections;using System.Collections.Generic;namespace GameAi{ public interface IBehaviorTreeNode { bool Process(AiController theOwner); } /// <summary> /// 行为框架,具体实现要继承DecoratorNode, ConditionNode, ActionNode, ImpulseNode /// </summary> public class BehaviorTreeRoot : IBehaviorTreeNode { public IBehaviorTreeNode root = null; public BehaviorTreeRoot() { } public bool Process(AiController theOwner) { return root.Process(theOwner); } public void AddChild(IBehaviorTreeNode root) { this.root = root; } } /// <summary> /// 复合节点,不能为叶子节点 /// </summary> public class CompositeNode : IBehaviorTreeNode { protected List<IBehaviorTreeNode> children = new List<IBehaviorTreeNode>(); /// <summary> /// 由子树实现 /// </summary> /// <param name="theOwner"></param> /// <returns></returns> public virtual bool Process(AiController theOwner) { return true; } public void AddChild(IBehaviorTreeNode _node) { children.Add(_node); } public void DelChild(IBehaviorTreeNode _node) { children.Remove(_node); } public void ClearChildren() { children.Clear(); } } /// <summary> /// 修饰类 /// </summary> public class DecoratorNode : IBehaviorTreeNode { protected IBehaviorTreeNode child = null; /// <summary> /// 由子类实现 /// </summary> /// <param name="theOwner"></param> /// <returns></returns> public virtual bool Process(AiController theOwner) { return child.Process(theOwner); } public void Proxy(IBehaviorTreeNode _child) { child = _child; } } /// <summary> /// 脉冲类 /// </summary> public class ImpulseNode : IBehaviorTreeNode { protected IBehaviorTreeNode child = null; /// <summary> /// 由子类实现 /// </summary> /// <param name="theOwner"></param> /// <returns></returns> public virtual bool Process(AiController theOwner) { return child.Process(theOwner); } public void Proxy(IBehaviorTreeNode _child) { child = _child; } } /// <summary> /// 叶子节点,条件判断类 /// </summary> public class ConditionNode : IBehaviorTreeNode { /// <summary> /// 由子类实现 /// </summary> /// <param name="theOwner"></param> /// <returns></returns> public virtual bool Process(AiController theOwner) { return false; } } /// <summary> /// 叶子节点,具体行为实现类 /// </summary> public class ActionNode : IBehaviorTreeNode { /// <summary> /// 由子类实现 /// </summary> /// <param name="theOwner"></param> /// <returns></returns> public virtual bool Process(AiController theOwner) { return false; } } /// <summary> /// 选择节点 /// 遇到一个child执行后返回true,停止迭代 /// 本node向自己的父节点返回true /// 如果所有的child都返回false,本node向自己父节点返回false /// </summary> public class SelectorLinear : CompositeNode { public override bool Process(AiController theOwner) { foreach (IBehaviorTreeNode _node in children) { if (_node.Process(theOwner)) { return true; } } return false; } } /// <summary> /// 遇到一个child执行后返回false,停止迭代 /// 本node向自己的父节点返回false /// 如果所有的child都返回true,本node向自己父节点返回true /// </summary> public class SequenceLinear : CompositeNode { public override bool Process(AiController theOwner) { foreach (IBehaviorTreeNode _node in children) { if (!_node.Process(theOwner)) { return false; } } return true; } } /// <summary> /// 修饰类取反 /// </summary> public class DecoratorNot : DecoratorNode { public override bool Process(AiController theOwner) { return !base.Process(theOwner); } }}打开Brainiac Designer导出的代码可以看到,里面只是添加一些节点,但是节点要干什么,里面没有实现了,所以我们要在untiy里实现各个节点的行为
首先是Attack.cs
using UnityEngine;using System.Collections;namespace GameAi{ public class Attack : ActionNode { public Attack() { } public override bool Process(AiController theOwner) { theOwner.Attack(); return true; } }}
CanNotFindPlayer.cs
using UnityEngine;using System.Collections;namespace GameAi{ public class CanNotFindPlayer : ConditionNode { public CanNotFindPlayer() { } public override bool Process(AiController theOwner) { return theOwner.CanNotFindPlayer(); } }}
Chase.cs
using UnityEngine;using System.Collections;namespace GameAi{ public class Chase : ActionNode { public Chase() { } public override bool Process(AiController theOwner) { theOwner.Chase(); return true; } }}
FindPlayer.cs
using UnityEngine;using System.Collections;namespace GameAi{ public class FindPlayer : ConditionNode { public FindPlayer() { } public override bool Process(AiController theOwner) { return theOwner.FindPlayer(); } }}
IsPlayerInAttackRange.cs
using UnityEngine;using System.Collections;namespace GameAi{ public class IsPlayerInAttackRange : ConditionNode { public IsPlayerInAttackRange() { } public override bool Process(AiController theOwner) { return theOwner.IsPlayerInAttackRange(); } }}
Patrol.cs
using UnityEngine;using System.Collections;namespace GameAi{ public class Patrol : ActionNode { public int PatrolRange = 0; public Patrol() { } public override bool Process(AiController theOwner) { theOwner.Patrol(PatrolRange); return true; } }}
行为树的各个节点已经定义好, 我们还需要定义一个Ai控制器AiController,Ai的的具体逻辑都是写在这里,根据名称用反射去决定调用哪个ai行为树,行为树的节点的具体行为只是调用这里的方法
AiController.cs
using UnityEngine;using System.Collections;using GameAi.Manager;namespace GameAi{ public class AiController : MonoBehaviour { private BehaviorTreeRoot _aiBehaviorTree; private string _aiBTreeName = "ai_1"; private float _aiIntervalTick = 0f; private float _aiIntervalTime = 0.5f; private void RegisterAiBehaviorTree() { _aiBehaviorTree = BTreeManager.instance.GetBTree(_aiBTreeName); } // Use this for initialization void Start() { RegisterAiBehaviorTree(); } void FixedUpdate() { //ai执行时间间隔处理 if (_aiIntervalTick == -1f) { _aiBehaviorTree.Process(this); _aiIntervalTick = 0f; } else { _aiIntervalTick += Time.deltaTime; if (_aiIntervalTick >= _aiIntervalTime) { _aiBehaviorTree.Process(this); _aiIntervalTick = 0f; } } } public void Chase() { Debug.Log("==========Chase======= "); } public void Attack() { Debug.Log("=========Attack========"); } public void Patrol(int patrolRange) { Debug.Log("=========Patrol========" + patrolRange); } public bool FindPlayer() { Debug.Log("=========FindPlayer========"); if (Random.Range(0, 10) > 5) { return false; } return true; } public bool IsPlayerInAttackRange() { Debug.Log("=========IsPlayerInAttackRange========"); if (Random.Range(0, 10) > 5) { return false; } return true; } public bool CanNotFindPlayer() { Debug.Log("=========CanNotFindPlayer========"); if (Random.Range(0, 10) > 5) { return false; } return true; } }}
整个Ai框架到这里已经定义好了,最后把AiController拖到一个GameObject上,执行就可以看到运行结果了
最后附上整个工程文件:源码
简单的Ai也可以用FSM实现,这里不细讲附上一个用FSM实现的Ai工程:源码
0 0
- untiy 3d结合Brainiac Designer做游戏Ai(二)
- untiy 3d结合Brainiac Designer做游戏Ai(一)
- Brainiac Designer
- untiy 3D 创建角色
- Untiy 访问组件(二)
- Android 3D游戏开发(二)
- 漫谈3D游戏引擎(二)
- 游戏人工智能(AI)开发(二)
- 游戏人工智能(AI)开发(二)
- untiy 3d ShaderLab第 1 章Shader(着色器)的概念和在 3D 游戏中的作用
- untiy 3d ShaderLab_第9章_2_球体阴影(二) 阴影的淡入/淡出
- 游戏编程入门(6):开发 Brainiac(记忆对对碰) 游戏
- C++游戏[Brainiac]游戏引擎使用体验
- Behavior Designer教程(AI)
- untiy 2d游戏平面直角坐标系的旋转应用
- untiy 3d ShaderLab读后感_0_目录
- 3D游戏编程(二)
- untiy游戏接入Play800(爱玩堂)
- 2015年NEUACM省赛练习赛第二场 B题补充题解
- MySQL索引类型一览 让MySQL高效运行起来
- 2015.5.16 loi test 考后总结
- POSIX
- 3-21
- untiy 3d结合Brainiac Designer做游戏Ai(二)
- java基础之程序流程控制和数组
- Java web基础总结八之—— jsp基础
- 第一次用Enumeration的一点感想
- JAVA学习 第九天(1)练习题
- 毕设(排课系统)笔记1---用户注册(一)
- Sicily 14516. Doorman
- 新浪微博栏目随便看看
- 手机屏幕测试