射線碰撞檢測

在我們的游戲開發過程中,有一個很重要的工作就是進行碰撞檢測。例如在射擊游戲中子彈是否擊中敵人,在RPG游戲中是否撿到裝備等等。在進行碰撞檢測時,我們最常用的工具就是射線,Unity 3D的物理引擎也為我們提供了射線類以及相關的函數接口。本文將對射線的使用進行一個總結。

射線是在三維世界中從一個點沿一個方向發射的一條無限長的線。在射線的軌跡上,一旦與添加了碰撞器的模型發生碰撞,將停止發射。我們可以利用射線實現子彈擊中目標的檢測,鼠標點擊拾取物體等功能。

Ray射線類和RaycastHit射線投射碰撞信息類是兩個最常用的射線工具類。

創建一條射線Ray需要指明射線的起點(origin)和射線的方向(direction)。這兩個參數也是Ray的成員變量。注意,射線的方向在設置時如果未單位化,Unity 3D會自動進行單位歸一化處理。射線Ray的構造函數為 :
public Ray(Vector3 origin, Vector3 direction);

RaycastHit類用于存儲發射射線后產生的碰撞信息。常用的成員變量如下:

collider與射線發生碰撞的碰撞器
distance 從射線起點到射線與碰撞器的交點的距離
normal 射線射入平面的法向量
point 射線與碰撞器交點的坐標(Vector3對象)

Physics.Raycast靜態函數用于在場景中發射一條可以和碰撞器碰撞的射線

(1)下面來實現一個簡單的demo

代碼如下:

using UnityEngine;
using System.Collections;public class RayCast : MonoBehaviour {// Use this for initializationvoid Start () {}// Update is called once per framevoid Update () {Ray ray = new Ray(transform.position, transform.forward);RaycastHit hit;if (Physics.Raycast(ray, out hit, Mathf.Infinity)){print("射線碰撞到了"+hit.collider.gameObject+"物體"+ray.origin+" "+hit.point);Debug.DrawLine(ray.origin,hit.point,Color.red);}}
}

?當運動的物體前進方向發出的射線接觸到cube時,scene中將會畫出一條紅色射線,以及打印出提示信息。

?

定向發射射線的實現

當我們要使用鼠標拾取物體或判斷子彈是否擊中物體時,我們往往是沿著特定的方向發射射線,這個方向可能是朝向屏幕上的一個點,或者是世界坐標系中的一個矢量方向,沿世界坐標系中的矢量方向發射射線我們已經在上面演示過如何實現。針對向屏幕上的某一點發射射線,Unity 3D為我們提供了兩個API函數以供使用,分別是ScreenPointToRayViewportPointToRay

(2)ScreenPointToRay

public Ray ScreenPointToRay(Vector3 position);
參數說明:position是屏幕上的一個參考點坐標。
返回值說明:返回射向position參考點的射線。當發射的射線未碰撞到物體時,碰撞點hit.point的值為(0,0,0)。

ScreenPointToRay方法從攝像機的近視口nearClip向屏幕上的一點position發射射線。Position用實際像素值表示射線到屏幕上的位置。當參考點position的x分量或y分量從0增長到最大值時,射線將從屏幕的一邊移動到另一邊。由于position在屏幕上,因此z分量始終為0。

下面我們用一段程序示例說明如何利用ScreenPointToRay來發射一條指向屏幕上的某點來進行定向檢測碰撞體。在場景中創建一個c_Cube位于攝像機的正前方,將下面的腳本RayDemo.cs掛載到攝像機上。

using UnityEngine;
using System.Collections;public class RayDemo : MonoBehaviour {Ray ray;RaycastHit hit;//創建射線到屏幕上的參考點,像素坐標Vector3 position = new Vector3(Screen.width / 2.0f, Screen.height / 2.0f, 0.0f);// Use this for initializationvoid Start () {}// Update is called once per framevoid Update () {//射線沿著屏幕x軸,從左向右循環掃描position.x = position.x >= Screen.width ? 0.0f : position.x + 1.0f;//生成射線ray = Camera.main.ScreenPointToRay(position);if (Physics.Raycast(ray, out hit, 100.0f)){//如果物體發生了碰撞,在screen視圖中繪制射線Debug.DrawLine(ray.origin,hit.point,Color.green);//打印射線檢測到的物體的名稱Debug.Log("射線檢測到的物體的名稱:"+hit.transform.name);}}
}

  運行截圖如下:

(3)ViewportPointToRay

public Ray ViewportPointToRay(Vector3 position);
參數說明:position為屏幕上的一個參考點坐標(坐標已單位化處理)。
返回值說明:返回射向position參考點的射線。當發射的射線未碰撞到物體時,碰撞點hit.point的值為(0,0,0)。

ViewportPointToRay方法從攝像機的近視口nearClip向屏幕上的一點position發射射線。Position用單位化比例值的方式表示射線到屏幕上的位置。當參考點position的x分量或y分量從0增長到1時,射線將從屏幕的一邊移動到另一邊。由于position在屏幕上,因此z分量始終為0。

下面我們用一段程序示例說明如何利用ViewportPointToRay來發射一條指向屏幕上的某點來進行定向檢測碰撞體。在場景中創建一個c_Cube位于攝像機的正前方,將下面的腳本RayDemo01.cs掛載到攝像機上。

using UnityEngine;
using System.Collections;public class RayDemo : MonoBehaviour {Ray ray;RaycastHit hit;//創建射線到屏幕上的參考點,像素坐標Vector3 position = new Vector3(0.5f, 0.5f, 0.0f);// Use this for initializationvoid Start () {}// Update is called once per framevoid Update () {//射線沿著屏幕x軸,從左向右循環掃描position.x = position.x >= 1.0f ? 0.0f : position.x + 0.005f;//生成射線ray = Camera.main.ViewportPointToRay(position);if (Physics.Raycast(ray, out hit, 100.0f)){//如果物體發生了碰撞,在screen視圖中繪制射線Debug.DrawLine(ray.origin,hit.point,Color.blue);//打印射線檢測到的物體的名稱Debug.Log("射線檢測到的物體的名稱:"+hit.transform.name);}}
}

  運行截圖如下:

(3)

利用二次發射射線的方式檢測內部物體

有的時候我們要檢測的物體在其他物體的內部,并且這兩個物體都具有碰撞器,用射線檢測返回的是第一個物體的信息。在這種情況下,我們需要使用二次射線發射的做法,即以第一次射線碰撞的外層物體的碰撞點作為第二次射線發射的起點,沿原來方向發射射線,判斷是否與內部物體發生碰撞。

下面我們用一段代碼示例來說明如何用二次發射射線來檢測位于物體內部的目標。在場景中創建兩個Cube,位于攝像機的正前方。在其中一個Cube的位置上創建一個Sphere,并設置它的大小為Cube的一半,這樣Sphere就位于Cube的內部。將下面的腳本RayDemo02.cs掛載到攝像機上。

using UnityEngine;
using System.Collections;public class RayDemo : MonoBehaviour {GameObject wrapper; // 外層物體  GameObject target; // 內層物體  string info = ""; // 碰撞檢測信息  void Update(){if (Input.GetMouseButton(0)){// 當鼠標左鍵按下時,向鼠標所在的屏幕位置發射一條射線  Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);RaycastHit hitInfo;if (Physics.Raycast(ray, out hitInfo)){// 當射線與物體發生碰撞時,在場景視圖中繪制射線  Debug.DrawLine(ray.origin, hitInfo.point, Color.red);// 獲得第一次碰撞的外層物體對象  wrapper = hitInfo.collider.gameObject;// 以第一次的碰撞點為起點,沿原來的方向二次發射射線  Ray ray2 = new Ray(hitInfo.point, ray.direction);RaycastHit hitInfo2;if (Physics.Raycast(ray2, out hitInfo2)){// 當射線與內層物體碰撞時,在場景中繪制射線  Debug.DrawLine(ray2.origin, ray2.direction, Color.green);// 獲得內層物體對象  target = hitInfo2.collider.gameObject;// 將外層物體的網格隱藏  wrapper.GetComponent<MeshRenderer>().enabled = false;// 設置碰撞信息  info = "檢測到物體: " + target.name + "坐標: " + target.transform.position;}else{// 如果二次發射的射線沒有與內層物體碰撞  // 顯示外層物體的網格  wrapper.GetComponent<MeshRenderer>().enabled = true;// 設置碰撞信息  info = "檢測到物體: " + wrapper.name + "坐標: " + wrapper.transform.position;}}}}void OnGUI(){// 在屏幕上打印輸出射線檢測的信息  GUILayout.Label(info);}}

  當點擊cube時,注意在偏離中心位置時,sphere沒有顯示出來,如圖:

點擊球的位置時,外部的cube 被隱藏了,因此我們能看到里面的小球

轉載于:https://www.cnblogs.com/cdpp/p/6340923.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/371619.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/371619.shtml
英文地址,請注明出處:http://en.pswp.cn/news/371619.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

高級ZK:異步UI更新和后臺處理–第1部分

異步UI更新非常有用&#xff0c;因為它們通常可以提高響應性&#xff0c;可用性和用戶界面的總體感覺。 我將在這里重點介紹ZK框架&#xff0c;但是通常&#xff0c;相同的原理也適用于桌面UI&#xff08;Swing&#xff0c;SWT&#xff09;。 長時間運行的處理 有時&#xff0…

php注冊登錄遍寫入 遍驗證,自動注冊登錄驗證機制的php代碼

在phpwind站點后臺添加“廣告管家”(CNZZ的一款廣告投放的應用)的應用&#xff0c;整個“廣告管家”通過iframe載入&#xff0c;載入的具體內容根據不同站點顯示針對該站點的具體內容。出于意用性方面的考慮&#xff0c;需要以下二點&#xff1a;1、首次進入“廣告管家”頁面自…

轉載:tensorflow保存訓練后的模型

訓練完一個模型后&#xff0c;為了以后重復使用&#xff0c;通常我們需要對模型的結果進行保存。如果用Tensorflow去實現神經網絡&#xff0c;所要保存的就是神經網絡中的各項權重值。建議可以使用Saver類保存和加載模型的結果。 1、使用tf.train.Saver.save()方法保存模型 tf.…

php url傳遞變量,php – 在laravel中通過url傳遞變量

我是laravel的新手,我正在努力讓我的網址格式正確.格式為http://mysite/blog?category1 instead of http://mysite/blog/category1這些是我正在使用的文件,有沒有辦法將路由放入BlogControllerRoute.phpRoute::get(blog/{category}, function($category null){// get all the…

Apache Wicket:記住我的功能

在Web應用程序中&#xff0c;具有“記住我”功能非常普遍&#xff0c;該功能使用戶每次訪問我們的網站時都能自動登錄。 可以使用Spring Security來實現這種功能&#xff0c;但我認為將基于請求的身份驗證框架與基于組件的Web框架結合使用并不是最好的主意。 這兩個世界不能很好…

Ubuntu 安裝中文

系統環境&#xff1a; 1. 官網 http://pinyin.sogou.com/linux/ 下載安裝包。 2. 先運行 apt-get update 。 3. 再運行 apt-get -f install 。 4. 再運行 可能有的UBuntu系統自帶了。 5. 如果下載的搜狐輸入法安裝包的格式為 .deb 的&#xff0c; 運行 &#xff1a; dpk…

Eigen教程(10)

整理下Eigen庫的教程&#xff0c;參考&#xff1a;http://eigen.tuxfamily.org/dox/index.html 混淆 在Eigen中&#xff0c;當變量同時出現在左值和右值&#xff0c;賦值操作可能會帶來混淆問題。這一篇將解釋什么是混淆&#xff0c;什么時候是有害的&#xff0c;怎么使用做。 …

matlab把符號數,Matlab?符號與數值之間的轉換

符號運算得到的是精確的解析解&#xff0c;但是有時需要進行數值轉換&#xff0c;主要通過以下幾個函數實現。1.digits 函數調用方法&#xff1a;digits(D)函數設置有效數字個數為D的近似解精度。2.vpa 函數vpaVariable-precision arithmeticSyntaxR vpa(A)R vpa(A,d)Descrip…

JSF組件庫–質量不只是零缺陷

自從我上次研究三個主要JSF組件庫的質量以來&#xff0c;已經有一段時間了。 2009年12月&#xff0c;我開始比較RichFaces&#xff0c;Primefaces和ICEfaces的整體軟件質量 。 從那時起&#xff0c;事情發生了變化&#xff0c;從現在開始&#xff0c;我想重新評估和更新它。 我…

[API檔案]GetDlgItem

函數功能 用于獲取指定對話框函數控件的句柄。 API函數原型 1 HWND WINAPI GetDlgItem( 2 _In_opt_ HWND hDlg, //指向包含該對話框的句柄 3 _In_ int nIDDlgItem //第二個參數是控件的名稱 4 ); 范例 可參見ComboBox_AddString宏的范例【點擊這里】轉載于:ht…

嵌入式實時系統的任務設計

嵌入式實時系統的任務設計主要為任務函數的設計、任務優先級的安排、任務的數據結構設計&#xff0c;任務之間的同步與通信設計。 一&#xff0e;任務函數的設計 任務函數按任務結構可分為單次執行任務、周期執行任務和事件觸發任務&#xff0c;各任務的主要差異點如下&#xf…

mssql php 5.4,PHP5.4如何連接MSSql Server2005

windows系統下&#xff0c;PHP5.3以上的版本已經不支持mssql擴展&#xff0c;所以如果你需要和sql server通信需要到http://msdn.microsoft.com/en-us/sqlserver/ff657782.aspx自行下載微軟提供的The SQL Server Driver for PHP。下載后解壓縮&#xff0c;將所有的.dll文件拷貝…

將原生SQL功能休眠到您的Spring Data Repository中

JPA為您提供NamedNativeQuery以便使用本機SQL。 但是&#xff0c;用法不是很方便&#xff0c;尤其是當您需要在本機SQL中映射多個實體時。 您必須定義一組容易出錯的SqlResultSetMapping映射。 對于以前使用過Hibernate本機SQL功能的用戶&#xff0c;您會發現它比JPA的NamedNat…

創建yii的第一個應用

原文鏈接轉載于:https://www.cnblogs.com/Baronboy/p/6354522.html

字符串匹配(KMP 算法 含代碼)

主要是針對字符串的匹配算法進行解說 有關字符串的基本知識傳統的串匹配法模式匹配的一種改進算法KMP算法網上一比較易懂的解說小樣例1計算next 2計算nextval代碼有關字符串的基本知識 串&#xff08;string或字符串&#xff09;是由零個或多個字符組成的有限序列&#xff0c;一…

php數組轉為js json,javascript-將數組php轉換為JSON時出錯

我在將多維PHP數組轉換為JSON時遇到了一些麻煩.我使用json_encode進行了轉換,但它為null.我正在嘗試開發orgChart,數據是從CSV文件中讀取的,并保存在數組中.布局和JS代碼用于接收JSON文件,因此我需要使用這種格式.這是數組的一部分,其中包含175個數組Array([2] > Array([id]…

UVa 10954 全部相加(Huffman編碼)

https://vjudge.net/problem/UVA-10954 題意&#xff1a;有n個數的集合S&#xff0c;每次可以從S中刪除兩個數&#xff0c;然后把它們的和放回集合&#xff0c;直到剩下一個數。每次操作的開銷等于刪除的兩個數之和&#xff0c;求最小開銷。 思路&#xff1a;Huffman編碼。 1 #…

serialVersionUID的作用以及如何用idea自動生成實體類的serialVersionUID

轉載&#xff1a;http://blog.csdn.net/liuzongl2012/article/details/45168585 serialVersionUID的作用&#xff1a; 通過判斷實體類的serialVersionUID來驗證版本一致性的。在進行反序列化時&#xff0c;JVM會把傳來的字節流中的serialVersionUID與本地相應實體類的serialVer…

js post方式請求另外一個php,利用JS使用POST方式提交請求的方法(結合代碼詳細解答)...

下面是我給大家整理的利用JS使用POST方式提交請求的方法&#xff0c;有興趣的同學可以去看看。一般都是寫上隱藏的form標簽&#xff0c;用來調用js函數然后submit全部用js來寫也行&#xff0c;以下是我在一個問答頻道看見別人寫的例子&#xff0c;放在這里function post(URL, P…

JBoss BRMS最佳實踐– BPM流程初始化層的提示

我過去發布過一些有關遷移策略的文章&#xff0c;仔細研究了流程層&#xff0c;并提供了一些有關jBPM的最佳實踐 &#xff0c;它們都涉及到BPM策略的非常具體的部分。 我想重新討論最佳實踐的主題&#xff0c;然后在智能集成企業級別上&#xff0c;我們討論使用JBoss BRMS對您的…