unity3d个人写的检测障碍物并避开的方法

原创 2015年11月19日 21:30:03

虽然unity3d有自带的navigation避开障碍物,但有一次做项目时发现:当场景大而且人物变多时这个navigation计算不是很灵敏,于是心想能否自己想出另外一个检测障碍物并避开的方法。话不多说,上代码:

using UnityEngine;
using System.Collections;

public class ObstacleDetection : MonoBehaviour {

public float MoveSpeed = 2; //避开时的移动速度
public float ColliderDistance = 2; //检测距离

public string[] ObstacleTags; //障碍物的标签,就是要避开的障碍物
public  bool IsObstacle{get{return _IsObstacle;}} //是否有障碍物,用来给外部的接口

private Vector3 pos; //记录避开障碍物前的的旋转坐标

private bool IsForward = false; //前方是否有障碍物
private bool IsInLeft  = false; //左方是否有障碍物
private bool IsInRight = false; //右方是否有障碍物
private bool _IsObstacle = false; //是否有障碍物

private float timer = 0; //避开障碍物后返回原先状态的缓冲计时

private Transform m_transform;
// Use this for initialization
void Start () {
m_transform = this.transform;

}
// Update is called once per frame
void Update () {
MoveForward ();
Detection();

}
//当侧面有障碍物而前方没有时向前移动
void MoveForward()
{
if(_IsObstacle)
{
if(!IsForward)
{
pos = m_transform.localEulerAngles;
m_transform.Translate(Vector3.forward*Time.deltaTime*MoveSpeed);
}
}
}
//障碍物检测
#region Detection
void Detection()
{
IsForward = DirectionForward ();
IsInLeft = DirectionLeft ();
IsInRight = DirectionRight ();

if (IsForward) {
if (IsInLeft && !IsInRight) 
{
float rotateAnglesY = RotateAngles (pos.y + 90);
m_transform.localEulerAngles = new Vector3 (m_transform.localEulerAngles.x,
                                           rotateAnglesY,
                                           m_transform.localEulerAngles.z);
else if (!IsInLeft && IsInRight) 
{
float rotateAnglesY = RotateAngles (pos.y - 90);
m_transform.localEulerAngles = new Vector3 (m_transform.localEulerAngles.x,
                                           rotateAnglesY,
                                           m_transform.localEulerAngles.z);
else if (IsInLeft && IsInRight) 
{
float rotateAnglesY = RotateAngles (pos.y + 180);
m_transform.localEulerAngles = new Vector3 (m_transform.localEulerAngles.x,
                                           rotateAnglesY,
                                           m_transform.localEulerAngles.z);
}
else 
{
float rotateAnglesY = RotateAngles (pos.y + Random_1_1 () * 90);
m_transform.localEulerAngles = new Vector3 (m_transform.localEulerAngles.x,
                                           rotateAnglesY,
                                           m_transform.localEulerAngles.z);
}
else 
{
if(!IsInLeft && !IsInRight)
{
if(IsObstacle)
{
//避开障碍物到返回原先状态的缓冲时间
timer += Time.deltaTime;
if(timer > 0.8f)
{
timer = 0;
_IsObstacle = false;
}
}
}
}
}
//检测前方
bool DirectionForward()
{
bool check = false;
RaycastHit hitForward;
Vector3 LocalForward = m_transform.TransformPoint(Vector3.forward)-m_transform.position;
if (Physics.Raycast (m_transform.position, 
                     LocalForward, 
                     out hitForward, ColliderDistance/2))
{
if(CompareTags(hitForward.transform.gameObject.tag))
{
_IsObstacle =true;
check = true;
}
}
return check;
}
//检测右方
bool DirectionRight()
{
bool check = false;
RaycastHit hitRight;
Vector3 LocalRight = m_transform.TransformPoint(Vector3.right)-m_transform.position;
if (Physics.Raycast (m_transform.position, 
                     LocalRight, 
                     out hitRight, ColliderDistance)) 
{
if(CompareTags(hitRight.transform.gameObject.tag))
{
_IsObstacle =true;
check = true;
}
}
return check;
}
//检测左方
bool DirectionLeft()
{
bool check = false;
RaycastHit hitLeft;
Vector3 LocalLeft = m_transform.TransformPoint(-Vector3.right)-m_transform.position;
if (Physics.Raycast (m_transform.position, 
                     LocalLeft, 
                     out hitLeft, ColliderDistance)) 
{
if(CompareTags(hitLeft.transform.gameObject.tag))
{
_IsObstacle =true;
check = true;
}
}
return check;
}
#endregion
//自己写的一些小功能
#region MyFunction
//遍历ObstacleTags数组,是否与其中的一个值相符
bool CompareTags(string name)
{
bool isSame = false;
for(int i = 0; i <  ObstacleTags.Length;i++)
{
if(ObstacleTags[i].Equals(name))
{
isSame = true;
break;
}
}
return isSame;
}
//将角度规范,变为0~360之间
float RotateAngles(float Angles)
{
float angles = 0;
if (Angles >= 0) {
angles = Angles - ((int)(Angles / 360)) * 360;
else 
{
angles = (((int)(Angles / 360))+1) * 360 - Angles;
}
return angles;
}
//产生-1~1的随机数,不包括0
float Random_1_1()
{
float index = Random.Range (-1,1);
if(index == 0)
{
index = Random_1_1();
}
return index;
}
#endregion
void OnDrawGizmos()
{
Gizmos.color = Color.red;
Gizmos.DrawLine (transform.position, transform.TransformPoint(Vector3.forward*ColliderDistance/2));
Gizmos.DrawLine (transform.position, transform.TransformPoint(Vector3.right*ColliderDistance));
Gizmos.DrawLine (transform.position, transform.TransformPoint(Vector3.left*ColliderDistance));
}

}


Unity中通过射线躲避障碍物寻路的一些初步探索

在简单的射线寻路方法上增加了一些条件判断,避免进入死胡同,可以解决一些简单的死胡同场景,但更复杂的场景还需要进一步探索...
  • ithot
  • ithot
  • 2016年10月01日 10:45
  • 1737

Unity 初级AI躲避障碍物

阅读《Unity Game AI programming 》第6章后,感觉躲避障碍物算法不是很给力。为了研究和学习Unity,自己改良躲避障碍物的算法。当然,代码没有优化,不过没关系,抛砖引玉,记录思...

unity3d_角色与障碍物遮挡

最近的项目有涉及到关于角色与障碍物的遮挡与显示问题: 个人能想到的解决方法有两种: ①从摄像机发射与角色连接射线,判断射线碰撞的go,将其材质改为半透明。 ②shader 第一种方法:...

Unity人工智能学习—躲避规则障碍一

第一部分:效果预览先上效果图。这一部分将要讲的是智能躲避规则的障碍物。其实,这是最终现实效果,在算法中实际上使用到了 一个隐藏的碰撞检测盒子,这个盒子是从智能体延伸出的。如图所示:保持红色长...

基于视觉的障碍物检测和规避

1. 介绍为了使直升机在复杂多变的走廊中平稳避障飞行,本文提出了三个算法: 一个鲁棒性好的平稳控制算法(基于光流+声波传感器);对周围环境做及时反应使helicopter保持在航线上 障...

图像处理(三) 检测障碍物

前几天写了一个小的项目关于:当手机处于静止状态时,识别是否动或者前方有不同物体MainActivitypublic class MainActivity extends Activity implem...
  • Kazichs
  • Kazichs
  • 2016年10月24日 20:31
  • 2280

基于深度摄像头的障碍物检测(realsense+opencv)

一个基于深度摄像头的障碍物检测 代码的核心思路是首先通过二值化,将一米之外的安全距离置零不考虑,然后通过开运算去除掉一些噪点(这个后来发现不一定有必要),在求出所有障碍物的凸包,这个时候要计算面积,...

【OpenCV】障碍物提取

由于后续要做移动机器人的视觉导航,所以提取机器人行进路径上的障碍物是很重要的一步。目前已基本实现障碍物的提取,但精度不高,后续仍要进行改进。本文主要参考了基于深度摄像头的障碍物检测(realsense...

unity-Navigation寻路-添加障碍物Obstacle

在场景中添加障碍物,需要点Bake重新烘焙出新的 导航网格,不是运行时。 如果在运行时添加障碍物动态Bake出新的导航网格,就需要使用 Nav Mesh Obstacle 官网传送门:http...

Unity20--动态的障碍物

一、动态障碍物     //动态障碍物,障碍物可移动,创建Navigation01文本     //1.先烘焙地面,在object面烘焙,障碍物先不烘焙,     //2.写文本,赋给了cu...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:unity3d个人写的检测障碍物并避开的方法
举报原因:
原因补充:

(最多只允许输入30个字)