在游戲中,我們常常要用到鼠標(biāo)來(lái)控制物體的移動(dòng)或是鼠標(biāo)拾取某個(gè)物體矗愧。還有射擊游戲里梯醒,子彈打中靶子......這些都需要Physics.Raycast和ray宽堆。可見(jiàn)他們的重要性茸习。
首先說(shuō)說(shuō)射線畜隶;
射線是3D世界中一個(gè)點(diǎn)向一個(gè)方向發(fā)射的一條無(wú)終點(diǎn)的線。在發(fā)射的軌跡中号胚,一旦與其他物體發(fā)生碰撞籽慢,它就會(huì)停止。
在API文檔中Ray是一個(gè)結(jié)構(gòu)體【Struct】
(對(duì)于沒(méi)有語(yǔ)言基礎(chǔ)的同學(xué)來(lái)說(shuō)理解這個(gè)可能會(huì)比較吃力猫胁,可以暫時(shí)簡(jiǎn)單理解成是unity人為設(shè)計(jì)規(guī)定的一種數(shù)據(jù)類型箱亿,可以像int那樣使用它)
static function Ray (origin : Vector3, direction : Vector3) : Ray 【構(gòu)造】
Origin: 射線的起點(diǎn) direction:射線的方向 ;
具體參數(shù)變量請(qǐng)參考官方腳本文檔弃秆。
舉個(gè)例子吧届惋。(下面會(huì)一一講解代碼)
//用鼠標(biāo)拾取物體
鼠標(biāo)碰到cube就會(huì)移動(dòng)到另一個(gè)plane中。
這里除了Ray還有Physics.Raycast菠赚,這兩者密不可分脑豹,下面 一 一闡述
(下面主要是解釋代碼,莫名其妙的地方聯(lián)系代碼衡查,跨度有點(diǎn)大瘩欺,后來(lái)都忘了例子是什么了QAQ)
剛剛接觸ray的時(shí)候感覺(jué)Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);有點(diǎn)不理解,只是記下來(lái)這句可以從攝像機(jī)發(fā)出一條射線,
那么這條射線的源點(diǎn)在哪击碗,又是沿什么方向呢筑悴?
(體會(huì):不理解或是第一次見(jiàn)的類、結(jié)構(gòu)一定要親自查API文檔稍途,并在腳本中試一試阁吝;看了文檔還是不理解就百度、問(wèn)人)
文檔中說(shuō):產(chǎn)生的射線是在世界空間中械拍,從相機(jī)的近裁剪面開(kāi)始并穿過(guò)屏幕position(x,y)像素坐標(biāo)(position.z被忽略)突勇。
那近裁面和屏幕是什么關(guān)系呢?是無(wú)限接近嗎坷虑?不知道啊.....~~~(>_<)~~~ 有時(shí)間要好好研究一下攝像機(jī)甲馋!有人知道的話,請(qǐng)告訴我~
那么為什么要把鼠標(biāo)位置轉(zhuǎn)化為屏幕位置呢迄损?
因?yàn)閱挝徊灰粯樱?/p>
屏幕空間點(diǎn)用像素定義定躏,屏幕的左下為(0,0);右上是(PixelWidth,pixelHeight).Z的位置是以世界單位衡量的到相機(jī)的距離芹敌。是像素坐標(biāo)痊远。
而攝像機(jī)的Vector3則是世界坐標(biāo),所以需要把屏幕上的點(diǎn)轉(zhuǎn)化為世界坐標(biāo)氏捞。
ScreenPointToRay()函數(shù)可以把屏幕像素坐標(biāo)變成一條射線碧聪。
下面說(shuō)說(shuō)Physics.Raycast()
API文檔中只給出這幾個(gè)方法:
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里卻可以找到更多的方法(經(jīng)骋壕ィ看到別人只用到了兩個(gè)變量逞姿,特意查了一下),如下圖:
不過(guò)我個(gè)人覺(jué)得還是用給的4個(gè)函數(shù)好點(diǎn)捆等,因?yàn)橛?個(gè)參數(shù)可以很容易看出你的意圖滞造,即代碼的可讀性會(huì)變高。
這里說(shuō)一下public static bool Raycast(Ray ray, RaycastHit hitInfo, float distance, int layerMask);
其他都差不多栋烤;
Ray ray是射線断部;RaycastHit hitInfo是碰撞信息;float distance是碰撞距離班缎;int layerMask是碰撞的層
這4個(gè)參數(shù)蝴光,我一開(kāi)始不太理解的地方是:RaycastHit hitInfo是用來(lái)記錄從raycast函數(shù)中得到的信息反饋。(out關(guān)鍵字达址,這個(gè)輸出參數(shù)不知道的話還是去補(bǔ)一下C#吧...)
這是什么蔑祟?沒(méi)概念!好抽象俺吝搿疆虚!什么信息?誰(shuí)的信息?有什么用径簿?
(是的罢屈,遇到unity定義的一些概念就會(huì)有些不理解,這很正常篇亭。而這些人為定義的抽象概念缠捌,unity一般會(huì)用結(jié)構(gòu)體來(lái)定義,而不是類译蒂,這也是struct和class的區(qū)別之一吧曼月。和Vector3,Ray一樣柔昼,都是結(jié)構(gòu)體哑芹,都是一些概念。)
下面就來(lái)看看RaycastHit是什么鬼吧捕透。
上面用拾取物體的例子先是申明了一個(gè)RaycastHit類型的hit變量聪姿,在Physics.Raycast()方法后,hit這個(gè)變量就攜帶了射線碰撞到那個(gè)物體的一些信息(這里碰到的是方塊cube)乙嘀。
這包括哪些信息呢末购?如圖:
(不知道的概念,自己寫一些簡(jiǎn)單代碼去試試乒躺,會(huì)受益匪淺U忻ぁ)
而這里就用hit得到了transform信息低缩,有了cube的transform嘉冒,我們不就可以控制它的移動(dòng)了嗎。
也說(shuō)一下int layerMask吧咆繁。
可以看到是int類型讳推,我們之前申明并初始化了targetMask = LayerMask.GetMask("target");【這個(gè)方法在圣典的中文API中貌似沒(méi)有】
LayerMask.GetMask()方法就是把target層用返回一個(gè)對(duì)應(yīng)的整數(shù)。
Vector3 offset = new Vector3(15, 0, 0);//設(shè)置cube要移動(dòng)的距離玩般;
hit.transform.position = hit.transform.position + offset;//移動(dòng)cube银觅;
Physics.Raycast(ray, out hit, 100f, targetMask)
總的來(lái)說(shuō),這句話的意思是:從攝像機(jī)發(fā)射一條射線坏为,射線的范圍是100米究驴,只和target層發(fā)生碰撞,碰撞后得到碰撞體的信息匀伏,并返回一個(gè)布爾值洒忧。
說(shuō)的有些啰嗦了,今天就寫到這吧够颠。
發(fā)布的時(shí)候驗(yàn)證碼錯(cuò)誤熙侍,有重寫了一遍QAQ~~~強(qiáng)烈建議蠻牛博客+++自動(dòng)保存~~~
寫文章不易,轉(zhuǎn)載請(qǐng)注明出處【Sugar丿miss丶QAQ】http://www.unitymanual.com/blog-42778.html