方法解析
原函数
public static bool Raycast (
Vector3 origin, //射线在世界坐标系中的起点。
Vector3 direction, //射线的方向
float maxDistance= Mathf.Infinity, //射线应检查碰撞的最大距离
int layerMask= DefaultRaycastLayers, //只检测选定层的碰撞
QueryTriggerInteraction queryTriggerInteraction=QueryTriggerInteraction.UseGlobal
//指定该查询是否应该命中碰撞体(参数QueryTriggerInteraction.Ignore指isTrigger打开时忽略物体)
);
因为origin和direction可以用Ray这种储存两个vector的变量,RaycastHit 用于从射线投射获取信息的结构,所以一般的写法为
private void FixedUpdate()
{
Ray ray = new Ray(transform.position, transform.forward);
RaycastHit hitInfo;
if(Physics.Raycast(ray, out hitInfo,10))
{
Debug.Log(hitInfo.collider.name);
Debug.DrawLine(transform.position,hitInfo.point,Color.green);
}
else
{
Debug.DrawLine(ray.origin,ray.origin + ray.direction * 100,Color.red);
}
}
public static RaycastHit[] RaycastAll (Ray ray, float maxDistance= Mathf.Infinity, int layerMask= DefaultRaycastLayers, QueryTriggerInteraction queryTriggerInteraction= QueryTriggerInteraction.UseGlobal);
RaycastAll会检测所有射线检测到的结果并且返回一个结果的数组
ray = new Ray(transform.position, transform.forward);
RaycastHit[] hitsInfo;
hitsInfo = Physics.RaycastAll(ray, maxSize, layerMask);
if (hitsInfo.Length != 0)
{
Debug.DrawLine(ray.origin,ray.origin + ray.direction * 10,Color.red);
}
else
{
Debug.DrawLine(ray.origin,ray.origin + ray.direction * 10,Color.green);
}
foreach (var info in hitsInfo)
{
Debug.Log(info.collider.gameObject.name);
info.collider.gameObject.GetComponent<Renderer>().material = highlightM;
}
方法作用
向场景中的所有碰撞体投射一条射线,该射线起点为 /origin/,朝向 /direction/,长度为 /maxDistance/。您可以选择提供一个 LayerMask,以过滤掉不想生成与其碰撞的碰撞体。
您可以通过指定 queryTriggerInteraction 来控制是让触发碰撞体生成命中效果,还是使用全局 Physics.queriesHitTriggers 设置。
注意事项
- 对于射线投射起点位于碰撞体内的情况,Raycast 不会检测到碰撞体。
- 对于射线检测官方建议在Fixed Update中使用
- 射线检测的对象必须要有Collider组件,且isTrigger的开关不影响射线检测的结果(参数QueryTriggerInteraction与之相关)
案例
Camera.main.ScreenPointToRay(Input.mousePosition)
将屏幕上的像素坐标(即鼠标在屏幕坐标上的具体位置),通过ScreenPointToRay()方法,传入并返回一条在世界坐标下从相机Camera的近裁面,出发穿过屏幕上的像素点的射线,即将鼠标的位置信息从屏幕坐标系转换到Ray射线类型
鼠标位置在平面上生成物体
public class PlaceMement : MonoBehaviour
{
public LayerMask planemask; //layer标签用于射线只检测plane
public GameObject tree; //生成的物体
private void FixedUpdate()
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
//调整在平面上的位置
if (Physics.Raycast(ray, out RaycastHit hitInfo, Mathf.Infinity,planemask))
{
tree.transform.position = hitInfo.point;
tree.transform.rotation = Quaternion.FromToRotation(Vector3.up, hitInfo.normal);//依靠平面的法线做变换角度
}
if (Input.GetMouseButtonDown(0))
{
Instantiate(tree, hitInfo.point, Quaternion.FromToRotation(Vector3.up, hitInfo.normal));
}
}
}

移动发射光束
using UnityEngine;
public class Enemy : MonoBehaviour
{
[SerializeField] private float moveSpeed;
public Transform target;
[SerializeField] private Transform A, B;
public Transform firePoint;
[SerializeField] private float maxDist;
public LayerMask layer;
[Header("Laser")] private LineRenderer lineRender;
[SerializeField] private Gradient redColor, greenColor;
private void Start()
{
target = B;
Physics2D.queriesStartInColliders = false;
lineRender = GetComponentInChildren<LineRenderer>();
}
void Update()
{
Move();
Detect();
}
void Move()
{
if (Vector2.Distance(transform.position, A.position) <= 0.1)
{
target = B;
}
if (Vector2.Distance(transform.position, B.position) <= 0.1)
{
target = A;
}
transform.position = Vector2.MoveTowards(transform.position, target.position, moveSpeed * Time.deltaTime);
}
void Detect()
{
RaycastHit2D hitInfo;
hitInfo = Physics2D.Raycast(firePoint.position, -transform.right * 5, maxDist,layer);
if (hitInfo.collider != null)
{
if (hitInfo.collider.tag == "Block")
{
Debug.Log(hitInfo.collider.gameObject.name);
Debug.DrawLine(firePoint.position,hitInfo.point,Color.red);
lineRender.SetPosition(1,hitInfo.point);
lineRender.colorGradient = greenColor;
}
lineRender.SetPosition(0,firePoint.position);//linerender初始点
}
}
}