射线(ray)是指由线段的一端无线延长所形成的直线。


射线多用于检测 在 Unity 中描述一个射线一个点加个方向,在与其他物体发生碰撞时将停止发射。

  • Ray 射线类。

    创建一个射线:
using UnityEngine;
using System.Collections;

namespace GaoSan{
    public class RayTest : MonoBehaviour
    {
        public Transform ori;//起点位置
        public Transform des;//终点位置
        void Update ()
        {
            // (des.position - ori.position) 终点位置减去 起点位置 等于方向向量
            Ray ray = new Ray(ori.position, (des.position - ori.position));
            // 输出检测
            print(ray);
        }

RayTest 脚本拖到摄像机中。在 Hierarchy 面板上创建两个 Cube ,Transform组建Reset ,将这两个Cube分别表示 ori 和 des,des Z轴改为10点击运行。

unity射线消耗 unity3d射线_世界坐标


为什么输出的 Dir :(0.0, 0.0, 1.0)呢?

当我们传入一个方向数值时Unity会自动将它转换成一个单位向量

  • 射线看不到,在 Debug 中有两种方法可以让开发者在 Scene 视图中观察到射线。
    1. Debug.DrawLine(Vector3 start, Vector3 end);此方法有四个重载。(传入的是两个顶点)
    2. Debug.DrawRay(Vector3 start, Vector3 dir);此方法有四个重载。(传入的是一个顶点和一个带长度的方向)

可以在 RayTest 代码中继续写:

//参数:ray.origin 射线起点;ray.direction * 10 带长度的方向
   Debug.DrawRay(ray.origin, ray.direction * 10);

运行结果:

unity射线消耗 unity3d射线_unity3d_02



射线检测

Physics.Raycast(有16个重载)

射线检测及投射一条射线在碰到物体时反馈一些信息。检测碰撞是基于 Collider ,射线检测是由物理发射出去的。

1. bool Physics.Raycast(Vector3 origin, Vector3 direction, float distance, int layerMask)

在场景中投下可与所有碰撞器碰撞的一条光线。返回值 bool 类型

2. bool Physics.Raycast(Ray ray, Vector3 direction, RaycastHit out hit, float distance, int layerMask)

在场景中投下可与所有碰撞器碰撞的一条光线。返回 (RaycastHit) 射到的物体信息(前提是返回 true)

3. bool Physics.Raycast(Ray ray, out RaycastHit hitInfo, float maxDistance, LayerMask.GetMask(params string[] layerNames))

在场景中投下可与指定层的所有碰撞器碰撞的一条射线。LayerMask 结构体;GetMask()指定层的名称。

Parameters:(参数)

1. origin :——- 在世界坐标,射线的起始点。
2. direction :— 射线的方向。
3. distance : —-射线的长度。
4. hitInfo : ——如果返回 ture ,hitInfo 将包含碰撞器碰撞的信息 。
5. layerMask : –只选定 LayerMask 层内的碰撞器,其它层内碰撞器忽略。
out关键字传入一个空的碰撞信息类,然后碰撞后赋值。可以得到碰撞物体的信息。

小知识

1. Camera.main.ScreenPointToRay(Vector3 pos);

创建一条以摄像机的近裁剪面上的一点为起点,经过鼠标对应世界坐标的射线。

2.Camera.main.ScreenToWorldPoint(Vector3 position );

将某一个屏幕坐标点转换成摄像机看见的世界坐标位置。传入的Vector3类型参数的z值指定了世界坐标距离摄像机的距离。

3.Camera.main.ViewportPointToRay(Vector3 pos);

创建一条以摄像机的近裁剪面上的一点为起点,到摄像机视口之内指定的一个点。

例题

在场景的视野中有一些有碰撞器的物体,当鼠标放在物体表面上时,按下鼠标左键,改变该物体的颜色。

using UnityEngine;
using System.Collections;

namespace GaoSan{
    public class RaycastTest : MonoBehaviour
    {
        void Update ()
        {
            // 创建一条以摄像机的近裁剪面上的一点为起点,经过鼠标对应世界坐标的射线。
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            RaycastHit hit;
            if (Input.GetMouseButtonDown(0))
            {
                if (Physics.Raycast(ray,out hit,100,1<<9))
                {
                    hit.transform.GetComponent<MeshRenderer>().material.color = Color.red;
                }
            }
        }
    }
}

当点击鼠标左键时,从摄像机的近裁剪面上的一点为起点,经过鼠标对应世界坐标的射线。射线长度为100,射线碰撞层级为9,(1<<9表示开启Layer9而0<<9表示关闭Layer9)其它层级忽略。(也就是说只有物体处于层级9才能被射线检测到。)

unity射线消耗 unity3d射线_Unity基础知识_03


创建三个物体,新建三个层级分别为8,9,10。把Plane、Cube和Sphere三个物体层级分别设置为8,9、10。脚本放到摄像机上点击运行,分别单机这三个物体,会发现只有Cube 会被改变颜色。

unity射线消耗 unity3d射线_unity3d_04