如果不想用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随机巡逻障碍物预判与快速运动时物理穿透的思考的更多相关文章

  1. 解决Unity中模型部件的MeshCollider不随动画一起运动的问题

    Unity的3d游戏开发中,经常遇到需要将模型的某一部分(比如武器),单独做碰撞处理的情况. 导入模型后,给武器部分添加MeshCollider,MeshCollider的Mesh通常包含在模型里,如 ...

  2. Unity中各个平台的预编译的运用方式

    1,unity中官方文档的一个操纵关键词   Platform Dependent Compilation 2,常用的预编译关键词    UNITY_EDITOR    编辑器调用.UNITY_STA ...

  3. Unity中List的随机排序(乱序)

    为什么要给List排序做一个Unity限定条件呢 首先,是C#中的List泛型,若是Java,直接调用Collection.shuffle()就OK了 而Unity的C#版本较低,不能使用Random ...

  4. Unity中的协程(一)

    这篇文章很不错的问题,推荐阅读英文原版: Introduction to Coroutines Scripting with Coroutines   这篇文章转自:http://blog.csdn. ...

  5. Unity Rain Ai 插件基本使用(二)

    前言 在前面的教程中我们已经基本实现了路径导航和障碍物规避. 但是这样我们并没有让我们的角色学会思考,他只是机械的去完成一些步骤,这并不能体现Rain插件的智能. 一个角色他应该有多个不同的状态,待机 ...

  6. 在Unity中创建攻击Slot系统

    http://www.manew.com/thread-109310-1-1.html 马上注册,结交更多好友,享用更多功能,让你轻松玩转社区. 您需要 登录 才可以下载或查看,没有帐号?注册帐号  ...

  7. Unity中的资源管理

    一.AssetBundle 相关 Q1:Unity中的SerializedFile是怎么产生的?请问用Unload(false)可以清除吗?因为读取了Bundle里面的内容后已经赋值给其他物体了.而且 ...

  8. Unity中使用Attribute

    Attribute是c#的语言特性 msdn说明如下: The Attribute class associates predefined system information or user-def ...

  9. Unity中2D和UGUI图集的理解与使用

    图集 什么是图集? 在使用3D技术开发2D游戏或制作UI时(即使用GPU绘制),都会使用到图集,而使用CPU渲染的2D游戏和UI则不存在图集这个概念(比如Flash的原生显示列表),那么什么是图集呢? ...

随机推荐

  1. 快速查看本地IP地址

    1. 新建Windows批处理文件(*.bat) @echo off echo 本机IP ipconfig|find "IPv4" echo. echo 电脑名 hostname ...

  2. 使用SQL Server内存优化表 In-Memory OLTP

    如果你的系统有高并发的要求,可以尝试使用SQL Server内存优化表来提升你的系统性能.你甚至可以把它当作Redis来使用. 要使用内存优化表,首先要在现在数据库中添加一个支持内存优化的文件组. M ...

  3. Redis令牌桶限流

    一 .场景描述 在开发接口服务器的过程中,为了防止客户端对于接口的滥用,保护服务器的资源, 通常来说我们会对于服务器上的各种接口进行调用次数的限制.比如对于某个 用户,他在一个时间段(interval ...

  4. SpringSession header/cookie/attribute存放 session id

    SpringSession header/cookie/attribute存放 SessionID(死磕) 疯狂创客圈 Java 高并发[ 亿级流量聊天室实战]实战系列 [博客园总入口 ] 架构师成长 ...

  5. Linux下部署SSM,通过启动tomcat即可运行

    Linux下部署SSM项目 1. Java环境配置(JRE&JDK) 安装JDK8:sudo yum install java-1.8.0-openjdk 将操作系统配置为默认使用JDK8:s ...

  6. sql server判断表存在

    在创建表.更改表结构.删除表或对表进行什么操作之前,一个比较严谨的做法是先判断该表是否已经存在. 在SQL Server中判断一个表是否存在,有两个方法,下面以diso表为例. 方法1 from sy ...

  7. Thinkphp 5.0.15 设计缺陷导致Insert/update-SQL注入 分析

    分析 与上一个漏洞类似,这个也是前端可以传入一个数组变量,如['exp','123','123'],后端根据array[0]来将array[1]和array[2]直接拼接到SQL语句中. 由于TP只是 ...

  8. python高级编程——进程和进程池

    python提供了一个跨平台的多进程支持——multiprocessing模块,其包含Process类来代表一个进程对象 1.Process语法结构:(注: 传参的时候一定使用关键字传参) 2.自定义 ...

  9. HttpWebRquest.GetRequestStreamAsync()发生延迟

    前景提要:此问题不定适用Browser通信方式,主要提供给通信发生异常时解决思路. Q: request请求创建过程发生延迟 [Scene]: ​ .Net的HttpWebRquest.GetRequ ...

  10. Saltstack_使用指南15_多master

    1. 主机规划 实现2个master,当这两个master运行时都可以向minion发送命令. salt 版本 [root@salt100 ~]# salt --version salt (Oxyge ...