내 연락처 정보
우편메소피아@프로톤메일.com
2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
광선 감지는 이름에 따라 광선을 사용하여 물체/여러 물체에 닿는지 여부를 감지합니다.
방사선 촬영 테스트는 두 부분으로 구성됩니다. 광선그리고발각
광선은 일상생활의 여러 곳에서 볼 수 있습니다.플래시,ppt 레이저 페이지 터닝 펜, 청우 시대 중반물벼룩
광선은 시작점, 방향, 거리로 구성됩니다. origin
, direction
그리고distance
물리학에서는 광선의 거리가 무한하므로 물리적 광선에는 하나의 시작점과 하나의 방향만 있습니다. 게임에서는 광선의 최대 거리도 시스템에 의해 제한됩니다. 1000.0미터 다음은 Ray에 대한 설명입니다.
Unity에서 Ray는 구조 볼륨의 기본 멤버입니다.origin
, direction
그리고GetPoint
즉, 광선을 따라 일정 거리에 있는 점의 시작점, 방향 및 위치는 다음과 같습니다. Unity의 Ray에 대한 코드입니다.
using System;
namespace UnityEngine
{
public struct Ray : IFormattable
{
public Ray(Vector3 origin, Vector3 direction);
public Vector3 origin { get; set; } // 起点(向量)
public Vector3 direction { get; set; }// 方向(向量)
public Vector3 GetPoint(float distance);// 沿着射线一定距离的点(向量)
public override string ToString();
public string ToString(string format);
public string ToString(string format, IFormatProvider formatProvider);
}
}
위의 코드에 따르면 Ray 생성자를 사용하여 광선을 직접 생성할 수 있음을 알 수 있습니다. 예를 들면 다음과 같습니다.
Ray ray = new Ray(Vector3.zero, Vector3.forward); // 射线的起点 + 射线的方向
위의 코드에 따르면 광선의 시작점은 Unity의 월드 좌표 원점(0,0,0)이고, 광선의 방향은 월드 좌표의 정방향임을 알 수 있습니다.
실제로는 레이저 포인터와 손전등을 볼 수 있지만 Unity의 광선은 보이지 않습니다. 따라서 광선을 표시하려면 다음 방법을 사용할 수 있습니다.
Debug.DrawRay()
디스플레이 레이LineRenderer
구성요소가 광선을 그립니다.단순히 광선을 구성하거나 표시하는 것은 손에 도구를 들고 도구 없이 작업하는 것과 같습니다.
물체 감지를 위해 광선을 사용하는 방법.
생각해 보세요. 일상 생활에서 레이저 포인터나 손전등은 벽에 밝은 점을 표시하거나 레이저 빛을 방출한 후 특정 장소를 비출 수 있습니다. 이는 벽이 상호 작용할 수 있음, 즉 광선이 충돌할 수 있음을 보여줍니다. 객체/ 객체가 감지되었습니다. Unity에서 다음 API를 사용하여 객체가 감지되었는지 확인하세요.
// 基础版API
public static bool Raycast(Ray ray);
public static bool Raycast(Vector3 origin, Vector3 direction, float maxDistance, int layerMask);
public static bool Raycast(Ray ray, out RaycastHit hitInfo);
public static bool Raycast(Ray ray, out RaycastHit hitInfo, float maxDistance);
// 常用版API
public static bool Raycast(Ray ray, out RaycastHit hitInfo, float maxDistance, int layerMask);
public static bool Raycast(Ray ray, float maxDistance);
광선 감지를 사용하려면 다음을 사용해야 합니다.Physics
물리학과 관련된 정적 함수가 포함된 라이브러리
위의 오버로드된 함수를 보면 어떤 것을 사용해야 할지 모르는 경우가 많습니다. 실제로 매개변수가 많은 경우에는 필요에 따라 서로 다른 오버로드된 매개변수를 사용합니다.
먼저 API의 기본 버전을 살펴보세요. public static bool Raycast(Ray ray);
반환 값에 따라 광선이 객체에 닿는지 여부를 알 수 있으며, 닿지 않으면 false를 반환합니다.
다른 API의 광선 감지public static bool Raycast(Ray ray, out RaycastHit hitInfo);
매개변수가 하나 더 있습니다.hitInfo
hitInfo 매개변수는 광선에 맞은 객체의 정보 구조입니다. 구조가 상대적으로 크기 때문에 Unreal Engine에서 광선 감지에 맞은 객체의 결과와 동일합니다.FHitResult
)은 거시적 관점이나 실용적인 관점에서 보면 광선이 물체에 부딪힐 때 물체 자체에 대한 정보와 히트 포인트에 대한 정보를 얻을 수 있습니다.
객체의 이름, 객체의 transfrom 구성 요소, 객체의 태그 등 객체 정보를 얻는 것은 이해하기 쉽습니다.
히트 포인트 정보, 즉 광선이 객체에 닿는 지점(히트 포인트)의 정보를 얻습니다.정상(노멀), 법선, 점정점 색상…
다음은RaycastHit
구조 정보에는 일반적으로 사용되는 정보에 주석이 추가되어 있습니다.lightmapCoord
이는 렌더링에 사용되는 라이트 맵 좌표입니다.
namespace UnityEngine
{
public struct RaycastHit
{
public Collider collider { get; } // 碰撞器
public int colliderInstanceID { get; }
public Vector3 point { get; set; } // 击中的点(命中点)
public Vector3 normal { get; set; } // 命中点的法线
public Vector3 barycentricCoordinate { get; set; } // 重心坐标
public float distance { get; set; } // 命中点距离射线起点的距离
public int triangleIndex { get; }
public Vector2 textureCoord { get; }
public Vector2 textureCoord2 { get; }
public Transform transform { get; } // Transform组件
public Rigidbody rigidbody { get; } // 刚体组件
public ArticulationBody articulationBody { get; }
public Vector2 lightmapCoord { get; }
public Vector2 textureCoord1 { get; }
}
}
즉 말하자면HitInfo
우리가 부딪힌 물체에 대한 정보를 저장합니다. 이 정보를 사용하여 더 많은 작업을 수행할 수 있습니다.
유니티에서는layerMask
물리적 충돌, 광선 캐스팅, 광선 감지 및 기타 작업을 제어하는 데 사용되는 개체 레이어 선택 메커니즘입니다.설정으로layerMask
를 사용하면 이러한 작업에 어떤 레이어를 포함하거나 제외할지 지정할 수 있습니다.
일반적으로 사용되는 광선 감지 API로 계속 돌아가기 public static bool Raycast(Ray ray, out RaycastHit hitInfo, float maxDistance, int layerMask);
가운데.
위 API에서 maxDistance가 광선의 거리라는 것은 말할 필요도 없습니다. 시스템에는 최대값도 다음과 같이 설정되어 있습니다.Mathf.Infinity
. 이 API에는 레이어 마스크인 layerMask 매개변수도 있습니다.
Unity에서 게임오브젝트를 구별하려면 태그를 추가하는 것, 즉 태그를 추가함으로써 게임오브젝트를 구별할 수 있습니다. 그러나 태그는 수동으로 태그 이름을 입력해야 하고, 손으로 입력할 때 실수하기 쉽습니다. 동시에 문자열이기 때문에 Unity 하단의 계산 속도가 약간 느립니다. Unity에는 레이어라는 개념이 있습니다.
Unity의 layerMask에는 32개의 레이어가 포함되어 있으며 그 중 일부는 이미 시스템에서 사용됩니다.Player
층, UI
레이어 시스템에서 사용하지 않는 레이어가 여전히 많이 있습니다. 레이어를 추가한 다음 게임 개체에 아동 노동 레이어를 추가하여 분류할 수 있습니다.
레이어를 추가하는 방법은 개체의 검사기 패널에서 레이어를 클릭한 다음레이어 추가그게 전부입니다. 그런 다음 수정해야 하는 개체에 대한 레이어를 수동으로 지정합니다.
레이어를 수동으로 추가한 후 사용하는 방법입니다.
존재하다public static bool Raycast(Ray ray, out RaycastHit hitInfo, float maxDistance, int layerMask);
가운데layereMask
우리는 그것이int
그러나 정수 유형에서는 숫자를 직접 채울 수 없으며 채우기 규칙은 시프트 연산을 사용합니다.
레이어 마스크를 채우는 방법:
레이어 마스크 값 가져오기:
1 << LayerMask.NameToLayer("LayerName")
. 이는 이 레이어의 layerMask를 나타내는 정수 값을 반환합니다.여러 레이어 결합:
|
. 예를 들어,layerMask = LayerMask.GetMask("Layer1", "Layer2")
"Layer1" 및 "Layer2"를 포함하는 layerMask가 생성됩니다.레이어 제외:
^
특정 레이어를 제외하려면 예를 들어,layerMask = ~LayerMask.GetMask("ExcludeLayer")
。레이어 확인:
layerMask.value & (1 << gameObject.layer)
. 결과가 0이 아니면 객체가 레이어 마스크에 있음을 의미합니다.// 示例代码
// 创建一个包含Layer1和Layer2的layerMask
int layerMask = LayerMask.GetMask("Layer1", "Layer2");
// 排除Layer3
layerMask = ~LayerMask.GetMask("Layer3");
// 使用layerMask进行射线检测
RaycastHit hit;
if (Physics.Raycast(ray, out hit, maxDistance, layerMask))
{
// 处理射线击中的对象
}
다음은 hitInfo 매개변수 없이 또는 hitInfo 매개변수와 함께 hitInfo 매개변수를 사용하는 코드입니다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RayCast : MonoBehaviour
{
/
// 构建一条射线 : 射线产生的起始点 + 射线的方向.
private Ray ray1 = new Ray(Vector3.zero, Vector3.forward);
// 射线距离
private float rayDistance = 100.0f;
// 击中的判定结果
bool hitResult = false;
// 射线击中的物体
private RaycastHit hitInfo;
void Start()
{
// 不含有hitInfo的函数
bool result1 = Physics.Raycast(Vector3.zero + new Vector3(0,0,10), Vector3.forward, 1000.0f, 1 << LayerMask.NameToLayer("Default"), QueryTriggerInteraction.UseGlobal);
if (result1)
{
Debug.Log("射线击中物体");
}
// 含有hitInfo的函数
hitResult = Physics.Raycast(ray1, out hitInfo, rayDistance, 1 << LayerMask.NameToLayer("Default"), QueryTriggerInteraction.UseGlobal);
if (hitResult == true)
{
print(hitInfo.collider.name);
print(hitInfo.transform);
print(hitInfo.point);
}
}
}
광선 감지를 사용하여 회전하는 레이저 포인터를 구현합니다. 물체를 만나면 광선 길이가 줄어들어 광선을 그려야 합니다.
필요한 기술: 광선 감지 + 회전 + LineRender
다음은 코드입니다
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RotateRay : MonoBehaviour
{
// LinerRender组件
private LineRenderer lineRenderer = null;
// 构建一条射线 : 射线产生的起始点 + 射线的方向.
private Ray ray = new Ray(Vector3.zero, Vector3.forward);
// 射线距离
private float rayDistance = 1000.0f;
// 击中的判定结果
bool hitResult = false;
// 射线击中的物体
private RaycastHit hitInfo;
void Start()
{
// 添加线条绘制组件
lineRenderer = this.gameObject.AddComponent<LineRenderer>();
InitLineRenderer(lineRenderer);
// 设置射线的起点和方向
ray.origin = this.transform.position;
ray.direction = this.transform.forward;
}
// Update is called once per frame
void Update()
{
// 重新设置射线的位置
ray.origin = this.transform.position;
ray.direction = this.transform.forward;
// 旋转游戏对象 -- 每秒旋转60°
Quaternion quaternion = Quaternion.AngleAxis(60f * Time.deltaTime, this.transform.up);
this.transform.rotation *= quaternion;
// 判断击中的物体
hitResult = Physics.Raycast(ray, out hitInfo, rayDistance, 1 << LayerMask.NameToLayer("Default"), QueryTriggerInteraction.UseGlobal);
if (hitResult == true)
{
print(hitInfo.collider.name);
}
// 显示并更新射线
UpdateLineRendererByRay(lineRenderer, ray, hitResult,hitInfo, rayDistance);
}
/// <summary>
/// 初始化线条渲染组件
/// </summary>
void InitLineRenderer(LineRenderer lineRenderer)
{
// lineRenderer = this.gameObject.AddComponent<LineRenderer>();
lineRenderer.positionCount = 2;
lineRenderer.startWidth = 0.2f;
lineRenderer.endWidth = 0.2f;
lineRenderer.startColor = Color.red;
lineRenderer.endColor = Color.green;
}
/// <summary>
/// 击中物体的时候修改射线的长度
/// </summary>
/// <param name="lineRenderer">lineRenderer组件</param>
/// <param name="ray">射线</param>
/// <param name="hitResult">是否命中物体</param>
/// <param name="hitInfo">命中物体信息</param>
/// <param name="rayDistance">射线距离</param>
void UpdateLineRendererByRay(LineRenderer lineRenderer,Ray ray, bool hitResult, RaycastHit hitInfo, float rayDistance)
{
if (lineRenderer == null || lineRenderer.positionCount < 2)
{
Debug.Log("LineRender组件不可以使用");
return;
}
// 修改起点位置
lineRenderer.SetPosition(0, ray.origin);
// 修改终点位置
if (hitResult == true)
{
lineRenderer.SetPosition(1, hitInfo.point);
}
else
{
lineRenderer.SetPosition(1, ray.GetPoint(rayDistance));
}
}
}
최적화된 코드
using UnityEngine;
public class RotateRay : MonoBehaviour
{
private LineRenderer lineRenderer;
private Ray ray;
private float rayDistance = 1000.0f;
private RaycastHit hitInfo;
void Start()
{
lineRenderer = this.gameObject.AddComponent<LineRenderer>();
InitLineRenderer(lineRenderer);
ray = new Ray(Vector3.zero, Vector3.forward);
}
void Update()
{
UpdateRayPosition();
RotateObject();
PerformRaycast();
UpdateLineRenderer();
}
void InitLineRenderer(LineRenderer lineRenderer)
{
lineRenderer.positionCount = 2;
lineRenderer.startWidth = 0.2f;
lineRenderer.endWidth = 0.2f;
lineRenderer.startColor = Color.red;
lineRenderer.endColor = Color.green;
}
void UpdateRayPosition()
{
ray.origin = this.transform.position;
ray.direction = this.transform.forward;
}
void RotateObject()
{
Quaternion rotation = Quaternion.AngleAxis(60f * Time.deltaTime, this.transform.up);
this.transform.rotation *= rotation;
}
void PerformRaycast()
{
int layerMask = 1 << LayerMask.NameToLayer("Default");
hitInfo = new RaycastHit(); // 初始化hitInfo,避免未击中时的错误
Physics.Raycast(ray, out hitInfo, rayDistance, layerMask, QueryTriggerInteraction.UseGlobal);
}
void UpdateLineRenderer()
{
if (lineRenderer == null || lineRenderer.positionCount < 2)
{
Debug.LogError("LineRenderer component is not available or not properly initialized.");
return;
}
lineRenderer.SetPosition(0, ray.origin);
lineRenderer.SetPosition(1, hitInfo.collider != null ? hitInfo.point : ray.GetPoint(rayDistance));
}
}
렌더링은 다음과 같습니다
using UnityEngine;
public class CameraRay: MonoBehaviour
{
// 射线距离
private float rayDistance = 1000.0f;
// 特效Prefab--外部可以自定义特效
public GameObject effectPrefab;
void Update()
{
if (Input.GetMouseButtonDown(0))
{
// 从摄像机发出一条射线
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hitInfo;
// 如果射线击中了指定层级的物体
if (Physics.Raycast(ray, out hitInfo, rayDistance, LayerMask.GetMask("Wall")))
{
// 生成特效 --格局法线来计算特效位置
GameObject effectObject = Instantiate(effectPrefab, hitInfo.point, Quaternion.LookRotation(hitInfo.normal));
// 销毁特效,参数为延迟时间
Destroy(effectObject, EffectPrefab.GetComponent<ParticleSystem>().main.duration);
}
}
}
}