2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
Säteentunnistus, nimen mukaan, käyttää sädettä havaitakseen osuuko se kohteeseen/useampaan esineeseen
Röntgentutkimus koostuu kahdesta osasta: SäteetjaHavaitseminen
Säteet näkyvät monissa paikoissa jokapäiväisessä elämässä, kutentaskulamppu,ppt lasersivun kääntävä kynä, keskellä Qingyu vuottakyklooppi
Säde koostuu aloituspisteestä, suunnasta ja etäisyydestä, nimittäin: origin
, direction
jadistance
Fysiikassa säteen etäisyys on ääretön, joten fysikaalisella säteellä on vain yksi lähtöpiste ja yksi suunta Pelissä säteen maksimietäisyys on myös järjestelmän rajoittama 1000,0 metriä Seuraava on kuvaus Säteestä.
Unityssa Ray on rakenne Rakennevolyymin perusjäsenet sisältävätorigin
, direction
jaGetPoint
Toisin sanoen pisteen aloituspiste, suunta ja sijainti tietyllä säteellä. Seuraava on Säteen koodi
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);
}
}
Yllä olevan koodin mukaan voidaan nähdä, että säde voidaan rakentaa suoraan käyttämällä Ray-konstruktoria, esim.
Ray ray = new Ray(Vector3.zero, Vector3.forward); // 射线的起点 + 射线的方向
Yllä olevan koodin mukaan voimme nähdä, että säteen aloituspiste on maailman koordinaattien origo yksikössä (0,0,0) ja säteen suunta on maailman koordinaattien eteenpäin suunta.
Todellisuudessa laserosoitin ja taskulamppu ovat näkyvissä, mutta Unityn säteet ovat näkymättömiä. Siksi, jos haluamme näyttää säteet, voimme käyttää seuraavia menetelmiä:
Debug.DrawRay()
näyttösädeLineRenderer
Komponentti vetää säteenPelkästään säteiden rakentamisella tai näyttämisellä ei ole merkitystä. Se vastaa työkalun pitämistä kädessä ja työskentelyä ilman työkalua.
Kuinka käyttää säteitä esineiden havaitsemiseen.
Ajattele sitä huolellisesti: jokapäiväisessä elämässämme laserosoittimemme tai taskulamppumme voivat näyttää valopisteitä seinällä tai valaista tietyn paikan laservalon lähettämisen jälkeen. Tämä osoittaa, että seinään voidaan vaikuttaa, toisin sanoen säteen kanssa objekti/ Objekti havaitaan Käytä seuraavaa API:ta Unityssa määrittääksesi, onko objekti havaittu.
// 基础版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);
Jotta voit käyttää säteentunnistusta, sinun on käytettäväPhysics
Kirjasto, joka sisältää staattisia fysiikkaan liittyviä toimintoja
Yllä olevia ylikuormitettuja toimintoja emme usein tiedä. Itse asiassa tarvitsemme vain perusparametreja.
Katso ensin API:n perusversio public static bool Raycast(Ray ray);
Palautusarvon mukaan voimme tietää osuuko säde kohteeseen. Jos se osuu, se palauttaa virheen.
Säteen tunnistus toisessa API:ssapublic static bool Raycast(Ray ray, out RaycastHit hitInfo);
Siinä on vielä yksi parametrihitInfo
HitInfo-parametri on säteen osuman kohteen tietorakenne Rakenne on suhteellisen suuri, mikä tarkoittaa, että se sisältää enemmän tietoa. Tämä on sama kuin säteen havaitseman kohteen tulos (.FHitResult
) ovat samanlaisia makronäkökulmasta tai käytännön näkökulmasta, kun säteen osuu kohteeseen, voimme saada tietoa itse kohteesta ja tietoa osumapisteestä.
Objektin tietojen saaminen on helppo ymmärtää: kuten kohteen nimi, objektin muunnoskomponentti, objektin tunniste...
Hanki tiedot osumapisteestä, eli tiedot pisteestä (osumapisteestä), jossa säde osuu kohteeseen: kuten pisteen koordinaatit,Normaali(normaali), normaalitaso, pistekärjen väri…
Seuraava onRaycastHit
Rakennetiedot, yleisesti käytettyihin on lisätty kommentteja On myös monia yleisesti käytettyjä ilman lisättyjä kommentteja, kutenlightmapCoord
Ne ovat kevyitä karttakoordinaatteja, joita käytetään renderöimiseen.
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; }
}
}
TarkoittaenHitInfo
Tallentaa osumamme kohteen tiedot, voimme käyttää näitä tietoja tehdäksemme enemmän asioita
Yhtenäisyydessä,layerMask
Se on objektikerroksen valintamekanismi, jota käytetään ohjaamaan fyysistä törmäystä, säteen valua, säteen havaitsemista ja muita toimintoja.asettamallalayerMask
, voit määrittää, mitkä tasot sisällytetään tai jätetään pois näistä toiminnoista.
Jatka takaisin yleisesti käytettyyn säteentunnistussovellusliittymään public static bool Raycast(Ray ray, out RaycastHit hitInfo, float maxDistance, int layerMask);
keskellä.
Yllä olevassa API:ssa on sanomattakin selvää, että maxDistance on säteen etäisyys Järjestelmässä on myös asetettu maksimiarvoMathf.Infinity
Tässä API:ssa on myös parametri layerMask, joka on kerrosmaski.
Peliobjektien erottamiseksi Unityssa voimme erottaa peliobjektit lisäämällä tunnisteita. Tunnisteet ovat kuitenkin hankalampia, ja virheitä on helppo kirjoittaa käsin. Samaan aikaan, koska se on merkkijono, Unityn alaosassa oleva laskentanopeus on hieman hitaampi. Unityssa on kerroksen käsite.
Unityn layerMask sisältää 32 tasoa, joista osa on jo järjestelmän käytössä, esimPlayer
kerros, UI
Tasot On edelleen monia tasoja, joita järjestelmä ei käytä. Voimme lisätä tasoja ja luokitella ne lisäämällä peliobjekteihin.
Kuinka lisätä taso Sinun on napsautettava Taso minkä tahansa kohteen Tarkastaja-paneelista ja napsauta sittenAddLayerSiinä kaikki, määritä sitten käsin taso muokattaville objekteille.
Kuinka käyttää sitä kerroksen manuaalisen lisäyksen jälkeen.
olla olemassapublic static bool Raycast(Ray ray, out RaycastHit hitInfo, float maxDistance, int layerMask);
keskellälayereMask
Opimme, että se tekee aint
Kokonaisluvun tyyppi ei kuitenkaan voi täyttää numeroita suoraan, täyttösäännöt käyttävät siirtotoimintoja,
Kerrosmaskin täyttäminen:
Hanki Layer Mask -arvo:
1 << LayerMask.NameToLayer("LayerName")
. Tämä palauttaa kokonaisluvun, joka edustaa tämän kerroksen layerMaskia.Yhdistä useita kerroksia:
|
. Esimerkiksi,layerMask = LayerMask.GetMask("Layer1", "Layer2")
LayerMask luodaan, mukaan lukien "Layer1" ja "Layer2".poissulje kerros:
^
sulkea pois tietyt tasot. Esimerkiksi,layerMask = ~LayerMask.GetMask("ExcludeLayer")
。Tarkista kerros:
layerMask.value & (1 << gameObject.layer)
. Jos tulos ei ole 0, se tarkoittaa, että objekti on layerMaskissa.// 示例代码
// 创建一个包含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))
{
// 处理射线击中的对象
}
Seuraava on koodi, joka käyttää hitInfo-parametria ilman hitInfo-parametria ja sen kanssa:
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);
}
}
}
Käytä säteentunnistusta pyörivän laserosoittimen toteuttamiseen Kun kohtaat kohteen, säteen pituus pienenee ja säde on piirrettävä.
Vaaditut taidot: Säteen havaitseminen + kierto + viivarenderöinti
Seuraava on koodi
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));
}
}
}
Optimoitu koodi
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));
}
}
Kuvaukset ovat seuraavat
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);
}
}
}
}