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

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

using UnityEngine;
using BehaviorDesigner.Runtime.Tasks;
using BehaviorDesigner.Runtime; [TaskCategory("MyActions")]
[TaskDescription("计算出更新的路径")]
public class ChooseWanderPosition : Action { [BehaviorDesigner.Runtime.Tasks.Tooltip("最长距离")]
public float wanderDistance; [BehaviorDesigner.Runtime.Tasks.Tooltip("存放目标地的变量")]
public SharedVector3 destination; [BehaviorDesigner.Runtime.Tasks.Tooltip("自己")]
public SharedGameObject monster; public override TaskStatus OnUpdate(){ Vector3 direction = new Vector3(Random.Range(-1f, 1f), 0f, UnityEngine.Random.Range(-1f, 1f));
direction *= wanderDistance; destination.Value = monster.Value.transform.position + direction;
return TaskStatus.Success;
}
}

[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()是节点执行时要运行的代码

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

using UnityEngine;
using BehaviorDesigner.Runtime.Tasks;
using BehaviorDesigner.Runtime; [TaskCategory("MyActions")]
[TaskDescription("转向玩家")]
public class FaceToPlayer : Action { [BehaviorDesigner.Runtime.Tasks.Tooltip("朝向的目标玩家")]
public SharedGameObject player; [BehaviorDesigner.Runtime.Tasks.Tooltip("自己")]
public SharedGameObject monster; public override TaskStatus OnUpdate(){ Vector3 targetDir = player.Value.transform.position - monster.Value.transform.position;
monster.Value.transform.rotation = Quaternion.LookRotation(targetDir);
return TaskStatus.Success;
}
}
using UnityEngine;
using BehaviorDesigner.Runtime.Tasks;
using BehaviorDesigner.Runtime; [TaskCategory("MyActions")]
[TaskDescription("移动至漫游点")]
public class MoveToWanderPoint : Action { [BehaviorDesigner.Runtime.Tasks.Tooltip("移动的速度")]
public float speed = ; [BehaviorDesigner.Runtime.Tasks.Tooltip("移动的目标点")]
public SharedVector3 position; [BehaviorDesigner.Runtime.Tasks.Tooltip("自己")]
public SharedGameObject monster; public override TaskStatus OnUpdate(){ monster.Value.GetComponent<NavMeshAgent>().Move(position.Value);
return TaskStatus.Success;
}
}
using UnityEngine;
using BehaviorDesigner.Runtime.Tasks;
using BehaviorDesigner.Runtime; [TaskCategory("MyActions")]
[TaskDescription("移动至玩家")]
public class MoveToWanderPoint : Action { [BehaviorDesigner.Runtime.Tasks.Tooltip("移动的速度")]
public float speed = ; [BehaviorDesigner.Runtime.Tasks.Tooltip("移动的目标玩家")]
public SharedGameObject player; [BehaviorDesigner.Runtime.Tasks.Tooltip("自己")]
public SharedGameObject monster; public override TaskStatus OnUpdate(){ monster.Value.GetComponent<NavMeshAgent>().Move(player.Value.transform.position);
return TaskStatus.Success;
}
}

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

using UnityEngine;
using BehaviorDesigner.Runtime.Tasks;
using BehaviorDesigner.Runtime; [TaskCategory("MyActions")]
[TaskDescription("设置怪物的基本属性")]
public class SetInfo : Action { [BehaviorDesigner.Runtime.Tasks.Tooltip("玩家")]
public SharedGameObject player; [BehaviorDesigner.Runtime.Tasks.Tooltip("自己")]
public SharedGameObject monster; public override TaskStatus OnUpdate(){ monster.Value = transform.parent.gameObject;
player.Value = GameObject.FindWithTag("Player");
return TaskStatus.Success;
}
}

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

using UnityEngine;
using BehaviorDesigner.Runtime.Tasks;
using BehaviorDesigner.Runtime; [TaskCategory("MyConditionals")]
[TaskDescription("判断范围内是否有玩家")]
public class PlayerInRange : Conditional { [BehaviorDesigner.Runtime.Tasks.Tooltip("距离")]
public float ranage; [BehaviorDesigner.Runtime.Tasks.Tooltip("判断距离的玩家")]
public SharedGameObject player; [BehaviorDesigner.Runtime.Tasks.Tooltip("自己")]
public SharedGameObject monster; public override TaskStatus OnUpdate(){ if(Vector3.Distance(player.Value.transform.position, monster.Value.transform.position) > ranage){ return TaskStatus.Failure;
}
return TaskStatus.Success;
}
}
using UnityEngine;
using BehaviorDesigner.Runtime.Tasks;
using BehaviorDesigner.Runtime; [TaskCategory("MyConditionals")]
[TaskDescription("判断对象是否移动")]
public class NotMove : Conditional { [BehaviorDesigner.Runtime.Tasks.Tooltip("上一次的位置")]
public Vector3 lastPosition; [BehaviorDesigner.Runtime.Tasks.Tooltip("判断的对象")]
public SharedGameObject obj; public override TaskStatus OnUpdate(){ if(obj.Value.transform.position == lastPosition){ return TaskStatus.Success;
}
lastPosition = obj.Value.transform.position;
return TaskStatus.Failure;
}
}

依靠这些节点就可以拼出一颗行为树,一运行就可以看到一个简单的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. 算法-MergeSort

    #include <iostream> #include <vector> #include <iterator> using namespace std; ; v ...

  2. export a java project to runable jar

    When a java project needs to be transfered to another machine, e.g. vps, we need to export it to a r ...

  3. X3850M2安装CertOS 7 KVM 2--Mount

    x3850 m2设备接的存储是DS8000,检查发现系统下有两块disk是IBM2107900,一块容量为215GB,另一块是4GB.原因简单,4GB是以前高可用群集时用来做仲裁盘的. 奇怪的是,每块 ...

  4. android.os.NetworkOnMainThreadException异常

    在android4.0以前,访问网络的代码可以写在UI主线程,但是在android4.0以上就不能在ui主线程中访问网络了,会出现android.os.NetworkOnMainThreadExcep ...

  5. GCHandler的使用

    众所周知,我们在使用c#托管代码时,内存地址和GC回收那不是我们关心的,CLR已经给我们暗箱操作. 但是如果我们在c#中调用了一个非托管代码,比如vc的DLL,而且他有个回调函数,需要引用c#中的某个 ...

  6. mybatis配置文件查询参数的传递

    通常来说,参数传递可以使用#与$进行编写,但是使用#的效率更高,使用$方式,查看日志更方便些,尤其是当执行的sql语句非常麻烦的时候. 1) 接口 形式 以下方式 [传递参数是一个实体] public ...

  7. 整数中1出现的次数(从1到n整数中1出现的次数)

    题目:求出1~13的整数中1出现的次数,并算出100~1300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1.10.11.12.13因此共出现6次,但是对于后面问题他就没辙了.AC ...

  8. centos 7 lamp (linux+apache+mysql+php)开发环境搭建(转+原创)

    准备篇:CentOS 7.0系统安装配置图解教程 http://www.jb51.net/os/188487.html 一.配置防火墙,开启80端口.3306端口 CentOS 7.0默认使用的是fi ...

  9. HTTP 响应头信息

    HTTP 响应头信息 HTTP请求头提供了关于请求,响应或者其他的发送实体的信息. 在本章节中我们将具体来介绍HTTP响应头信息.

  10. web api 初体验 解决js调用跨域问题

    跨域界定 常见跨域: 同IP不同端口: http:IP:8001/api/user     http:IP:8002/api/user 不同IP不同端口: http://172.28.20.100:8 ...