最近在學(xué)習(xí)Unity的過程中,攻擊判定這一塊是想的比較多的部分台妆,自己在開發(fā)的過程中翎猛,也嘗試過多種方法,最后想到寫一篇文章總結(jié)一下接剩,也希望能對之后學(xué)習(xí)Unity的同學(xué)有一些幫助切厘。
1.利用碰撞器的觸發(fā)器Trigger
????這種是比較基礎(chǔ)的做法,利用OnTriggerEntry函數(shù)懊缺,當(dāng)目標(biāo)進(jìn)入觸發(fā)器時觸發(fā)疫稿。例如玩家有一把劍,我要做攻擊判定的話鹃两,我就可以在劍上掛一個觸發(fā)器遗座,設(shè)定好大小,當(dāng)播放動畫時俊扳,隨著劍的揮動途蒋,目標(biāo)會進(jìn)入Trigger的范圍,此時就會調(diào)用OnTriggerEntry函數(shù)拣度。但是這樣做有個弊端碎绎,如果揮舞速度太快,檢測會有問題抗果;還有就是必須滿足“進(jìn)入”這個條件,也就是說如果原來目標(biāo)就在觸發(fā)器范圍內(nèi)奸晴,或者觸發(fā)器在目標(biāo)內(nèi)冤馏,是不會觸發(fā)函數(shù)的。所以這種方法不太適用于3D游戲寄啼。
????不過這種方法也不是不能用逮光,只是適用條件有限,在2D游戲上墩划,結(jié)合上Animation的錄制功能涕刚,通過動畫來改變Trigger的大小,這樣就可以觸發(fā)OnTriggerEntry函數(shù)一次或者多次乙帮,這樣也是可以做出不錯效果的杜漠。在3D游戲中,可以在人物前面放置一個大小合適Trigger當(dāng)做攻擊范圍,再結(jié)合動畫事件進(jìn)行攻擊判定驾茴,不過這樣做的缺點是攻擊范圍大小恒定盼樟,如果人物的攻擊范圍大小不一,就要創(chuàng)建很多空子物體來設(shè)定Trigger范圍锈至,腳本也不好管理晨缴。
2.利用向量
????可以定義兩個向量作為攻擊范圍,向量有方向也有長度峡捡,攻擊范圍是可以確定的击碗。例如設(shè)定兩個向量,向量1為Transform.forward的左偏45度们拙,向量2為Transform.forward的右偏45度稍途,長度均為5。此時攻擊范圍為半徑為5睛竣,度數(shù)為90°的扇形晰房。此時就可以計算敵人是不是在攻擊范圍內(nèi),可以通過Vector3.Angle來計算(角度制)射沟,Vector3.Distance來計算距離殊者。
????這種方法的局限在于1.如何獲取到敵人的游戲物體,可以通過觸發(fā)器也可以遍歷你的敵人列表验夯。2.當(dāng)敵人體積過大時猖吴,有可能身體的一部分已經(jīng)進(jìn)入攻擊范圍,但是postion沒有進(jìn)入攻擊范圍挥转,此時判定就會出現(xiàn)錯誤海蔽。看情況使用绑谣。
3.利用射線Raycast
????使用Physics.Raycast()這個方法來發(fā)射射線党窜,當(dāng)射線碰到物體,或者碰到指定Laymask層的物體借宵,或者一定距離后就會返回幌衣,返回值是Bool類型。通過out關(guān)鍵字來輸出碰撞到的物體的信息壤玫,變量類型為RaycastHit豁护。例如我定義一個射線Ray ray =new Ray(), 一個射線返回RaycastHit hit,那么就應(yīng)該這么使用Physics.Raycast(ray,out hit),表示碰到物體欲间,就會返回ture楚里,物體信息儲存在hit中。沒有碰到猎贴,就會范圍false班缎,hit為null蝴光。這個方法還有很多重載,可以自己查閱API吝梅,根據(jù)情況使用虱疏。
? ? 這種方法是射擊游戲的常用判斷方法,可以結(jié)合lineRender來渲染子彈飛過的特效苏携。不過這種方法也不是萬能的做瞪,它的局限在于射出射線的點只有一個,用來做射擊游戲的攻擊判定是非常合適的右冻,但是不能用來做判定比較嚴(yán)格的游戲装蓬。為什么呢,因為射擊游戲的發(fā)射方向是可以根據(jù)準(zhǔn)星調(diào)整的纱扭,視覺上的判定也是準(zhǔn)星方向牍帚,如果是動作游戲,rpg游戲之類的乳蛾,攻擊類型多樣暗赶,就會出現(xiàn)差錯。例如一個從上至下的斬?fù)羲嘁叮舴秶鷳?yīng)該是豎著的一條線蹂随,那么射線應(yīng)該怎發(fā)射呢?如果直直的往前發(fā)射因惭,那么當(dāng)敵人蹲下的時候岳锁,就會檢測不到。你或許會想做成動作模式不就完了嗎蹦魔?(就是類似于龍之谷的操作方式)滨攻,也是不行的蛔屹,判定始終在攻擊軌跡中央,和攻擊動畫和攻擊特效有出入轮洋。
4.利用射線Linecast
? ? 這也是Physics的一個方法愕鼓, Physics.Linecast()愿题。連接兩個點形成線段桂肌,如果線段中間有物體狰闪,就返回true,否則返回flase,同樣表制,這個方法需要定義一個RaycastHit類型的變量來接收返回數(shù)據(jù),具體方法為Physics.Linecast(Vector3?point1,?Vector3?point2控乾,out hit)么介。這種方法需要在武器或者拳頭或者其他的需要攻擊判定的地方設(shè)定一個點,當(dāng)動畫播放時蜕衡,這個點的世界坐標(biāo)就會變化壤短,此時我們可以選擇記錄某幾個時間點上判定點的世界坐標(biāo),再用Linecast進(jìn)行判定。一般取判定點的坐標(biāo)的話我們同樣可以利用動畫事件久脯。
? ? 這種方法調(diào)試的時候最好用lineRender把攻擊軌跡渲染出來纳胧,或者用Debug.DrawLine()畫出來(記得設(shè)定存在時間,不然一瞬間就消失了看不到)帘撰,這樣可以方便調(diào)整我們?nèi)∨卸c的時間節(jié)點跑慕,不然可能會疑惑,明明我設(shè)定好了摧找,怎么檢測不到核行。這種方法適合于動作游戲,以及一些判定比較精細(xì)的游戲蹬耘。需要注意的一點是芝雪,Linecast每一幀都會進(jìn)行判定,一般我們只需要一個動作判定一次综苔,那么還需要在代碼里進(jìn)行約束惩系。
上面大概就是我能想到的四種攻擊判定的方法,每個方法也有每個方法是適用范圍如筛,資源消耗也不同堡牡,還是要視情況選擇使用。我最開始做的時候也在網(wǎng)上搜了很久如何做攻擊判定妙黍,這里寫個文章悴侵,希望對新學(xué)習(xí)unity的同學(xué)有幫助,同時也算做個總結(jié)拭嫁,如果有說錯的地方還請指出可免。(轉(zhuǎn)載請注明出處)