您的位置:首页 > 移动开发 > Unity3D

unity3d碰撞检测之立方体碰撞算法

2015-08-09 21:05 831 查看
         相信很多做游戏的开发人员都会面临 物体碰撞检测的问题  一般的手游不需要考虑Y轴 只需要用到简单的 点与面的位置关系 即1点在面内 2 点在面外或则点与线的位置关系1 点在线上 2点在线外,假如要做类似天涯明月刀的端游 人物可能会跳到房子上 这时候你需要考虑到Y轴 那么点与面的位置关系就不满足碰撞需求了 我们这时候就需要用圆柱体碰撞 或则 立方体碰撞了 这里我要讲解的就是立方体碰撞检测的算法

         首先做立方体碰撞检测算法需要哪些条件呢 1 立方体的8个顶点坐标 2 要检测的点坐标

         假如我要做一个英雄普通攻击碰撞 我可以得到英雄的三维坐标 知道英雄的坐标,立方体的8个顶点坐标也随即可以得出了 怪物坐标自然也是已知的 分析到这里 接下来就是实现算法了

         知道了立方体的8个顶点坐标 和怪物坐标

         我们以立方体其中一个顶点作为坐标原点,过原点其中两个顶点分别在另两条坐标轴上 即立方体3个顶点分别在3条轴上 然后将怪物变换位置从世界坐标到坐标原点为Point1  这个时候以新坐标原点立方体的长宽高也形成了一个新的坐标Point2 最后分别比较Point1和Point2, x、y、z即可得出结果 文字分析结束下面上代码

#region 立方体碰撞

/// <summary>
/// 立方体碰撞(主角朝向 可对空)使用函数
/// </summary>
/// <param name="transform">当前对象</param>
/// <param name="Point">敌人坐标</param>
/// <param name="width">立方体宽度</param>
/// <param name="distance">立方体长度</param>
/// <param name="hight">立方体高度</param>
/// <param name="JuLi">当前对象离脚底的距离</param>
/// <returns>是否在立方体内</returns>
public static bool Cubecollision(ref Transform Cude, Transform transform, Vector3 Point, float width, float distance, float hight, float JuLi)
{
//得出立方体的8个顶点坐标
Quaternion r = transform.rotation;
Vector3 DownLeftback = (transform.position + (r * Vector3.left) * width + (r * Vector3.down) * JuLi);
Vector3 DownRightback = (transform.position + (r * Vector3.right) * width + (r * Vector3.down) * JuLi);
Vector3 DownLeftforward = DownLeftback + (r * Vector3.forward) * distance;
Vector3 DownRightforward = DownRightback + (r * Vector3.forward) * distance;
Vector3 UpLeftback = DownLeftback + (r * Vector3.up) * hight;
Vector3 UpRightback = DownRightback + (r * Vector3.up) * hight;
Vector3 UpLeftforward = UpLeftback + (r * Vector3.forward) * distance;
Vector3 UpRightforward = UpRightback + (r * Vector3.forward) * distance;
//判断是否在立方体内
if (Cubedetection(ref Cude, Point, UpLeftforward, UpRightforward,
UpLeftback, UpRightback, DownLeftforward,
DownRightforward, DownLeftback, DownRightback))
{
return true;
}
return false;
}

/// <summary>
/// 画线函数测试立方体是否正确
/// </summary>
/// <param name="transform"></param>
/// <param name="Point"></param>
/// <param name="width"></param>
/// <param name="distance"></param>
/// <param name="hight"></param>
/// <param name="JuLi"></param>
public static void Cubedrawingline(Transform transform, float width, float distance, float hight, float JuLi)
{
Quaternion r = transform.rotation;
Vector3 Downleftback = (transform.position + (r * Vector3.left) * width + (r * Vector3.down) * JuLi);
Vector3 DownRightback = (transform.position + (r * Vector3.right) * width + (r * Vector3.down) * JuLi);
Vector3 DownLeftforward = Downleftback + (r * Vector3.forward) * distance;
Vector3 DownRightforward = DownRightback + (r * Vector3.forward) * distance;
Vector3 UpLeftback = Downleftback + (r * Vector3.up) * hight;
Vector3 UpRightback = DownRightback + (r * Vector3.up) * hight;
Vector3 UpLeftforward = UpLeftback + (r * Vector3.forward) * distance;
Vector3 UpRightforward = UpRightback + (r * Vector3.forward) * distance;
//底面
Debug.DrawLine(Downleftback, DownRightback);
Debug.DrawLine(Downleftback, DownLeftforward);
Debug.DrawLine(DownRightback, DownRightforward);
Debug.DrawLine(DownLeftforward, DownRightforward);
//左面
Debug.DrawLine(Downleftback, UpLeftback);
Debug.DrawLine(UpLeftback, UpLeftforward);
Debug.DrawLine(UpLeftforward, DownLeftforward);
Debug.DrawLine(DownLeftforward, Downleftback);
//右面
Debug.DrawLine(DownRightback, UpRightback);
Debug.DrawLine(UpRightback, UpRightforward);
Debug.DrawLine(UpRightforward, DownRightforward);
Debug.DrawLine(DownRightforward, DownRightback);
//上面
Debug.DrawLine(UpRightback, UpRightforward);
Debug.DrawLine(UpLeftback, UpRightback);
Debug.DrawLine(UpLeftback, UpLeftforward);
Debug.DrawLine(UpLeftforward, UpRightforward);
//前面
Debug.DrawLine(UpLeftforward, UpRightforward);
Debug.DrawLine(UpLeftforward, DownLeftforward);
Debug.DrawLine(UpRightforward, DownRightforward);
Debug.DrawLine(DownLeftforward, DownRightforward);
//后面
Debug.DrawLine(UpLeftback, UpRightback);
Debug.DrawLine(UpLeftback, Downleftback);
Debug.DrawLine(UpRightback, DownRightback);
Debug.DrawLine(Downleftback, DownRightback);
}

/// <summary>
/// 立方体碰撞检测算法
/// </summary>
/// <param name="Cude">Transform 坐标原点 没办法因为要用到InverseTransformPoint函数必须传个Transform进来 为了节约性能用了ref引用传递 </param>
/// <param name="Point">敌人坐标</param>
/// <param name="UpLeftforward">立方体上左前坐标</param>
/// <param name="UpRightforward">立方体上右前坐标</param>
/// <param name="UpLeftback">立方体上左后坐标</param>
/// <param name="UpRightback">立方体上右后坐标</param>
/// <param name="DownLeftforward">立方体下左前坐标</param>
/// <param name="DownRightforward">立方体下右前坐标</param>
/// <param name="DownLeftback">立方体下左后坐标</param>
/// <param name="DownRightback">立方体下右前坐标</param>
/// <returns>返回是否在立方体内</returns>
private static bool Cubedetection(ref Transform Cude, Vector3 Point, Vector3 UpLeftforward, Vector3 UpRightforward, Vector3 UpLeftback, Vector3 UpRightback, Vector3 DownLeftforward, Vector3 DownRightforward, Vector3 DownLeftback, Vector3 DownRightback)
{
//判断(Cude代表坐标原点)Cude是否为空
if (Cude == null)
{
Cude = GameObject.CreatePrimitive(PrimitiveType.Cube).transform;
//去掉Mesh使之成为一个空物体
Destroy(Cude.GetComponent<MeshFilter>());
Destroy(Cude.GetComponent<BoxCollider>());
Destroy(Cude.GetComponent<MeshRenderer>());
}
//这里以上左后为坐标原点 规定Y轴上方向为正方向 X轴右方向为正 Z轴前方向为正
Cude.position = UpLeftback;
//得出以Cude为坐标原点立方体长宽高形成的新坐标x y z
float x = (UpRightback - UpLeftback).x;
float y = (DownLeftback - UpLeftback).y;
float z = (UpLeftforward - UpLeftback).z;
//转换Point变换位置从世界坐标到Cude自身坐标
Vector3 m_Point = Cude.InverseTransformPoint(Point);
//比较x y z大小判断是否在立方体内
if (m_Point.y >= y && m_Point.y <= 0 && m_Point.x <= x && m_Point.x >= 0 && m_Point.z <= z && m_Point.z >= 0)
{
Debug.Log("对方在立方体内");
return true;
}
Debug.Log("对方不在立方体内");
return false;
}
#endregion

 

 

版权声明:本篇文章为原创,欢迎交流,欢迎转载;转载请勿篡改内容,并且注明出处,谢谢!

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息