在遊戲中,我們常常要用到鼠標來控制物體的移動或是鼠標拾取某個物體。還有射擊遊戲裏,子彈打中靶子......這些都需要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
作者:Moment__格調
鏈接:https://www.jianshu.com/p/6ccd8e91e996
來源:簡書
著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。