unity 4种实现动态障碍方法
此文将介绍4种实现动态障碍的方法,2种基于navmesh,2种基于astar算法。
1.基于navmesh。
1.制作场景障碍:
a.有几个独立的障碍物,就定义几个user area,即,一个场景仅仅支持一个字节数目的独立障碍物

b.建立碰撞盒建立障碍物:
碰撞盒是可行走区域。

c.设置碰撞盒gameobject的navigation面板的object页签的navigation area属性:
每个独立障碍物对应一个前面步骤a中定义的area,如果几个障碍一起动态生成或消失,则可以使用同一个area

2.代码控制这些动态障碍物的生成和消失:
障碍物消失是它的碰撞盒区域加入navmesh寻路mask中,即障碍物区域可行走,生成是不加入mask中,该区域不可行走
开启或关闭第几个door:
_door += ;//因为前面有3个内置area:walkable,not walkable和jump,假如_door=1,即_door+=2后_door=3, 下面的1<<3后1在右起第4个字节,即对于第4个area:door1
if (_flag > )//flag>0表示开门,即障碍物消失,该碰撞盒区域可行走,需把该area位 置为1
{
navmesh_mask_ |= ( << _door);
}
else
{
navmesh_mask_ &= (~( << _door));//该area位 置为0
}
3.真正用到的地方(上面所有的工作服务的对象,其实也是此动态障碍解决方法的思考起点,我就是想知道CalculatePath的第3个参数的作用才找到此解决方法的):
所谓障碍物,影响的就是寻路!当障碍物消失时我们需要让此区域可行走,没消失时不可行走,下面是寻路代码:
NavMeshPath nav_path = new NavMeshPath();
if (NavMesh.CalculatePath(src_pos, dis_pos, navmesh_mask_, nav_path))
即,通过控制calculatepath的第3个参数navmesh_mask实现动态障碍的控制:navmesh_mask每个位对应一个area,当某个area对应的位是0时寻路认为不可行走,1则可行走。
总结:此方法简单明了,并且navmesh功能是官方提供的,性能方面占优。但这个动态障碍物必须是预先摆好的,不能像lol中亚索的盾牌那样“随意区域”动态,不过一般这种假动态就已经足够项目使用了。
看来要继续研读navmesh文档,看官方有没有提供解决真动态障碍的方案了。
更新更新:打脸了,打脸了,用NavMesh Obstacle组件就能轻易让一个gameobject变成障碍物并重新计算寻路网格,这个好啊,是真动态!明天测试一下。
再次更新再次更新:因为使用navmesh_mask的方式不需要重构寻路网格,所以性能很好,所以把navmesh_mask和navmesh obstacle结合起来使用:
固定位置的动态障碍物使用navmesh_mask,不固定位置的动态障碍物使用navmesh obstacle,这样也不算打脸了=。=
2.基于astar,动态障碍物状态更新时,都需要重新计算“可行走”网格,即把障碍物所在区域改成可行走,重新设置整个网格的“可行走”区域,让寻路变得正确。这个astar插件已经基本做好了,读者可以查阅其文档即可。
大致说一下2种解决方法:
1.astar的动态障碍物实例脚本是这样的:一个带collider的gameobject,每次移动都调用一下:
AstarPath.active.UpdateGraphs(oldbounds);AstarPath.active.UpdateGraphs(newbounds);//oldbounds表示旧位置的bounds,new表示新位置的包围盒立方体
其实就是刷新一下网格某个区域,对这个区域的每个网点检测:如果被带collider的物体占,则不可行走,否则可行走。这明显可以解决随意位置动态障碍问题,并且用法简单,可以考虑。
2.还有另外一种方法,也是我目前项目使用的:不依赖collider,直接输入一个bounds,然后把这个bounds和整个网格相交,得到需要更新的bounds区域,然后直接对整个区域的网点node进行设置是否可行走:
GridGraph mGridGraph=null;
NavGraph[] graphs = AstarPath.active.graphs;
for(...)
{
if (graphs[i] is GridGraph)
{
mGridGraph = graphs[i] as GridGraph;
break;
}
}
...//计算需要设置的网点外壳
mGridGraph.nodes[z * mGridGraph.width+x].Walkable = pWalkAble;
本文总结:本文基于navmesh给出了2种解决方法,实际应用时可以结合起来提高性能,基于astar也提出了2种解决方法。
unity 4种实现动态障碍方法的更多相关文章
- Unity 几种优化建议
转: http://user.qzone.qq.com/289422269/blog/1453815561?ptlang=2052 Unity 几种优化建议 最简单的优化建议: 1.PC平台的话保持场 ...
- 使用runtime给类动态添加方法并调用 - class_addMethod
上手开发 iOS 一段时间后,我发现并不能只着眼于完成需求,利用闲暇之余多研究其他的开发技巧,才能在有限时间内提升自己水平.当然,“其他开发技巧”这个命题对于任何一个开发领域都感觉不找边际,而对于我来 ...
- Struts2 动态调用方法
struts2动态调用方法有两种方式 方式一:用通配符进行调用: Action方法: package com.bjyinfu.struts.actions; public class CatchDyn ...
- Xcode中Objc动态调用方法同时避免警告的几个办法
我们在Xcode中使用objc写代码的时候往往会碰到动态调用方法的时候. 如果是静态调用这很常见,不会有任何问题: [self performSelector:@selector(method)]; ...
- Python爬虫之三种网页抓取方法性能比较
下面我们将介绍三种抓取网页数据的方法,首先是正则表达式,然后是流行的 BeautifulSoup 模块,最后是强大的 lxml 模块. 1. 正则表达式 如果你对正则表达式还不熟悉,或是需要一些提 ...
- ref:一种新的攻击方法——Java Web表达式注入
ref:https://blog.csdn.net/kk_gods/article/details/51840683 一种新的攻击方法——Java Web表达式注入 2016年07月06日 17:01 ...
- ASM(四) 利用Method 组件动态注入方法逻辑
这篇继续结合样例来深入了解下Method组件动态变更方法字节码的实现.通过前面一篇,知道ClassVisitor 的visitMethod()方法能够返回一个MethodVisitor的实例. 那么我 ...
- 目前以lib后缀的库有两种,一种为静态链接库(Static Libary,以下简称“静态库”),另一种为动态连接库(DLL,以下简称“动态库”)的导入库(Import Libary,以下简称“导入库”)。静态库是一个或者多个obj文件的打包
前以lib后缀的库有两种,一种为静态链接库(Static Libary,以下简称“静态库”),另一种为动态连接库(DLL,以下简称“动态库”)的导入库(Import Libary,以下简称“导入库”) ...
- Guava动态调用方法
前言 大家在Coding的时候,经常会遇到这样一个情况,根据不同的条件去执行对应的代码.我们通常的处理方式是利用if-else判断,或者直接switch-case,特别是jdk1.6之后,swith开 ...
随机推荐
- JQuery插件,轻量级表单模型验证(续 一)
之前的代码结构,不方便扩展多结构的模型验证 重新结构设计了一下验证模型核心 var validateForm = (function(model) { model.Key = "[data- ...
- Linux集群配置离线ntp时间同步服务
集群中时间不同步有可能会让大数据的应用程序运行混乱,造成不可预知的问题,比如Hbase.mongodb副本集等,Hbase当时间差别过大时就会挂掉,mongodb如果副本时间过快,会出现时间栈帧溢出提 ...
- java目前常用的几种定时任务
java目前常用的几种定时任务 JDK自带的Timer spring的Task Quartz elastic-job分布式定时任务 一.JDK自带的Timer Timer是jdk中提供的一个定时器工具 ...
- 拓展欧几里得求 ax + by = c的通解(a >=0, b >= 0)
#include <iostream> #include <cstdio> #include <algorithm> #include <vector> ...
- IOS - ACL (访问控制列表)
ACL 介绍 ACL 是一款 IOS 软件工具,而不是某种协议.从名字上来看,ACL 的主要功能是控制对网络资源的访问.事实上这是 ACL 最早的用途.现在 ACL 除了能够限制访问外,更多时候,我们 ...
- tableau用户留存分析
1.数据源 这是个母婴产品的购买流水数据 2.数据处理 字段拆分.创建购买点会员生命周期 3.分析不同省份的留存率情况 根据第12个月的留存率对省市进行分组 实际业务中也可以通过类似的方法对用户年龄组 ...
- 2020-08-02:输入ping IP 后敲回车,发包前会发生什么?
福哥答案2020-08-02: 首先根据目的IP和路由表决定走哪个网卡,再根据网卡的子网掩码地址判断目的IP是否在子网内.如果不在则会通过arp缓存查询IP的网卡地址,不存在的话会通过广播询问目的IP ...
- MSF常用命令备忘录
msf下的命令 set session x:设置要攻击的session #监听端口反弹PHP shell use exploit/multi/handler set payload php/meter ...
- C++中将对象this转换成unsigned char指针
示例程序 // ---CodeBlob.h--- #ifndef CODEBLOB_H_ #define CODEBLOB_H_ class CodeBlob { private: const cha ...
- STL函数库的应用第四弹——全排列(+浅谈骗分策略)
因为基础算法快学完了,图论又太难(我太蒻了),想慢慢学. 所以暂时不写关于算法的博客了,但又因为更新博客的需要,会多写写关于STL的博客. (毕竟STL函数库还是很香的(手动滑稽)) 请出今天主角:S ...