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));
}

}


版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

学习Unity3D之动态障碍物、高空跳下和选择性行走。

欢迎来到unity学习、unity培训、unity企业培训教育专区,这里有很多U3D资源、U3D培训视频、U3D教程、U3D常见问题、U3D项目源码,我们致力于打造业内unity3d培训、学习第一品牌...

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

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

Unity 初级AI躲避障碍物

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

Unity人工智能学习—高级随机运动

前面的学习中已经涉及到了随机运动,这一篇主要还是前面的随机运动的改进,不废话直接上效果图吧,对比前面的随机运动,这里的飞机会随机的转动方向,而且转弯平滑 有一种做法是每一帧都计算出一个随机的驱动...

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

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

unity3d_角色与障碍物遮挡

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

unity-Navigation寻路-添加跳跃点 Off-mesh Link

在两个 不连通 的寻路网格间,如果想在这两个网格间行走,就需要添加跳跃的连接 Off-mesh Link 官网地址:https://docs.unity3d.com/Manual/nav-Crea...

Unity3D获取当前键盘按键及Unity3D鼠标、键盘的基本操作

获取当前键盘按键,代码如下: using UnityEngine; using System.Collections; public class GetCurrentKey : MonoBehavio...

Unity3D Editor 编辑器简易教程

Star 自定义编辑器简易教程 an introduction to custom editors 原文地址 http://catlikecoding.com/unity/tutorials/...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

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