Unity 射线检测碰撞

这次用案例讲解射线碰撞。我们要模仿,一个小物体快速碰撞一个大物体时的碰撞效果。新建一个3D工程,场景中新建一个cube位置是(0,0,500),给cube添加tag为cube。再新建一个Sphere,位置是(0,0,0);给Sphere添加刚体组件,取消重力。再添加脚本,名为SphereSpeed,并编辑:

using UnityEngine;
using System.Collections;

public class SphereSpeed : MonoBehaviour {
    public float speed = 10;   //定义球体 移动的速度

    // Use this for initialization

    void Start()
    {

    }

    // Update is called once per frame
    void Update () {
        transform.Translate(Vector3.forward * speed);

    }


    void OnCollisionEnter(Collision other)
    {
        if (other.collider.tag == "cube")
        {
            Debug.Log("碰撞到了cube");
        }
    }
}

这个代码很简单,大家应该能看懂,我就不解释了。
这里写图片描述
这里有一个小技巧去截这种图,就是先按下暂停按钮,然后按run,游戏就会在第一帧后暂停,然后点击暂停旁边的下一帧,就可以一帧一帧执行了。
但是大家有没有发现,这个时候,并没有打印出Log。这个好像是Unity自身的问题,但假如我们有正好需要这样的实现,又该怎么做呢?
这里有两个比较常用的方法。1:增加球体的碰撞体体积。2:使用射线检测碰撞。这里我们就采用第二种。修改脚本:

using UnityEngine;
using System.Collections;

public class SphereSpeed : MonoBehaviour {
    private Ray rays;  //声明一条射线
    // Use this for initialization

    void Start()
    {
        //以小球中心为起始点,前方为目标点创建一条射线
        rays = new Ray(transform.position, Vector3.forward);
    }
    // Update is called once per frame
    void Update () {
        if (Input.GetKeyDown(KeyCode.J))
        {
            //光线投射碰撞
            //用来获取从raycast函数中得到的信息
            RaycastHit hit;
            //发射一条射线,当光线投射与任何碰撞器交叉时为真,否则为假。
            if (Physics.Raycast(rays, out hit))
            {
                Debug.Log(hit.collider.name);
            }
        }
    }
}

现在运行游戏,就会有信息打印了。
这里写图片描述

但是假如现在cube前面有一个物体的话会怎么样呢?
射线是当碰撞到一个物体时就会消失,所以他会打印第一个碰到的物体的名字,那该怎么做呢?
既然这样,我们就让他只碰撞某一个物体就好了。Unity中使用层级关系来来解决这个问题。给cube添加一个Layer名字就叫做cube(随便取也行)。
这里写图片描述
我们规定射线只需要碰撞这一层的东西就行了。现在修改代码:

using UnityEngine;
using System.Collections;

public class SphereSpeed : MonoBehaviour {
    private Ray rays;  //声明一条射线
    public LayerMask mask;  //定义一个公共的层级
    //也可以这样写:

       // public LayerMask mask = 1 << 8;  打开第8的层
       // ~(1 << 8) 打开除了第10之外的层。

       // ~(1 << 0) 打开所有的层。

       // (1 << 8) | (1 << 8) 打开第10和第8的层。


    // Use this for initialization
    void Start()
    {
        //以小球中心为起始点,前方为目标点创建一条射线
        rays = new Ray(transform.position, Vector3.forward);
    }

    // Update is called once per frame
    void Update () {
        if (Input.GetKeyDown(KeyCode.K))
        {
            //光线投射碰撞
            //用来获取从raycast函数中得到的信息
            RaycastHit hit;

            //发射一条射线,当光线投射与任何碰撞器交叉时为真,否则为假。
            //600是射线的最大距离
            //mask就是我们选择的层
            if (Physics.Raycast(rays, out hit, 600, mask))
            {
                Debug.Log(hit.collider.name);
            }
        }

    }
}

然后再外面选择上刚刚给cube添加的层
这里写图片描述

现在运行游戏,按下键盘,就能看见只碰撞到了cube。
这里写图片描述

项目工程:http://pan.baidu.com/s/1jHWVwxC 密码:ditb

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页