如果不想用Unity的导航系统,很多时候就要解决如何预判前进路径中的障碍物问题,之前也看过一些非常经典的寻路算法例如AStar寻路,虽然也可实现功能,但总感觉有些小题大做。寻路算法大多数都是为了得出最优解,但如果只是用在一个区域内随机运动的远程怪身上的话,根本就不需要用这么复杂的算法。
就比如上面这个简单的远程怪,它根本就不想接近玩家,它的运动方式就是在一定的距离内朝任意方向走一段,到达了就朝玩家来一发,然后就这么反复,直到它被打死。(哎,这悲伤的命运)
然后问题就出现了,因为它就这么呆萌呆萌地一直朝选定的下一个随机位置运动,那么很可能在途中遭遇不可逾越的障碍物,假如这怪物能跳的话那还好说,碰到了障碍物就飞奔而起,来个360度空中转体3周半,惊艳全场。可惜的是它并又没有Get这个技能,所以你就会看到一个顶着障碍物干瞪眼的家伙与障碍物进行着永无天日的持久抗争,于心不忍的你开始给它增加一些预判障碍物的方法:
1.最简单最粗暴,能不能直接用时间来呢,一段时间内还没有任何的距离运动,那说明遇到障碍物了,直接就*重新随机下一个目标位置,如果随机的下一个位置又有障碍物,那就继续,直到可以继续运动为止。其实这里更优的做法应该是进行学习,每次随机到障碍物位置后就记下来,以后周围半径1的范围内都不再成为下一个随机点。
public override TaskStatus OnUpdate()
{
if (timer > .2f)
{
if ((transform.position - posAtlastTimer).sqrMagnitude < .1f)
{
//记录当前位置...
//重新随机目标位置...
}
timer = 0f;
posAtlastTimer = transform.position;
}
}
需要一个计时器timer和记录目标上一timer位置的变量posAtlastTimer。
2.考虑利用OnCollisionEnter(Collision collision)方法来检测,判断碰到的碰撞体的标签,如果是障碍物,就记录当前位置并重新随机。这种方式可以避免因为反复随机到障碍物位置而产生的卡顿问题。
public override void OnCollisionEnter(Collision collision)
{
if (collision.transform.tag == "Collider")
{
//记录当前位置...
//重新随机目标位置...
}
}
3.在每次随机运动前就进行射线检测,发出一条从当前点到目标点方向的射线(也可以按照物体的上下左右边缘发出多条),射线的长度即为当前位置到目标位置的距离,如果射线碰到了障碍物,那么就可以提前得知该路径是无效的。
private Vector3 RayCheckCollider(Vector3 tarPos)
{
Vector3 offset = tarPos - transform.position;
Ray ray = new Ray(transform.position, offset);
RaycastHit info;
if (Physics.Raycast(ray, out info, offset.magnitude))
{
if (info.collider.tag == "Collider")
{
//记录当前位置...
//重新随机目标位置...
tarPos = RayCheckCollider(tarPos);//递归检测
}
}
Debug.DrawLine(ray.origin, tarPos,Color.red);
return tarPos;
}
以上三种方法并不冲突,可同时使用。一般第三种方法要优于前两种,它可以提前避免遭遇障碍物,但往往这样做也缺乏了一定的真实性,可以额外设置一个视野范围进行优化,判断AI是否能提前察觉障碍物,此时发出的射线长度也应该是该视野半径值,一旦AI在行进目标位置的过程中发现障碍物,不等碰到障碍物之前就重新随机下一个目标位置。
AI通过学习记录的无效目标位置集合可用于每次随机出下一目标位置的判定依据,该集合点可设定为所有AI进行随机判定的全局变量。
private void CheckDeadZone(Vector3 tarPos)
{
foreach(var item in deadPoints)
{
if ((item - tarPos).sqrMagnitude < 1f)
{
//重新随机目标位置...
return;
}
}
}
后来发现在遇到快速运动的物体的物理穿透问题时也可以用到射线检测作为预判,在快要到达障碍物时脱离当前运动状态或将速度迅速降低,可有效解决物理穿透的问题。
关于Unity中AI随机巡逻障碍物预判与快速运动时物理穿透的思考的更多相关文章
-
解决Unity中模型部件的MeshCollider不随动画一起运动的问题
Unity的3d游戏开发中,经常遇到需要将模型的某一部分(比如武器),单独做碰撞处理的情况. 导入模型后,给武器部分添加MeshCollider,MeshCollider的Mesh通常包含在模型里,如 ...
-
Unity中各个平台的预编译的运用方式
1,unity中官方文档的一个操纵关键词 Platform Dependent Compilation 2,常用的预编译关键词 UNITY_EDITOR 编辑器调用.UNITY_STA ...
-
Unity中List的随机排序(乱序)
为什么要给List排序做一个Unity限定条件呢 首先,是C#中的List泛型,若是Java,直接调用Collection.shuffle()就OK了 而Unity的C#版本较低,不能使用Random ...
-
Unity中的协程(一)
这篇文章很不错的问题,推荐阅读英文原版: Introduction to Coroutines Scripting with Coroutines 这篇文章转自:http://blog.csdn. ...
-
Unity Rain Ai 插件基本使用(二)
前言 在前面的教程中我们已经基本实现了路径导航和障碍物规避. 但是这样我们并没有让我们的角色学会思考,他只是机械的去完成一些步骤,这并不能体现Rain插件的智能. 一个角色他应该有多个不同的状态,待机 ...
-
在Unity中创建攻击Slot系统
http://www.manew.com/thread-109310-1-1.html 马上注册,结交更多好友,享用更多功能,让你轻松玩转社区. 您需要 登录 才可以下载或查看,没有帐号?注册帐号 ...
-
Unity中的资源管理
一.AssetBundle 相关 Q1:Unity中的SerializedFile是怎么产生的?请问用Unload(false)可以清除吗?因为读取了Bundle里面的内容后已经赋值给其他物体了.而且 ...
-
Unity中使用Attribute
Attribute是c#的语言特性 msdn说明如下: The Attribute class associates predefined system information or user-def ...
-
Unity中2D和UGUI图集的理解与使用
图集 什么是图集? 在使用3D技术开发2D游戏或制作UI时(即使用GPU绘制),都会使用到图集,而使用CPU渲染的2D游戏和UI则不存在图集这个概念(比如Flash的原生显示列表),那么什么是图集呢? ...
随机推荐
-
PHP redis Api 中文文档
phpredis是php的一个扩展,效率是相当高有链表排序功能,对创建内存级的模块业务关系 很有用;以下是redis官方提供的命令使用技巧: 下载地址如下: https://github.com/ow ...
-
MBProgressHUD框架的使用:https://github.com/jdg/MBProgressHUD
MBProgressHUD是一个开源类库,实现了各种样式的提示框, 下载地址:https://github.com/jdg/MBProgressHUD,然后把两个MBProgressHUD.h和MBP ...
-
Linux下mysql备份 恢复
转载自http://blog.chinaunix.net/uid-20577907-id-161611.html 比如我们要备份mysql中已经存在的名为linux的数据库,要用到命令mysqldum ...
-
xp 中的IIS安装成功之后,访问网页显示没有权限访问解决方法
在做xp的IIS发布网站时遇到一个问题就是当你访问网站的时候,显示没有权限访问网站,但是我已经开启了匿名访问网站了,怎么还没有权限访问呢?后来经过上网搜资料解决,当时很多网上都说没打开匿名访问,当时我 ...
-
PostgreSQL Replication之扩展与BDR
在这一章中,将向您介绍一个全新的技术,成为BDR.双向复制(BDR),在PostgreSQL的世界里,它绝对是一颗冉冉升起的新星.在不久的将来,许多新的东西将会被看到,并且人们可以期待一个蓬勃发展的项 ...
-
C#调用windows api 实现打印机控制
using System; using System.Text; using System.Runtime.InteropServices; using System.Security; using ...
-
自定义class类的简单使用
晚上闲着无事, 然后看了阮老师的es6 的类用法,包括继承. 然后, 想着在vue中怎么使用class . 1. 定义一个 classmodel.js 文件. 里面包含如下代码: 2.接着, 在vue ...
-
YUV介绍
YUV444与YUV422下采样. 一.YUV介绍 YUV有三个分量:Y(Luminance/Luma:亮度).U和V表示色差,体现的是图片的色彩信息.相对于RGB彩色空间,将亮度信息和色彩信息分离. ...
-
如何激活已经运行过的Activity, 而不是重新启动新的Activity
Intent i=new Intent(this,Activity1.class); i.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); st ...
-
redis总结问题
简单回顾了redis,在这过程中 首先得了解redis是什么,redis的运用场景,redis支持哪些数据格式,redis如何操作数据,redis如何实现高可用 redis是什么: Redis 是一个 ...