Technology sharing

Unitas--Ray Detectio--RayCast

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

Unitas-Ray Detection-RayCast

1. significatione radiographic probatio

Deprehensio radius, secundum nomen, radius utitur ad detegendum an objectum/multiplices res ferit?

Probatio radiographica duabus partibus constat: RadiietDeprehensio

2. Ubi probatio radiographica adhiberi potest?

  1. dirigentes ludum
    • Ludio tendere et Dirigentes: detegit an lusoris acies visus cum hoste vel alio scopo secat.
    • Bullet trajectoria et effecta: Simulate viam fugae et effectum glandium ferire.
  2. Commercium et UI *
    • Mus deprehensio preme: Deprehende utrum muris scaenici strepita intersecet cum obiecto ludi vel UI elemento.
    • Touchscreen commercium: Deprehendere an tactus lusoris intersecet quoddam elementum venationis in mobili fabrica.
  3. Mores moderatoris et AI
    • Visio detectionis: NPC vel hostes lusores deprehendere vel alias personas intra certum spatium emittere.
    • Occursus fuga: AI characteres detectionis radius utuntur ad collisiones moventes vitandas.
  4. Virtual Realitas (VR) et Augmented Realitas (AR)
    • Oculus vel manus semita: lusoris intuitum deprehendere vel manus in VR positione.
    • Objectum commercium: Deprehensio an lusor cum obiectis virtualibus in AR secet.

3.Ray in unitate

Radii in multis locis in vita cotidiana videri possunt, utsaccus dorsualis,ppt laser pagina calamumIn media Qingyu annisCyclopum

Radius constat ex parte principii, directionis et distantiae, nempe; origin , direction etdistance

In physicis, distantia radii est infinita, ergo radius physicus habet unum tantum principium et unam partem 1000.0 metra.

In unitate, Ray est structuraorigin, direction etGetPointHoc est, principium, directio et positio puncti in quadam distantia per radium

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);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

3,1 Construendo radios

Secundum codicem superius videri potest radium construi posse directe adhibito conditori radiophonico, exempli gratia:

Ray ray = new Ray(Vector3.zero, Vector3.forward); // 射线的起点 + 射线的方向
  • 1

Secundum codicem superius videre possumus principium ray principium mundi in unitate coordinatae (0,0,0), et directio radii est anterior directio mundi coordinatae.

3.2 Quomodo radios ostendant?

Re quidem vera, monstrator noster laser et lampadiosa videri possunt, radii autem in unitate sunt invisibilis.

  • ususDebug.DrawRay()ostentationem ray
  • ususLineRendererComponent trahit radium

4.Ray deprehendatur in unitate

Modo construendi vel ostentandi radios nihil significat. Aequivalet instrumentum in manu tenere et sine ferramento operari.

Qualiter utatur radiis obiectorum deprehendendorum.

Diligenter cogita: In vita nostra quotidiana, monstratores nostri laser vel lampades lucere possunt maculas parieti ostendere vel aliquem locum illuminare, postquam laser emissus est lumen objectum/- Objectum deprehenditur.

4.1Raycat munus

// 基础版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);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

Uti deprehensione ray, uti debesPhysicsBibliotheca, quae munera stataria ad physicam pertinentia continet

Videntes functiones supra onustas, saepe nescimus quibus quis utatur. Re vera basica tantum indigent.

Primum aspectum in basic versio API public static bool Raycast(Ray ray); Secundum valorem reditus, quod scire possumus est an objectum percusserit radius. Si percusserit, verum redit.

4.2HitInfo compages

Ray deprehensio in alio APIpublic static bool Raycast(Ray ray, out RaycastHit hitInfo);Plus est unus modulus inhitInfo

In hitInfo parameter est notitia structurae obiecti radiophonici. Structura est relative magna, quae significat plura indicia continet.FHitResult) similes sunt.

  • Objecti informationes, omnes informationes per transformare possunt
  • Percute punctum notitia

Obiectum notitiae facile cognoscitur: ut nomen objecti, a parte objecti, Tag objecti.

Informatio puncti, id est, puncti indicio (hit punctum) ubi radius obiecto ferit: ut coordinatae puncti;Normal(normalis), planum normale, punctumvertex color

Hoc estRaycastHitInformatio structurae, quae usitatius commentarios adiecitlightmapCoordLevis sunt tabulae coordinatae, ad reddendum adhibitae.

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; }
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

Id est, narranturHitInfoServat informationes circa obiectum quod feritur, hac informatione uti possumus plura facere

4.3 layerMask

in Unitate,layerMask Obiectum est tabulatum delectu mechanismum adhibitum ad conflictum physicum, ray dejectionem, ray detectionem et alias operationes.per occasumlayerMasknotare potes utra strata ab his operibus includantur vel excludantur.

Permanere in communi ray deprehendatur API public static bool Raycast(Ray ray, out RaycastHit hitInfo, float maxDistance, int layerMask);medium.

In superiori API, praeterquam quod maxDistantia sit distantia radiophonicaMathf.InfinityEst etiam in hac API modulus layerMask, quod larva lavacrum est.

Ludum res in unitate distinguere, ludi res distinguere possumus additis tags, id est, additis Tags. Tags tamen magis molesta sunt. Eodem tempore, quia est chorda, celeritas calculi in fundo unitatis paulo tardius est.

Stratum in unitate continet 32 ​​ordines, quarum aliquae iam systematis utuntur, utPlayeraccumsan, UIStratis multae adhuc stratae a systemate non adhibitae sunt.

Quomodo iacuit addere?AddLayerId igitur manually accumsan specificare pro iis quae immutanda sunt.

Unity_RayCast_AddLayer

Qualiter uti adiecto Iacuit manually.

existpublic static bool Raycast(Ray ray, out RaycastHit hitInfo, float maxDistance, int layerMask);mediumlayereMaskDidici quod facit aintTypus autem integer in numeris directe implere non potest, regulae impletio mutationibus utitur operationibus;

Quam imple in layerMask:

  1. Get Layer larva pretii

    • Singulae tabulae integrae valorem respondentem habet, ab 0 incipiens. Exempli gratia, iacuit default (Default) valorem 0 habet, et UI iacuit plerumque 5 .
    • Creare layerMask pro specifica strato, uti potes 1 << LayerMask.NameToLayer("LayerName") . Hic redit valorem integrum repraesentans layerMask pro hac tabula.
  2. Miscere plures stratis

    • Si plures stratas coniungere voles, bitwise VEL operator uti potes | . Exempli gratialayerMask = LayerMask.GetMask("Layer1", "Layer2") layerMask creabitur, inter "Layer1" et "Layer2".
  3. excludere accumsan

    • Iacuit excludere, primum larvam creare potes quae omnes stratos continet et tunc operator XOR bitwise utere ^ certis stratis excludere. Exempli gratialayerMask = ~LayerMask.GetMask("ExcludeLayer")
  4. reprehendo accumsan

    • Ad reprimendam si res in certo layerMask, uti potes layerMask.value & (1 << gameObject.layer) . Si effectus non est 0, significat obiectum in layerMask.
    // 示例代码
    // 创建一个包含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))
    {
        // 处理射线击中的对象
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

5.Ray deprehendatur codice

Sequens est codicem qui parametro hitInfo utitur sine et cum hitInfo parametro;

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);
        }
    }       
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

6.Ray terrorem

Deprehensio radius utere ad effectum deducendi monstratorem laser rotantem. Cum obiecto occurrens, radius longitudo reducitur, et radius trahi debet.

Artes requiruntur: Ray Detection + Rotation + LineRender

Hoc signum est

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));
        }
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93

Optimized codice

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));
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65

Redditae sunt

Unity_RayCast.gif

7. Muris click generare specialem effectum

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);
            }
        }
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29