Κοινή χρήση τεχνολογίας

Unity--Ray Detection--RayCast

2024-07-12

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

Unity–Ray Detection–RayCast

1.Η έννοια του ακτινογραφικού ελέγχου

Η ανίχνευση ακτίνων, σύμφωνα με το όνομα, χρησιμοποιεί μια ακτίνα για να ανιχνεύσει εάν χτυπά ένα αντικείμενο/πολλά αντικείμενα

Ο ακτινολογικός έλεγχος αποτελείται από δύο μέρη: ΑκτίνεςκαιΑνίχνευση

2. Πού μπορεί να χρησιμοποιηθεί ο ακτινογραφικός έλεγχος;

  1. παιχνίδι σκοποβολής
    • Σκόπευση και Σκοποβολή παίκτη: Ανιχνεύει εάν η οπτική γωνία του παίκτη τέμνεται με έναν εχθρό ή άλλο στόχο.
    • Τροχιά και εφέ σφαίρας: Προσομοίωση της διαδρομής πτήσης και του εφέ χτυπήματος των σφαιρών.
  2. Αλληλεπίδραση και διεπαφή χρήστη
    • Ανίχνευση κλικ του ποντικιού: Εντοπίστε εάν το κλικ του ποντικιού του παίκτη τέμνεται με ένα αντικείμενο παιχνιδιού ή ένα στοιχείο διεπαφής χρήστη.
    • Αλληλεπίδραση με οθόνη αφής: Εντοπίστε εάν το άγγιγμα ενός παίκτη τέμνει ένα συγκεκριμένο στοιχείο παιχνιδιού σε μια κινητή συσκευή.
  3. Ελεγκτές χαρακτήρων και AI
    • Ανίχνευση όρασης: Το NPC ή οι εχθροί εντοπίζουν παίκτες ή άλλους χαρακτήρες εντός ενός συγκεκριμένου εύρους.
    • Αποφυγή σύγκρουσης: Οι χαρακτήρες AI χρησιμοποιούν ανίχνευση ακτίνων για να αποφύγουν τις συγκρούσεις όταν κινούνται.
  4. Εικονική πραγματικότητα (VR) και επαυξημένη πραγματικότητα (AR)
    • Παρακολούθηση ματιών ή χεριών: Εντοπίστε το βλέμμα ή τη θέση του χεριού του παίκτη σε VR.
    • Αλληλεπίδραση αντικειμένου: Ανίχνευση εάν το πρόγραμμα αναπαραγωγής τέμνεται με εικονικά αντικείμενα στο AR.

3.Ray in Unity

Οι ακτίνες μπορούν να φανούν σε πολλά σημεία της καθημερινής ζωής, όπως π.χφακός,στυλό περιστροφής σελίδας με λέιζερ ppt, στη μέση των ετών QingyuΚύκλωπας

Μια ακτίνα αποτελείται από ένα σημείο εκκίνησης, μια κατεύθυνση και μια απόσταση, δηλαδή: origin , direction καιdistance

Στη φυσική, η απόσταση της ακτίνας είναι άπειρη, επομένως η φυσική ακτίνα έχει μόνο ένα σημείο εκκίνησης και μία κατεύθυνση Στο παιχνίδι, η μέγιστη απόσταση της ακτίνας περιορίζεται επίσης από το σύστημα 1000,0 μέτρα Ακολουθεί περιγραφή του Ray.

Στο Unity, το Ray είναι μια δομή Τα βασικά μέλη του όγκου της δομής περιλαμβάνουνorigin, direction καιGetPointΔηλαδή, το σημείο εκκίνησης, η κατεύθυνση και η θέση ενός σημείου σε μια ορισμένη απόσταση κατά μήκος της ακτίνας

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 Κατασκευή ακτίνων

Σύμφωνα με τον παραπάνω κώδικα, μπορεί να φανεί ότι μια ακτίνα μπορεί να κατασκευαστεί απευθείας χρησιμοποιώντας τον κατασκευαστή Ray, για παράδειγμα:

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

Σύμφωνα με τον παραπάνω κώδικα, μπορούμε να δούμε ότι το σημείο εκκίνησης της ακτίνας είναι η αρχή των συντεταγμένων του κόσμου στην ενότητα (0,0,0), και η κατεύθυνση της ακτίνας είναι η προς τα εμπρός κατεύθυνση των συντεταγμένων του κόσμου.

3.2 Πώς να εμφανίσετε τις ακτίνες

Στην πραγματικότητα, ο δείκτης λέιζερ και ο φακός μας μπορούν να φανούν, αλλά οι ακτίνες στο Unity είναι αόρατες, επομένως, εάν θέλουμε να εμφανίσουμε τις ακτίνες, μπορούμε να χρησιμοποιήσουμε τις ακόλουθες μεθόδους:

  • χρήσηDebug.DrawRay()ακτίνα οθόνης
  • χρήσηLineRendererΤο συστατικό σχεδιάζει την ακτίνα

4.Ανίχνευση ακτίνων στο Unity

Απλώς η κατασκευή ή η εμφάνιση των ακτίνων δεν έχει νόημα.

Πώς να χρησιμοποιήσετε τις ακτίνες για την ανίχνευση αντικειμένων.

Σκεφτείτε το προσεκτικά: Στην καθημερινή μας ζωή, οι δείκτες λέιζερ ή οι φακοί μας μπορούν να εμφανίσουν φωτεινά σημεία στον τοίχο ή να φωτίσουν ένα συγκεκριμένο σημείο μετά την εκπομπή φωτός λέιζερ το αντικείμενο/ Το αντικείμενο ανιχνεύεται Χρησιμοποιήστε το ακόλουθο API στο Unity για να προσδιορίσετε εάν το αντικείμενο ανιχνεύεται.

4.1 Λειτουργία Raycat

// 基础版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

Για να χρησιμοποιήσετε την ανίχνευση ακτίνων, πρέπει να χρησιμοποιήσετε τοPhysicsΒιβλιοθήκη, η οποία περιέχει στατικές συναρτήσεις που σχετίζονται με τη φυσική

Βλέποντας τις παραπάνω υπερφορτωμένες συναρτήσεις, συχνά δεν ξέρουμε ποια να χρησιμοποιήσουμε. Στην πραγματικότητα, χρειαζόμαστε μόνο τις βασικές παραμέτρους.

Πρώτα κοιτάξτε τη βασική έκδοση του API public static bool Raycast(Ray ray); Σύμφωνα με την τιμή που επιστρέφει, αυτό που μπορούμε να γνωρίζουμε είναι αν η ακτίνα χτυπά ένα αντικείμενο, επιστρέφει true.

4.2 Δομή HitInfo

Ανίχνευση ακτίνων σε άλλο APIpublic static bool Raycast(Ray ray, out RaycastHit hitInfo);Υπάρχει μια ακόμη παράμετρος μέσαhitInfo

Η παράμετρος hitInfo είναι η δομή πληροφοριών του αντικειμένου που χτυπήθηκε από την ακτίνα Η δομή είναι σχετικά μεγάλη, πράγμα που σημαίνει ότι περιέχει περισσότερες πληροφορίες.FHitResult) είναι παρόμοια Από μακροσκοπική ή πρακτική προοπτική, όταν μια ακτίνα χτυπά ένα αντικείμενο, μπορούμε να λάβουμε πληροφορίες για το ίδιο το αντικείμενο και πληροφορίες για το σημείο πρόσκρουσης.

  • Πληροφορίες αντικειμένου, όλες οι πληροφορίες μπορούν να ληφθούν μέσω μετασχηματισμού
  • Πληροφορίες για το σημείο χτυπήματος

Η απόκτηση των πληροφοριών ενός αντικειμένου είναι εύκολα κατανοητή: όπως το όνομα του αντικειμένου, το στοιχείο μεταφοράς από το αντικείμενο, η ετικέτα του αντικειμένου...

Λάβετε τις πληροφορίες του σημείου χτυπήματος, δηλαδή τις πληροφορίες ενός σημείου (σημείο πρόσκρουσης) όπου η ακτίνα χτυπά το αντικείμενο: όπως οι συντεταγμένες του σημείου,Κανονικός(κανονικό), κανονικό επίπεδο, το σημείο τουχρώμα κορυφής

Το παρακάτω είναι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; }
    }
}

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

ΔηλαδήHitInfoΑποθηκεύει τις πληροφορίες σχετικά με το αντικείμενο που χτυπήσαμε, μπορούμε να χρησιμοποιήσουμε αυτές τις πληροφορίες για να κάνουμε περισσότερα πράγματα

4.3 layerMask

Στην ενότητα,layerMask Είναι ένας μηχανισμός επιλογής στρώματος αντικειμένου που χρησιμοποιείται για τον έλεγχο της φυσικής σύγκρουσης, της χύτευσης ακτίνων, της ανίχνευσης ακτίνων και άλλων λειτουργιών.με ρύθμισηlayerMask, μπορείτε να καθορίσετε ποια επίπεδα πρέπει να συμπεριληφθούν ή να εξαιρεθούν από αυτές τις λειτουργίες.

Συνεχίστε πίσω στο API ανίχνευσης ακτίνων που χρησιμοποιείται συνήθως public static bool Raycast(Ray ray, out RaycastHit hitInfo, float maxDistance, int layerMask);Μέσης.

Στο παραπάνω API, είναι αυτονόητο ότι το maxDistance είναι η απόσταση της ακτίνας Το σύστημα έχει επίσης μια μέγιστη τιμήMathf.InfinityΥπάρχει επίσης μια παράμετρος layerMask σε αυτό το API, η οποία είναι η μάσκα επιπέδου.

Για να διακρίνουμε τα αντικείμενα του παιχνιδιού στο Unity, μπορούμε να διακρίνουμε τα αντικείμενα του παιχνιδιού προσθέτοντας ετικέτες, δηλαδή προσθέτοντας ετικέτες. Ωστόσο, οι ετικέτες είναι πιο ενοχλητικές. Ταυτόχρονα, επειδή είναι μια συμβολοσειρά, η ταχύτητα υπολογισμού στο κάτω μέρος του Unity είναι λίγο πιο αργή. Υπάρχει μια έννοια του επιπέδου στο Unity.

Το layerMask στο Unity περιέχει 32 επίπεδα, μερικά από τα οποία χρησιμοποιούνται ήδη από το σύστημα, όπως π.χPlayerστρώμα, UIΕπίπεδα Υπάρχουν ακόμα πολλά επίπεδα που δεν χρησιμοποιούνται από το σύστημα.

Πώς να προσθέσετε ένα επίπεδο Πρέπει να κάνετε κλικ στο Layer στον πίνακα επιθεώρησης οποιουδήποτε αντικειμένου και, στη συνέχεια, να κάνετε κλικAddLayerΑυτό είναι όλο και, στη συνέχεια, καθορίστε με μη αυτόματο τρόπο το επίπεδο για τα αντικείμενα που πρέπει να τροποποιηθούν.

Unity_RayCast_AddLayer

Πώς να το χρησιμοποιήσετε μετά την μη αυτόματη προσθήκη του επιπέδου.

υπάρχειpublic static bool Raycast(Ray ray, out RaycastHit hitInfo, float maxDistance, int layerMask);ΜέσηςlayereMaskΜάθαμε ότι κάνει αintΤύπος ακέραιου, ωστόσο, δεν μπορούμε να συμπληρώσουμε τους αριθμούς απευθείας, οι κανόνες πλήρωσης χρησιμοποιούν πράξεις μετατόπισης,

Πώς να συμπληρώσετε layerMask:

  1. Λάβετε την τιμή Layer Mask

    • Κάθε επίπεδο έχει μια αντίστοιχη ακέραια τιμή, που ξεκινά από το 0. Για παράδειγμα, το προεπιλεγμένο επίπεδο (Προεπιλογή) έχει τιμή 0 και το επίπεδο διεπαφής χρήστη είναι συνήθως 5.
    • Για να δημιουργήσετε ένα layerMask για ένα συγκεκριμένο επίπεδο, μπορείτε να χρησιμοποιήσετε 1 << LayerMask.NameToLayer("LayerName") . Αυτό επιστρέφει μια ακέραια τιμή που αντιπροσωπεύει το layerMask για αυτό το επίπεδο.
  2. Συνδυάστε πολλαπλά στρώματα

    • Εάν θέλετε να συνδυάσετε πολλά επίπεδα, μπορείτε να χρησιμοποιήσετε τον τελεστή bitwise OR | . Για παράδειγμα,layerMask = LayerMask.GetMask("Layer1", "Layer2") Θα δημιουργηθεί ένα layerMask, συμπεριλαμβανομένων των "Layer1" και "Layer2".
  3. εξαίρεση στρώματος

    • Για να εξαιρέσετε ένα επίπεδο, μπορείτε πρώτα να δημιουργήσετε μια μάσκα που να περιέχει όλα τα επίπεδα και στη συνέχεια να χρησιμοποιήσετε τον τελεστή XOR bitwise ^ για να εξαιρεθούν συγκεκριμένα επίπεδα. Για παράδειγμα,layerMask = ~LayerMask.GetMask("ExcludeLayer")
  4. Ελέγξτε το στρώμα

    • Για να ελέγξετε εάν ένα αντικείμενο βρίσκεται στο καθορισμένο layerMask, μπορείτε να χρησιμοποιήσετε layerMask.value & (1 << gameObject.layer) . Εάν το αποτέλεσμα δεν είναι 0, σημαίνει ότι το αντικείμενο βρίσκεται σε 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.Κωδικός ανίχνευσης ακτίνων

Ο παρακάτω είναι ο κώδικας που χρησιμοποιεί την παράμετρο 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);
        }
    }       
}

  • 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 Detection + Rotation + 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));
        }
    }
}

  • 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

Βελτιστοποιημένος κώδικας

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

Οι αποδόσεις είναι οι εξής

Unity_RayCast.gif

7. Κάντε κλικ με το ποντίκι για να δημιουργήσετε ένα ειδικό εφέ

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