unity3d 立方体碰撞检测_unity3d 碰撞器检测碰撞 - CSDN
  • 相信很多做游戏的开发人员都会面临...人物可能会跳到房子上 这时候你需要考虑到Y轴 那么点与面的位置关系就不满足碰撞需求了 我们这时候就需要用圆柱体碰撞 或则 立方体碰撞了 这里我要讲解的就是立方体碰撞检测的算法

             相信很多做游戏的开发人员都会面临 物体碰撞检测的问题  一般的手游不需要考虑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

     

     

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

     

    展开全文
  • 需求:当立方体Cube碰到地面Plane的时候,输出碰撞物体的名称,则表述检测立方体碰撞了地面。 过程: 1.搭建一个简单的场景。 在新的工程中选择File->new Scene创建新的场景。 然后在该场景中添加地板:GameObject...

    需求:当立方体Cube碰到地面Plane的时候,输出碰撞物体的名称,则表述检测到立方体碰撞了地面。

    过程:

    1.搭建一个简单的场景。

    在新的工程中选择File->new Scene创建新的场景。

    然后在该场景中添加地板:GameObject->Create Other->Plain,

    以及正方体:GameObject->Create Other->Cube。

    给正方体添加刚体:Component->Physics->Rigidbody。

    添加后可以设置刚体属性。

    在Project处右击,选择Import Package->Physic Matarials。

    引入完成后可以直接把材质拖动到Hierachy窗口的组件中。

    bouncy:弹力十足的蹦蹦跳跳型。

    ice:像冰块一样碰撞。

    metal:像金属一样碰撞。

    rubber:像橡胶一样碰撞。

    wood:像木头一样碰撞。

    然后在“Hierarchie”面板中单击表示地板的组件,然后在Inspector中给它命名为“Ground

    然后调整他们的位置大约像这样:



    2.创建脚本文件添加监听。


    选择Assets->Create->Javascript,创建JS文件并且重命名为“Collision”

    在Project窗口中双击它,Unity会启动Monodevelop来编辑js文件。
    清除里面默认创建的代码。写上。

    function OnCollisionEnter(obj:Collision)
    {
        Debug.Log("Collider:"+obj.collider.name+" gameObject:"+obj.gameObject.name);
    }


    onCollisionEnter函数解释:这个函数是在被绑定的物体与其他物体发生碰撞的时候被调用。

    obj参数解释:被撞的物体参数,类型是Collision,在本例中就是“Ground”。

    携带变量gameObject,是我们碰撞的物体。

    3、将脚本文件拖到立方体上实现绑定

    在"Project"面板中选中collision.js脚本,按住鼠标左键不放,直接拖入“Hierarchie”面板中,放到Ground上,松开鼠标即完成绑定。可以在右边的Inspetor面板查看相关内容。


    现在可以运行该程序了。

    运行后在界面左下角会输出:

            Collider:Cube gameObject:Cube

    至此一个简单的碰撞检测便完成了。

    展开全文
  • 在进行碰撞检测时,我们最常用的工具就是射线,Unity 3D的物理引擎也为我们提供了射线类以及相关的函数接口。本文将对射线的使用进行一个总结。 射线是在三维世界中从一个点沿一个方向发射的一条无限长的线。在射线...

    在我们的游戏开发过程中,有一个很重要的工作就是进行碰撞检测。例如在射击游戏中子弹是否击中敌人,在RPG游戏中是否捡到装备等等。在进行碰撞检测时,我们最常用的工具就是射线,Unity 3D的物理引擎也为我们提供了射线类以及相关的函数接口。本文将对射线的使用进行一个总结。

    射线是在三维世界中从一个点沿一个方向发射的一条无限长的线。在射线的轨迹上,一旦与添加了碰撞器的模型发生碰撞,将停止发射。我们可以利用射线实现子弹击中目标的检测,鼠标点击拾取物体等功能。

    射线的创建和显示

    Ray射线类和RaycastHit射线投射碰撞信息类是两个最常用的射线工具类。

    创建一条射线Ray需要指明射线的起点(origin)和射线的方向(direction)。这两个参数也是Ray的成员变量。注意,射线的方向在设置时如果未单位化,Unity 3D会自动进行单位归一化处理。射线Ray的构造函数为 :
    public Ray(Vector3 origin, Vector3 direction);

    RaycastHit类用于存储发射射线后产生的碰撞信息。常用的成员变量如下:collider与射线发生碰撞的碰撞器
    distance 从射线起点到射线与碰撞器的交点的距离
    normal 射线射入平面的法向量
    point 射线与碰撞器交点的坐标(Vector3对象)

    Physics.Raycast静态函数用于在场景中发射一条可以和碰撞器碰撞的射线,相关的API如下:

         **1public static bool Raycast(Vector3 origin, Vector3 direction, float distance=Mathf.Infinity, intlayerMask=DefaultRaycastLayers);**
         **参数说明:**
         origin            射线起点世界坐标
         direction          射线方向矢量
         distance            射线长度(起点到终点的距离),默认设置为无限长
         layerMask        显示层掩码(只选择层次为layerMask指定层次的碰撞器进行碰撞,其他层次的碰撞器忽略)
         **返回值说明:**
         当射线与碰撞器发生碰撞时返回值为true,未穿过任何碰撞器时返回为false。
    
         **2public static boolRaycast(Vector3 origin, Vector3 direction, RaycastHit hitInfo, float distance =Mathf.Infinity, int layerMask = DefaultRaycastLayers);**
         这个重载函数定义了一个碰撞信息类**RaycastHit**,在使用时通过out关键字传入一个空的碰撞信息对象。当射线与碰撞器发生碰撞时,该对象将被赋值,可以获得碰撞信息包括transform、rigidbody、point 等。如果未发生碰撞,该对象为空。
    
         **3public static boolRaycast(Ray ray, float distance = Mathf.Infinity, int layerMask =DefaultRaycastLayers);**
         这个重载函数使用已有的一条射线Ray来作为参数。
    
         **4public static boolRaycast(Ray ray, RaycastHit hitInfo, float distance = Mathf.Infinity, intlayerMask = DefaultRaycastLayers);**
         这个重载函数使用已有的射线Ray来作为参数并获取碰撞信息RaycastHit。
         在调试时如果想显示一条射线,可以使用Debug.DrawLine来实现。
         **public static void DrawLine(Vector3start, Vector3 end, Color color);**
         只有当发生碰撞时,在Scene视图中才能看到画出的射线。
    
         下面这个例子创建了一个从主摄像机向y轴负向发射一条射线检测下方是否有平面存在。在场景中摄像机下方创建一个Plane游戏对象,并将下面的脚本RayDemo01.cs挂载到摄像机上。
             using UnityEngine;  
             using System.Collections;  
    
             public class RayDemo01 : MonoBehaviour {  
    
                    void Update () {  
                       // 以摄像机所在位置为起点,创建一条向下发射的射线  
                       Ray ray = new Ray(transform.position, -transform.up);  
                       RaycastHit hit;  
                       if(Physics.Raycast(ray, out hit, Mathf.Infinity))  
                       {  
                           // 如果射线与平面碰撞,打印碰撞物体信息  
                           Debug.Log("碰撞对象: " + hit.collider.name);  
                            // 在场景视图中绘制射线  
                           Debug.DrawLine(ray.origin, hit.point, Color.red); 
                       }  
                   }  
             }

    运行程序后,如图1所示,在场景视图中可以看见摄像机发出的射线。当检测到下方的平面时,会在控制台中打印输出检测结果,如图2所示。


    图1 在场景中显示的射线.jpg

    图2 在控制台中打印的碰撞检测信息.jpg

    定向发射射线的实现

    当我们要使用鼠标拾取物体或判断子弹是否击中物体时,我们往往是沿着特定的方向发射射线,这个方向可能是朝向屏幕上的一个点,或者是世界坐标系中的一个矢量方向,沿世界坐标系中的矢量方向发射射线我们已经在上面演示过如何实现。针对向屏幕上的某一点发射射线,Unity 3D为我们提供了两个API函数以供使用,分别是ScreenPointToRayViewportPointToRay

    public Ray ScreenPointToRay(Vector3 position);
    参数说明:
    position是屏幕上的一个参考点坐标。
    返回值说明:返回射向position参考点的射线。当发射的射线未碰撞到物体时,碰撞点hit.point的值为(0,0,0)。

    ScreenPointToRay方法从摄像机的近视口nearClip向屏幕上的一点position发射射线。Position用实际像素值表示射线到屏幕上的位置。当参考点position的x分量或y分量从0增长到最大值时,射线将从屏幕的一边移动到另一边。由于position在屏幕上,因此z分量始终为0。

    下面我们用一段程序示例说明如何利用ScreenPointToRay来发射一条指向屏幕上的某点来进行定向检测碰撞体。在场景中创建一个Cube位于摄像机的正前方,将下面的脚本RayDemo02.cs挂载到摄像机上。

    using UnityEngine;  
    using System.Collections;  
    
    public class RayDemo02 : MonoBehaviour {  
        Ray ray;  
        RaycastHit hit;  
        // 创建射线到屏幕上的参考点,像素坐标  
        Vector3 position = new Vector3(Screen.width/2.0f, Screen.height/2.0f, 0.0f);  
    
        void Update () {  
            // 射线沿着屏幕x轴从左向右循环扫描  
            position.x = position.x >= Screen.width ? 0.0f : position.x + 1.0f;  
            // 生成射线  
            ray = Camera.main.ScreenPointToRay(position);  
            if(Physics.Raycast(ray, out hit, 100.0f))  
            {  
                // 如果与物体发生碰撞,在Scene视图中绘制射线  
                Debug.DrawLine(ray.origin, hit.point, Color.green);  
                // 打印射线检测到的物体的名称  
                Debug.Log("射线检测到的物体名称: " + hit.transform.name);  
            }  
        }  
    }

    在这段代码中,首先声明了一个变量position,用于记录射线到屏幕上的实际交点的像素坐标,然后在Update方法中更改position的x分量值,使得射线从屏幕左方向右方不断循环扫描,接着调用方法ScreenPointToRay生成射线ray,最后绘制射线和打印射线探测到的物体的名称。运行程序后,如图3所示,在Scene视图中可以看到我们绘制的射线正在场景中扫描,图4是在控制台下打印输出射线探测到的物体名称。


    图3 使用ScreenPointToRay方法发射射线.jpg

    图4 控制台中输出的碰撞检测信息.jpg

    public Ray ViewportPointToRay(Vector3 position);
    参数说明:
    position为屏幕上的一个参考点坐标(坐标已单位化处理)。
    返回值说明:返回射向position参考点的射线。当发射的射线未碰撞到物体时,碰撞点hit.point的值为(0,0,0)。

    ViewportPointToRay方法从摄像机的近视口nearClip向屏幕上的一点position发射射线。Position用单位化比例值的方式表示射线到屏幕上的位置。当参考点position的x分量或y分量从0增长到1时,射线将从屏幕的一边移动到另一边。由于position在屏幕上,因此z分量始终为0。

    下面我们用一段程序示例说明如何利用ViewportPointToRay来发射一条指向屏幕上的某点来进行定向检测碰撞体。在场景中创建一个Cube位于摄像机的正前方,将下面的脚本RayDemo03.cs挂载到摄像机上。

    using UnityEngine;  
    using System.Collections;  
    
    public class RayDemo03 : MonoBehaviour {  
        Ray ray;  
        RaycastHit hit;  
        // 创建射线到屏幕上的参考点,单位化坐标  
        Vector3 position = new Vector3(0.5f, 0.5f, 0.0f);  
        void Update () {  
            // 射线沿着屏幕x轴从左向右循环扫描  
            position.x = position.x >= 1.0f ? 0.0f : position.x + 0.002f;  
            // 生成射线  
            ray = Camera.main.ViewportPointToRay(position);  
            if(Physics.Raycast(ray, out hit, 100.0f))  
            {  
                // 如果与物体发生碰撞,在Scene视图中绘制射线  
                Debug.DrawLine(ray.origin, hit.point, Color.green);  
                // 打印射线检测到的物体的名称  
                Debug.Log("射线检测到的物体名称: " + hit.transform.name);  
            }  
        }  
    }

    在这段代码中,首先声明了一个变量position,用于记录射线到屏幕上的实际交点的像素坐标,然后在Update方法中更改position的x分量值,使得射线从屏幕左方向右方不断循环扫描,接着调用方法ViewportPointToRay生成射线ray,最后绘制射线和打印射线探测到的物体的名称。运行程序后,如图5所示,在Scene视图中可以看到我们绘制的射线正在场景中扫描,图6是在控制台下打印输出射线探测到的物体名称。


    图5 使用ViewportPointToRay方法发射射线.jpg

    图6 控制台中输出的碰撞检测信息.jpg

    利用二次发射射线的方式检测内部物体

    有的时候我们要检测的物体在其他物体的内部,并且这两个物体都具有碰撞器,用射线检测返回的是第一个物体的信息。在这种情况下,我们需要使用二次射线发射的做法,即以第一次射线碰撞的外层物体的碰撞点作为第二次射线发射的起点,沿原来方向发射射线,判断是否与内部物体发生碰撞。

    下面我们用一段代码示例来说明如何用二次发射射线来检测位于物体内部的目标。在场景中创建两个Cube,位于摄像机的正前方。在其中一个Cube的位置上创建一个Sphere,并设置它的大小为Cube的一半,这样Sphere就位于Cube的内部。将下面的脚本RayDemo04.cs挂载到摄像机上。

    using UnityEngine;  
    using System.Collections;  
    
    public class RayDemo04 : MonoBehaviour {  
            GameObject wrapper; // 外层物体  
            GameObject target; // 内层物体  
            string info = ""; // 碰撞检测信息  
    
            void Update () {  
    
            if(Input.GetMouseButton (0))  
            {  
                // 当鼠标左键按下时,向鼠标所在的屏幕位置发射一条射线  
          Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);  
                RaycastHit hitInfo;  
                if(Physics.Raycast(ray, out hitInfo))  
                {  
                    // 当射线与物体发生碰撞时,在场景视图中绘制射线  
                    Debug.DrawLine(ray.origin, hitInfo.point, Color.red);  
                    // 获得第一次碰撞的外层物体对象  
                    wrapper = hitInfo.collider.gameObject;  
                   // 以第一次的碰撞点为起点,沿原来的方向二次发射射线  
                   Ray ray2= new Ray(hitInfo.point, ray.direction);  
                   RaycastHit hitInfo2;  
                   if(Physics.Raycast(ray2, out hitInfo2))  
                   {  
                   // 当射线与内层物体碰撞时,在场景中绘制射线  
                   Debug.DrawLine(ray2.origin, ray2.direction, Color.green);  
                   // 获得内层物体对象  
                   target = hitInfo2.collider.gameObject;  
                   // 将外层物体的网格隐藏  
                   wrapper.GetComponent<MeshRenderer().enabled = false;  
                   // 设置碰撞信息  
                   info = "检测到物体: " + target.name + "坐标: " + target.transform.position;  
                    }  
                    else  
                    {  
                   // 如果二次发射的射线没有与内层物体碰撞  
                   // 显示外层物体的网格  
                   wrapper.GetComponent<MeshRenderer>().enabled = true;  
                   // 设置碰撞信息  
                   info = "检测到物体: " + wrapper.name + "坐标: " + wrapper.transform.position;  
                   }  
                }  
            }  
        }  
    
        void OnGUI(){  
            // 在屏幕上打印输出射线检测的信息  
            GUILayout.Label(info);  
        }  
    }

    在上面这段代码中我们使用左移位操作符<<来设置碰撞层的掩码layerMask。Unity 3D中共有32个层,对应使用一个32位整数的各个位来表示每个层级,当这个位为1时表示使用这个层,为0时表示不使用这个层。

    LayerMask.NameToLayer这个API是返回我们使用自定义命名所定义的层的层索引,注意从0开始。当我们使用左移位操作设置层次掩码时,对应的自定义层级是n我们就将1左移n位,这样射线就只在layerMask指定的层次上进行碰撞检测。可供使用的自定义的层级从第8层开始,我们将8~10层分别命名为Capsule、Sphere和Cube,并将Capsule、Shpere和Cube三个物体的layer分别设置为对应的层次。一开始我们将所有物体设置为透明不可见。当按下鼠标左键发射射线时,返回射线方向上所有碰撞的物体信息,将获取到的物体对象,全部设置为半透明可见。点击按钮可以切换检测碰撞的层次。

    运行代码,如图9、图10所示,当切换不同的按钮控制射线在不同的层次上检测碰撞,显示的物体也便不同。


    图9 仅显示Cube层时进行的射线碰撞检测.jpg

    图10 显示所有层时进行的射线碰撞检测.jpg

    当然还有很多的关于射线使用的API不能一一赘述,这篇只是做一个简单的梳理,更多的API例如SphereCast、LineCast的具体用法可以查阅官方文档。



    文/Orpheus(简书作者)
    原文链接:http://www.jianshu.com/p/d6d3d7bf5151
    著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。
    展开全文
  • 由于unity自带的碰撞组件特别耗费性能,网上的unity物体碰撞的c#代码实现比较少,没有适合的,只能自己写一个来用: 立方体: using System; using System.Collections.Generic; using UnityEngine; namespace ...

    由于unity自带的碰撞组件特别耗费性能,网上的unity物体碰撞的c#代码实现比较少,没有适合的,只能自己写一个来用:
    立方体:

    using System;
    using System.Collections.Generic;
    using UnityEngine;
    
    namespace Assets
    {
        class Class1 : MonoBehaviour
        {
            List<Action> listAction = new List<Action>();
            //用来检测碰撞的间隔时间(可以直接把检测放入update()中,不过100毫秒的定时器效果上也能实现)
            System.Timers.Timer timer = new System.Timers.Timer();
            //原坐标
            Vector3 oldPoint;
            //要移动的坐标
            Vector3 point;
            //0:待机;1:移动
            int currentState = 0;
            //是否可以移动
            bool canMove = true;
    
            // Use this for initialization
            void Start()
            {
                oldPoint = transform.position;
                timer.Interval = 100;
                timer.Enabled = true;
                timer.Elapsed += (a, b) => isMove(point);
            }
    
            // Update is called once per frame
            void Update()
            {
                foreach (Action a in listAction) {
                    a();
                }
                listAction.Clear();
                point = transform.position;
                if (currentState == 1) {
                    if (checkCollision()) {
                        canMove = false;
                    }
                }
            }
    
            void isMove(Vector3 position) {
                if (oldPoint != position)
                {
                    if (!canMove)
                    {
                        listAction.Add(new Action(()=> gameObject.transform.position = oldPoint));
                        canMove = true;
                    }
                    else {
                        currentState = 1;
                        oldPoint = position;
                    }
                }
                else {
                    currentState = 0;
                }
            }
    
            bool checkCollision() {
                Vector3 zzPoint = gameObject.transform.position;
                Vector3 zzScale = gameObject.transform.localScale;
                //另一物体坐标信息
                GameObject dm = GameObject.Find("Cube (1)");
                Vector3 dmPoint = dm.transform.position;
                Vector3 dmScale = dm.transform.localScale;
    
                //坐标检测(当两个物体的x、y、z方向间距都小于两个物体在该方向上的长度)
                if ((Math.Abs(zzPoint.x - dmPoint.x) <= zzScale.x / 2 + dmScale.x / 2) &&
                    (Math.Abs(zzPoint.y - dmPoint.y) <= zzScale.y / 2 + dmScale.y / 2) &&
                    (Math.Abs(zzPoint.z - dmPoint.z) <= zzScale.z / 2 + dmScale.z / 2))
                {
                    return true;
                }
                return false;
            }
        }
    }
    

    球体:

    using System;
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class sphereCollision : MonoBehaviour {
    
        List<Action> listAction = new List<Action>();
        //用来检测碰撞的间隔时间(可以直接把检测放入update()中,不过100毫秒的定时器效果上也能实现)
        System.Timers.Timer timer = new System.Timers.Timer();
        //原坐标
        Vector3 oldPoint;
        //要移动的坐标
        Vector3 point;
        //0:待机;1:移动
        int currentState = 0;
        //是否可以移动
        bool canMove = true;
    
        // Use this for initialization
        void Start()
        {
            oldPoint = transform.position;
            timer.Interval = 100;
            timer.Enabled = true;
            timer.Elapsed += (a, b) => isMove(point);
        }
    
        // Update is called once per frame
        void Update()
        {
            foreach (Action a in listAction)
            {
                a();
            }
            listAction.Clear();
            point = transform.position;
            if (currentState == 1)
            {
                if (sphereCheckCollision())
                {
                    canMove = false;
                }
            }
        }
    
        void isMove(Vector3 position)
        {
            if (oldPoint != position)
            {
                if (!canMove)
                {
                    listAction.Add(new Action(() => gameObject.transform.position = oldPoint));
                    canMove = true;
                }
                else
                {
                    currentState = 1;
                    oldPoint = position;
                }
            }
            else
            {
                currentState = 0;
            }
        }
    
        bool sphereCheckCollision()
        {
            Vector3 zzPoint = gameObject.transform.position;
            Vector3 zzScale = gameObject.transform.localScale;
            //另一物体坐标信息
            GameObject dm = GameObject.Find("Sphere (1)");
            Vector3 dmPoint = dm.transform.position;
            Vector3 dmScale = dm.transform.localScale;
    
            //坐标检测(当两个圆相切时,圆心距离为r1+r2,两个圆心在x、y、z上的距离差为x1、x2、x3,用三角函数计算时至少计算两个维度的距离差才能和圆心距进行比较)
            if ((Math.Sqrt(Math.Pow(Math.Abs(zzPoint.x - dmPoint.x), 2) + Math.Pow(Math.Abs(zzPoint.y - dmPoint.y), 2)) <= zzScale.x / 2 + dmScale.x / 2) &&
                (Math.Sqrt(Math.Pow(Math.Abs(zzPoint.x - dmPoint.x), 2) + Math.Pow(Math.Abs(zzPoint.z - dmPoint.z), 2)) <= zzScale.x / 2 + dmScale.x / 2) &&
                (Math.Sqrt(Math.Pow(Math.Abs(zzPoint.y - dmPoint.y), 2) + Math.Pow(Math.Abs(zzPoint.z - dmPoint.z), 2)) <= zzScale.x / 2 + dmScale.x / 2))
            {
                return true;
            }
            return false;
        }
    
    }
    

    转载于:https://www.cnblogs.com/xiaoguangit/p/11282077.html

    展开全文
  • 需求:当立方体Cube碰到地面Plane的时候,输出碰撞物体的名称,则表述检测立方体碰撞了地面。 过程: 1.搭建一个简单的场景。 在新的工程中选择File->new Scene创建新的场景。 然后在该场景中添加地板...

    转载出处:http://blog.csdn.net/pleasecallmewhy/article/details/8289880

    需求:当立方体Cube碰到地面Plane的时候,输出碰撞物体的名称,则表述检测到立方体碰撞了地面。

    过程:

    1.搭建一个简单的场景。

    在新的工程中选择File->new Scene创建新的场景。

    然后在该场景中添加地板:GameObject->Create Other->Plain,

    以及正方体:GameObject->Create Other->Cube。

    给正方体添加刚体:Component->Physics->Rigidbody。

    添加后可以设置刚体属性。

    在Project处右击,选择Import Package->Physic Matarials。

    引入完成后可以直接把材质拖动到Hierachy窗口的组件中。

    bouncy:弹力十足的蹦蹦跳跳型。

    ice:像冰块一样碰撞。

    metal:像金属一样碰撞。

    rubber:像橡胶一样碰撞。

    wood:像木头一样碰撞。

    然后在“Hierarchie”面板中单击表示地板的组件,然后在Inspector中给它命名为“Ground”

    然后调整他们的位置大约像这样:



    2.创建脚本文件添加监听。


    选择Assets->Create->Javascript,创建JS文件并且重命名为“Collision”

    在Project窗口中双击它,Unity会启动Monodevelop来编辑js文件。
    清除里面默认创建的代码。写上。

    [javascript] view plaincopy
    1. function OnCollisionEnter(obj:Collision)  
    2. {  
    3.     Debug.Log("Collider:"+obj.collider.name+" gameObject:"+obj.gameObject.name);  
    4. }  


    onCollisionEnter函数解释:这个函数是在被绑定的物体与其他物体发生碰撞的时候被调用。

    obj参数解释:被撞的物体参数,类型是Collision,在本例中就是“Ground”。

    携带变量gameObject,是我们碰撞的物体。

    3、将脚本文件拖到立方体上实现绑定

    在"Project"面板中选中collision.js脚本,按住鼠标左键不放,直接拖入“Hierarchie”面板中,放到Ground上,松开鼠标即完成绑定。可以在右边的Inspetor面板查看相关内容。


    现在可以运行该程序了。

    运行后在界面左下角会输出:

            Collider:Cube gameObject:Cube

    至此一个简单的碰撞检测便完成了。

    展开全文
  • Unity3D-游戏中的技能碰撞检测 在游戏战斗中,我们会用到各种各样的碰撞检测,来判断是否打中了目标 比如扇形检测/圆形检测   还有矩形检测,王者荣耀里后羿的大招就是一个很长的矩形碰撞   ...
  • 在这章内容里,我们来看看在unity3d中是如何完成简单的碰撞检测的。描述如下:当立方体碰到地面,输出被立方体碰撞的地面的name“地板”,则表述检测到立方体碰撞了地面。 第一步 搭建场景。  如何搭建场景,...
  • 在这章内容里,我们来看看在unity3d中是如何完成简单的碰撞检测的。描述如下:当立方体碰到地面,输出被立方体碰撞的地面的name“地板”,则表述检测到立方体碰撞了地面。 第一步 搭建场景。  如何搭建场景,...
  • 在“Project”面板中单击“Create”旁边的小三角,选择“javascript”创建一个名为“collision”的js文件。双击它,系统启动Monodevelop来编辑js文件。  清除里面默认创建的代码。写上。  function ...
  • unity3D Collider 碰撞

    2018-08-02 09:34:54
    unity3D Collider 碰撞碰撞器的种类: 1、盒碰撞器(Box Collider) 2、椭圆碰撞器(Sphere Collider) 3、胶囊碰撞器(Capsule Collider) 4、车轮碰撞器(Wheel Collider)专用于车辆 5、网格碰撞器(Mesh ...
  • 当立方体Cube碰撞到地面Plane的时候,输出碰撞物体的名称,则表述检测立方体碰撞了地面。 过程: 1、搭建一个简单的场景 a. 在新建的工程中选择File->newScene来创建新的场景。 b. 然后在该场景中...
  • 在这章内容里,我们来看看在unity3d中是如何完成简单的碰撞检测的。描述如下:当立方体碰到地面,输出被立方体碰撞的地面的name“地板”,则表述检测到立方体碰撞了地面。 第一步 搭建场景。 如何搭建场景,只要...
  • Box Collider(盒碰撞器)——立方体 Sphere Collider(球碰撞器)——球体 Capsule Collider(胶囊碰撞器)——胶囊体 Mesh Collider(网格碰撞器)——从物体的网格创建一个碰撞器,不能与其他网格...
  • 当立方体Cube碰到地面Plane的时候,输出碰撞物体的名称,则表述检测立方体碰撞了地面。 过程: 1.搭建一个简单的场景。 在新的工程中选择File->new Scene创建新的场景。 然后在该场景中添加地板:...
  • // _____ _____ // | | | | // | x==|======|==x | 是错误的 // |_____| |_____| // // _____ _____ // | | | | // | |x====x| | 正确的 // ...
  • Unity碰撞体组件

    2019-10-01 15:29:44
    3D物理组件中碰撞体组件添加与设置 碰撞体是物理组件中的一类,3D物理组件和2D物理组件有独特的碰撞体组件,它要与刚体一起添加到游戏对象上才能触发碰撞。如果两个刚体相互撞在一起,除非两个对象有碰撞体时物理...
1 2 3 4 5 ... 20
收藏数 450
精华内容 180
关键字:

unity3d 立方体碰撞检测