unity3d問題集 <3> 對Physics.Raycast和Ray(射線)的理解

在游戲中,我們常常要用到鼠標來控制物體的移動或是鼠標拾取某個物體。還有射擊游戲里,子彈打中靶子......這些都需要Physics.Raycast和ray。可見他們的重要性。

首先說說射線;

射線是3D世界中一個點向一個方向發射的一條無終點的線。在發射的軌跡中,一旦與其他物體發生碰撞,它就會停止。

在API文檔中Ray是一個結構體【Struct】

(對于沒有語言基礎的同學來說理解這個可能會比較吃力,可以暫時簡單理解成是unity人為設計規定的一種數據類型,可以像int那樣使用它)

static function Ray (origin : Vector3, direction : Vector3) : Ray 【構造】

Origin: 射線的起點 direction:射線的方向 ;

具體參數變量請參考官方腳本文檔。

舉個例子吧。(下面會一一講解代碼)

//用鼠標拾取物體


鼠標碰到cube就會移動到另一個plane中。

這里除了Ray還有Physics.Raycast,這兩者密不可分,下面 一 一闡述
(下面主要是解釋代碼,莫名其妙的地方聯系代碼,跨度有點大,后來都忘了例子是什么了QAQ)

剛剛接觸ray的時候感覺Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);有點不理解,只是記下來這句可以從攝像機發出一條射線,

那么這條射線的源點在哪,又是沿什么方向呢?

(體會:不理解或是第一次見的類、結構一定要親自查API文檔,并在腳本中試一試;看了文檔還是不理解就百度、問人)

文檔中說:產生的射線是在世界空間中,從相機的近裁剪面開始并穿過屏幕position(x,y)像素坐標(position.z被忽略)。

那近裁面和屏幕是什么關系呢?是無限接近嗎?不知道啊.....~~~(>_<)~~~ 有時間要好好研究一下攝像機!有人知道的話,請告訴我~


那么為什么要把鼠標位置轉化為屏幕位置呢?

因為單位不一樣;

屏幕空間點用像素定義,屏幕的左下為(0,0);右上是(PixelWidth,pixelHeight).Z的位置是以世界單位衡量的到相機的距離。是像素坐標。

而攝像機的Vector3則是世界坐標,所以需要把屏幕上的點轉化為世界坐標。

ScreenPointToRay()函數可以把屏幕像素坐標變成一條射線。

下面說說Physics.Raycast()

API文檔中只給出這幾個方法:

public static bool Raycast(Ray ray, RaycastHit hitInfo, float distance, int layerMask);

public static bool Raycast(Ray ray, float distance, int layerMask);

public static bool Raycast(Vector3 origin, Vector3 direction, float distance, int layerMask);

public static bool Raycast(Vector3 origin, Vector3 direction, RaycastHit , float distance ,int layerMask );

但是我在VS里卻可以找到更多的方法(經常看到別人只用到了兩個變量,特意查了一下),如下圖:


不過我個人覺得還是用給的4個函數好點,因為用4個參數可以很容易看出你的意圖,即代碼的可讀性會變高。

這里說一下public static bool Raycast(Ray ray, RaycastHit hitInfo, float distance, int layerMask);

其他都差不多;

Ray ray是射線;RaycastHit hitInfo是碰撞信息;float distance是碰撞距離;int layerMask是碰撞的層

這4個參數,我一開始不太理解的地方是:RaycastHit hitInfo是用來記錄從raycast函數中得到的信息反饋。(out關鍵字,這個輸出參數不知道的話還是去補一下C#吧...)

這是什么?沒概念!好抽象啊!什么信息?誰的信息?有什么用?

(是的,遇到unity定義的一些概念就會有些不理解,這很正常。而這些人為定義的抽象概念,unity一般會用結構體來定義,而不是類,這也是struct和class的區別之一吧。和Vector3,Ray一樣,都是結構體,都是一些概念。)

下面就來看看RaycastHit是什么鬼吧。

上面用拾取物體的例子先是申明了一個RaycastHit類型的hit變量,在Physics.Raycast()方法后,hit這個變量就攜帶了射線碰撞到那個物體的一些信息(這里碰到的是方塊cube)。

這包括哪些信息呢?如圖:


(不知道的概念,自己寫一些簡單代碼去試試,會受益匪淺!)

而這里就用hit得到了transform信息,有了cube的transform,我們不就可以控制它的移動了嗎。

也說一下int layerMask吧。

可以看到是int類型,我們之前申明并初始化了targetMask = LayerMask.GetMask("target");【這個方法在圣典的中文API中貌似沒有】

LayerMask.GetMask()方法就是把target層用返回一個對應的整數。


Vector3 offset = new Vector3(15, 0, 0);//設置cube要移動的距離;

hit.transform.position = hit.transform.position + offset;//移動cube;

Physics.Raycast(ray, out hit, 100f, targetMask)

總的來說,這句話的意思是:從攝像機發射一條射線,射線的范圍是100米,只和target層發生碰撞,碰撞后得到碰撞體的信息,并返回一個布爾值。

說的有些啰嗦了,今天就寫到這吧。
發布的時候驗證碼錯誤,有重寫了一遍QAQ~~~強烈建議蠻牛博客+++自動保存~~~
寫文章不易,轉載請注明出處【Sugar丿miss丶QAQ】http://www.unitymanual.com/blog-42778.html

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 在我們的游戲開發過程中,有一個很重要的工作就是進行碰撞檢測。例如在射擊游戲中子彈是否擊中敵人,在RPG游戲中是否撿...
    壹米玖坤閱讀 24,617評論 0 17
  • 何為物理射線? 從一個點往一個方向,發射一根無限長的射線,這根射線與場景中的其余的游戲物體的碰撞體組件相碰撞,射線...
    困卡閱讀 10,081評論 0 2
  • 相關api 1、Ray Camera.main.ScreenPointToRay(Vector3 pos)返回一條...
    千云_android閱讀 418評論 0 1
  • Unity3D塔防開發流程 配置環境及場景搭建 編程語言:C#,略懂些許設計模式,如果不了解設計模式,BUG Mo...
    Grape_葡萄閱讀 2,997評論 1 3
  • “你會感激生活的暴擊嗎?” “我可以放下,可以原諒,但我不會感激。如果爸媽知道我曾經經歷了那么大的暴擊,他們得心疼...
    柒玥_M閱讀 791評論 0 2