继续昨天的工程,给Monster添加一个空物体命名为AI,在AI添加脚本BehaviorTree,然后就可以打开行为树编辑器进行编辑了

先写好自定义的节点脚本,下面是一个寻找漫游点的行为节点脚本

  1. using UnityEngine;
  2. using BehaviorDesigner.Runtime.Tasks;
  3. using BehaviorDesigner.Runtime;
  4.  
  5. [TaskCategory("MyActions")]
  6. [TaskDescription("计算出更新的路径")]
  7. public class ChooseWanderPosition : Action {
  8.  
  9. [BehaviorDesigner.Runtime.Tasks.Tooltip("最长距离")]
  10. public float wanderDistance;
  11.  
  12. [BehaviorDesigner.Runtime.Tasks.Tooltip("存放目标地的变量")]
  13. public SharedVector3 destination;
  14.  
  15. [BehaviorDesigner.Runtime.Tasks.Tooltip("自己")]
  16. public SharedGameObject monster;
  17.  
  18. public override TaskStatus OnUpdate(){
  19.  
  20. Vector3 direction = new Vector3(Random.Range(-1f, 1f), 0f, UnityEngine.Random.Range(-1f, 1f));
  21. direction *= wanderDistance;
  22.  
  23. destination.Value = monster.Value.transform.position + direction;
  24. return TaskStatus.Success;
  25. }
  26. }

[TaskCategory("MyActions")]

指定文件的目录为MyActions,我是在Actions下新建了一个MyActions的文件夹,所以指定目录为MyActions

其实也可以不指定,但是添加节点时就会显得杂乱

[TaskDescription("计算出更新的路径")]

这可以提示脚本的功能

public的属性将会显示在面板上

既可使用int float GameObject这种unity的类型,但缺点在于无法和其他脚本共享变量

Shared xxx类型是插件提供的,他在整个行为树中都能使用

使用Shared xxx类型前,必须在Variables先定义变量

之后点击该按钮切换后就能选择全局的变量了

最后设置如下,该节点就完成了

[BehaviorDesigner.Runtime.Tasks.Tooltip("xxx")]是面板上变量的解释,移动到面板变量上会显示

作为行为节点必须继承自Action并实现OnUpdate

OnUpdate()是节点执行时要运行的代码

接下来贴出其他要用到的行为节点

  1. using UnityEngine;
  2. using BehaviorDesigner.Runtime.Tasks;
  3. using BehaviorDesigner.Runtime;
  4.  
  5. [TaskCategory("MyActions")]
  6. [TaskDescription("转向玩家")]
  7. public class FaceToPlayer : Action {
  8.  
  9. [BehaviorDesigner.Runtime.Tasks.Tooltip("朝向的目标玩家")]
  10. public SharedGameObject player;
  11.  
  12. [BehaviorDesigner.Runtime.Tasks.Tooltip("自己")]
  13. public SharedGameObject monster;
  14.  
  15. public override TaskStatus OnUpdate(){
  16.  
  17. Vector3 targetDir = player.Value.transform.position - monster.Value.transform.position;
  18. monster.Value.transform.rotation = Quaternion.LookRotation(targetDir);
  19. return TaskStatus.Success;
  20. }
  21. }
  1. using UnityEngine;
  2. using BehaviorDesigner.Runtime.Tasks;
  3. using BehaviorDesigner.Runtime;
  4.  
  5. [TaskCategory("MyActions")]
  6. [TaskDescription("移动至漫游点")]
  7. public class MoveToWanderPoint : Action {
  8.  
  9. [BehaviorDesigner.Runtime.Tasks.Tooltip("移动的速度")]
  10. public float speed = ;
  11.  
  12. [BehaviorDesigner.Runtime.Tasks.Tooltip("移动的目标点")]
  13. public SharedVector3 position;
  14.  
  15. [BehaviorDesigner.Runtime.Tasks.Tooltip("自己")]
  16. public SharedGameObject monster;
  17.  
  18. public override TaskStatus OnUpdate(){
  19.  
  20. monster.Value.GetComponent<NavMeshAgent>().Move(position.Value);
  21. return TaskStatus.Success;
  22. }
  23. }
  1. using UnityEngine;
  2. using BehaviorDesigner.Runtime.Tasks;
  3. using BehaviorDesigner.Runtime;
  4.  
  5. [TaskCategory("MyActions")]
  6. [TaskDescription("移动至玩家")]
  7. public class MoveToWanderPoint : Action {
  8.  
  9. [BehaviorDesigner.Runtime.Tasks.Tooltip("移动的速度")]
  10. public float speed = ;
  11.  
  12. [BehaviorDesigner.Runtime.Tasks.Tooltip("移动的目标玩家")]
  13. public SharedGameObject player;
  14.  
  15. [BehaviorDesigner.Runtime.Tasks.Tooltip("自己")]
  16. public SharedGameObject monster;
  17.  
  18. public override TaskStatus OnUpdate(){
  19.  
  20. monster.Value.GetComponent<NavMeshAgent>().Move(player.Value.transform.position);
  21. return TaskStatus.Success;
  22. }
  23. }

因为移动调用了NavMeshAgent,所以我们先烘焙下场景并给Monster添加NavMeshAgent控件

  1. using UnityEngine;
  2. using BehaviorDesigner.Runtime.Tasks;
  3. using BehaviorDesigner.Runtime;
  4.  
  5. [TaskCategory("MyActions")]
  6. [TaskDescription("设置怪物的基本属性")]
  7. public class SetInfo : Action {
  8.  
  9. [BehaviorDesigner.Runtime.Tasks.Tooltip("玩家")]
  10. public SharedGameObject player;
  11.  
  12. [BehaviorDesigner.Runtime.Tasks.Tooltip("自己")]
  13. public SharedGameObject monster;
  14.  
  15. public override TaskStatus OnUpdate(){
  16.  
  17. monster.Value = transform.parent.gameObject;
  18. player.Value = GameObject.FindWithTag("Player");
  19. return TaskStatus.Success;
  20. }
  21. }

我们还需要自己写一个判断节点来判定玩家和怪物的距离,还需一个判断节点判断物体是否移动

  1. using UnityEngine;
  2. using BehaviorDesigner.Runtime.Tasks;
  3. using BehaviorDesigner.Runtime;
  4.  
  5. [TaskCategory("MyConditionals")]
  6. [TaskDescription("判断范围内是否有玩家")]
  7. public class PlayerInRange : Conditional {
  8.  
  9. [BehaviorDesigner.Runtime.Tasks.Tooltip("距离")]
  10. public float ranage;
  11.  
  12. [BehaviorDesigner.Runtime.Tasks.Tooltip("判断距离的玩家")]
  13. public SharedGameObject player;
  14.  
  15. [BehaviorDesigner.Runtime.Tasks.Tooltip("自己")]
  16. public SharedGameObject monster;
  17.  
  18. public override TaskStatus OnUpdate(){
  19.  
  20. if(Vector3.Distance(player.Value.transform.position, monster.Value.transform.position) > ranage){
  21.  
  22. return TaskStatus.Failure;
  23. }
  24. return TaskStatus.Success;
  25. }
  26. }
  1. using UnityEngine;
  2. using BehaviorDesigner.Runtime.Tasks;
  3. using BehaviorDesigner.Runtime;
  4.  
  5. [TaskCategory("MyConditionals")]
  6. [TaskDescription("判断对象是否移动")]
  7. public class NotMove : Conditional {
  8.  
  9. [BehaviorDesigner.Runtime.Tasks.Tooltip("上一次的位置")]
  10. public Vector3 lastPosition;
  11.  
  12. [BehaviorDesigner.Runtime.Tasks.Tooltip("判断的对象")]
  13. public SharedGameObject obj;
  14.  
  15. public override TaskStatus OnUpdate(){
  16.  
  17. if(obj.Value.transform.position == lastPosition){
  18.  
  19. return TaskStatus.Success;
  20. }
  21. lastPosition = obj.Value.transform.position;
  22. return TaskStatus.Failure;
  23. }
  24. }

依靠这些节点就可以拼出一颗行为树,一运行就可以看到一个简单的AI在运行,在攻击范围内它会攻击,在追击范围内它会追击敌人直到可以攻击,否则漫游

红圈位置可以改变节点颜色,更容易观察行为树结构

一些细节方面可以观看Demo

http://git.oschina.net/yejinqi/BehaviorTreeDemo

如果的事:http://y.qq.com/#type=song&mid=0040ZKt52jxJ6Y&play=1

unity行为树制作AI简单例子(2)的更多相关文章

  1. unity行为树制作AI简单例子(1)

    用行为树来制作AI是非常方便的,今天就给大家简单介绍一下行为树的强大之处. 所用插件 Behavior Designer v1.421 最开始 我使用过Rain插件,不过用过Behavior Desi ...

  2. 【Unity技巧】制作一个简单的NPC

    1. 写在前面 前几天看了cgcookie的一个教程,学习了下怎么根据已有人物模型制作一个仿版的NPC人物,感觉挺好玩的,整理一下放到博客里! 先看一下教程里面的最终效果. 是不是很像个幽灵~ 下面是 ...

  3. [转] 3个学习Socket编程的简单例子:TCP Server/Client, Select

    以前都是采用ACE的编写网络应用,最近由于工作需要,需要直接只用socket接口编写CS的代码,重新学习这方面的知识,给出自己所用到的3个简单例子,都是拷贝别人的程序.如果你能完全理解这3个例子,估计 ...

  4. iOS实用技能扩展-静态库的制作与简单使用

    前言:此文是关于静态库的概念描述,如何制作及简单调试使用,不同版本的说明与场景使用. 1.关于库的简介: 库可以分为2种类型 开源库 公开源代码,能看到具体实现 比如SDWebImage.AFNetw ...

  5. TensorFlow练习13: 制作一个简单的聊天机器人

    现在很多卖货公司都使用聊天机器人充当客服人员,许多科技巨头也纷纷推出各自的聊天助手,如苹果Siri.Google Now.Amazon Alexa.微软小冰等等.前不久有一个视频比较了Google N ...

  6. 让AI简单且强大:深度学习引擎OneFlow技术实践

    本文内容节选自由msup主办的第七届TOP100summit,北京一流科技有限公司首席科学家袁进辉(老师木)分享的<让AI简单且强大:深度学习引擎OneFlow背后的技术实践>实录. 北京 ...

  7. JFrame、JPanel 、Layout开发的简单例子

    写了Java这么久,居然发现想手写一个带网格袋布局的JFrame,还不记得怎么写,写了这么多代码真不敢说记得所有细节. 幸好,只要记清楚概念就能快速开发.首先,明确一下3种容器类的差别和用途: No. ...

  8. Unity 3D 简易制作摄像机围绕物体随鼠标旋转效果

    Unity 3D 简易制作摄像机围绕物体随鼠标旋转效果 梗概: 一. 摄像机围绕目标物体旋转, 即摄像机离目标物体有一定的距离且旋转轴心为该物体的位置. 二. 当目标物体被障碍物挡住后, 需要将摄像机 ...

  9. PureMVC和Unity3D的UGUI制作一个简单的员工管理系统实例

    前言: 1.关于PureMVC: MVC框架在很多项目当中拥有广泛的应用,很多时候做项目前人开坑开了一半就消失了,后人为了填补各种的坑就遭殃的不得了.嘛,程序猿大家都不喜欢像文案策划一样组织文字写东西 ...

随机推荐

  1. CSS之照片集效果

    代码: <!DOCTYPE html><html><head> <title>照片影集</title> <meta charset=& ...

  2. Java 社区论坛 - Sym 1.6.0 发布

    简介 Sym 是一个用 Java 写的现代化的社区论坛,欢迎来体验!(如果你需要搭建一个企业内网论坛,请使用 SymX) 非常详细的 Sym 功能点脑图 Sym 的诞生是有如下几点原因: (正版) 好 ...

  3. 项目组J2ee程序员的标志,你中招没 转载+评论

    原文在此 校园级别的程序员的标志: 代码中最多的是嵌套if(null == xxx),还要告诉你,null必须写在前面,我靠. 防止把==写成=,c语言时代常犯的错误.由于null不能做左值,在写=的 ...

  4. Java中静态内部类的理解

    class A { public void func() { A a=new A(); C c=a.new C(); } public static void main(String[] args) ...

  5. JAVA vo pojo javabean dto区别

    JavaBean 是一种JAVA语言写成的可重用组件.为写成JavaBean,类必须是具体的和公共的,并且具有无参数的构造器.JavaBean 通过提供符合一致性设计模式的公共方法将内部域暴露成员属性 ...

  6. UGUI与DOtween的坑

    在使用ugui和dotween做动画时,如使用transform.DoMoveX,.DoLocalMoveX,.DoMove,.DoLocalMove等方法时,动画效果有可能是错误的,什么时候错误呢? ...

  7. ios 大图 真机不显示的问题

    png的图片只是命名为png,格式不是png的. 打开terminal终端,cd图片目录,输入命令sips -s format png *.* --out pngs,再把图片覆盖即可

  8. AJAX实现异步登录

    //代码较为简单,只是测试所用 1.html登录页面代码 <table> <tr> <td>用户名:</td> <td><input ...

  9. Android锁屏或灭屏状态下,快速按两次音量下键实现抓拍功能(1.2Framework层使用startService形式实现)

        如前一篇博文所分析,我们可以使用广播的形式在快速按下两次音量下键的时候发出广播,以方便客户端进行捕捉.既然有两种方式可以实现该Issue那么哪种方式是首选呢?     我个人推荐使用启动服务的 ...

  10. HDU 5441 离线处理 + 并查集

    题意:给n个节点m条带权值边的无向图.然后q个问题,每次询问点对的数目,点对需要满足的条件是:1)连通:2)其路径的最大权值不能超过询问值. 分析:如果没次询问一次,dfs一次,很可能超时,因此可以用 ...