当前位置: 代码迷 >> 综合 >> 【Unity】Physics.Raycast和Ray
  详细解决方案

【Unity】Physics.Raycast和Ray

热度:53   发布时间:2023-12-13 10:12:29.0

在游戏中,我们常常要用到鼠标来控制物体的移动或是鼠标拾取某个物体。还有射击游戏里,子弹打中靶子……这些都需要Physics.Raycast和ray。可见他们的重要性。

首先说说射线:

射线是3D世界中一个点向一个方向发射的一条无终点的线。在发射的轨迹中,一旦与其他物体发生碰撞,它就会停止。

在API文档中Ray是一个结构体【Struct】

namespace UnityEngine
{//// 摘要://     Representation of rays.public struct Ray{//// 摘要://     Creates a ray starting at origin along direction.//// 参数://   origin:////   direction:public Ray(Vector3 origin, Vector3 direction);//// 摘要://     The origin point of the ray.public Vector3 origin { get; set; }//// 摘要://     The direction of the ray.public Vector3 direction { get; set; }//// 摘要://     Returns a point at distance units along the ray.//// 参数://   distance:public Vector3 GetPoint(float distance);//// 摘要://     Returns a nicely formatted string for this ray.//// 参数://   format:public override string ToString();//// 摘要://     Returns a nicely formatted string for this ray.//// 参数://   format:public string ToString(string format);}
}

举个例子吧。(下面会一一讲解代码)

//用鼠标拾取物体

鼠标碰到cube就会移动到另一个plane中。

这里除了Ray还有Physics.Raycast,这两者密不可分,下面 一 一阐述

刚刚接触ray的时候感觉
 Ray ray =Camera.main.ScreenPointToRay(Input.mousePosition);

有点不理解,只是记下来这句可以从摄像机发出一条射线,

那么这条射线的源点在哪,又是沿什么方向呢?

文档中说:产生的射线是在世界空间中,从相机的近裁剪面开始并穿过屏幕position(x,y)像素坐标(position.z被忽略)。

那近裁面和屏幕是什么关系呢?是无限接近吗?不知道啊…..~~~~
看下图:

那么为什么要把鼠标位置转化为屏幕位置呢? 因为单位不一样;屏幕空间点用像素定义,屏幕的左下为(0,0);右上是(PixelWidth,pixelHeight).Z的位置是以世界单位衡量的到相机的距离。是像素坐标。而摄像机的Vector3则是世界坐标,所以需要把屏幕上的点转化为世界坐标,ScreenPointToRay()函数可以把屏幕像素坐标变成一条射线。

下面说说Physics.Raycast()

API文档中只给出这几个方法:

public static bool Raycast(Ray ray, RaycastHit hitInfo, float distance, int layerMask);public static bool Raycast(Ray ray, float distance, int layerMask);public static bool Raycast(Vector3 origin, Vector3 direction, float distance, int layerMask);public static bool Raycast(Vector3 origin, Vector3 direction, RaycastHit , float distance ,int layerMask );

但是我在VS里却可以找到更多的方法(经常看到别人只用到了两个变量,特意查了一下),如下图:

不过我个人觉得还是用给的4个函数好点,因为用4个参数可以很容易看出你的意图,即代码的可读性会变高。

这里说下
public static bool Raycast(Ray ray, RaycastHit hitInfo, float distance, int layerMask);
其他的都差不多;

Ray ray是射线;RaycastHit hitInfo是碰撞信息;float distance是碰撞距离;int
layerMask是碰撞的层

RaycastHit hitInfo是用来记录从raycast函数中得到的信息反馈。(out是C#关键字)。上面用拾取物体的例子先是申明了一个RaycastHit类型的hit变量,在Physics.Raycast()方法后,hit这个变量就携带了射线碰撞到那个物体的一些信息(这里碰到的是方块cube)。

这包括哪些信息呢?如图:

而这里就用hit得到了transform信息,有了cube的transform,我们不就可以控制它的移动了吗。


也说一下int layerMask吧。

可以看到是int类型,我们之前申明并初始化了targetMask =
LayerMask.GetMask(“target”);【这个方法在圣典的中文API中貌似没有】

LayerMask.GetMask()方法就是把target层用返回一个对应的整数。

这里一定要给cube给自己单独定义一个layer层,否则射线可能击中好多个物体,那样就不对了。

Vector3 offset = new Vector3(15, 0, 0);//设置cube要移动的距离;hit.transform.position = hit.transform.position + offset;//移动cube;
Physics.Raycast(ray, out rayhit, 100f, target)

总的来说,这句话的意思是:从摄像机发射一条射线,射线的范围是100米,只和target层发生碰撞,碰撞后得到碰撞体的信息,并返回一个布尔值。

  相关解决方案