Unity 3種攻擊判斷算法 適用於小兵,防御塔之類的會主動攻擊的敵人


        在我們正常的開發過程中,除了一些必要的射線檢測,為了性能着想,我們都會盡可能的不使用unity的物理系統,因為unity為了讓物體具備真實的運動效果,通常底層會有大量的算法,就比如collider的觸發器,看似一句api就搞定的觸發,實際上底層經過大量的運算,這種運算是十分消耗性能的。當然,如今我們處在性能過盛的時代,大多數人不必要考慮這方面的消耗,但是就我而言,性能這東西,能摳一點是一點,等到你的游戲成型之后,你就會有大驚喜,這也就是為什么Unity開發為什么非常注重優化的原因。項目往往到了中期,老大打手一呼,全部人手里活先停一停,搞一波優化再開工,這樣的事情屢見不鮮。

        我們在開發一些比較大型的3D游戲過程中,邏輯代碼非常多,很多技能,位置的運算其實是很復雜的,如果每個小兵、防御塔之類的都用觸發器,那么1000個小兵就是1000個觸發器,這是很恐怖的,為了不增加CPU的壓力,使得游戲更加流暢,我們就會自己使用公式去模擬一些物理行為。如果你只是開發一個小型的,休閑益智的小游戲,就沒有必要糾結這些了,物理系統該上就上,這些游戲大多時間短任務急,內容也不多,用物理系統能給自己省不少事情。這里會寫3種算法,個人改良的,感覺比較好用比較實用,所以記錄下來。

一、圓形攻擊判斷

       圓形適用於360度無死角的檢測,就像英雄聯盟,一旦你進入防御塔的攻擊范圍,無論你是在哪個位置,打你沒商量,這種算法是最簡單的,也不需要很多的位置運算,邏輯就是以防御塔自身為圓心,觸發攻擊的范圍是半徑(這個自己設定,看各自的需求),計算圓心與英雄根節點的距離再跟半徑對比,通常會有三個結果,圓上,圓內,圓外加上自己的邏輯即可,下圖的邏輯就跟農葯一樣,當你到一定范圍,先是警示,再進去就發動攻擊。

 1  /// <summary>
 2     /// 圓形攻擊判斷
 3     /// </summary>
 4     /// <param name="hero">英雄方位</param>
 5     /// <param name="attackRadius">攻擊距離</param>
 6     /// <param name="warnningRadius">警告距離</param>
 7     void RoundAttackLogic(Transform hero,float attackRadius,float warnningRadius)
 8     {
 9         float tmpDis = Vector3.Distance(hero.position, transform.position);
10         if (tmpDis > attackRadius)
11         {
12             if (tmpDis <= warnningRadius)
13             {
14                 //警告
15             }
16         }
17         else
18         {
19             //攻擊
20         }
21     }

 

 

二、扇形攻擊判斷

       扇形攻擊是從圓形攻擊演變而來,復雜了那么一丟丟。圓形攻擊判斷是360無死角的,那么策划同學過來了,說我現在不做防御塔了,我要做一個燈塔。好樣的,那么這樣再繼續使用圓形攻擊判斷顯然是不行的。大家都知道,燈塔是從一點出發,越往遠處照射范圍就越大,還有一點,就是燈塔照射范圍存在角度,並不是周圍全部掃描,就類似於一個扇形。算法邏輯還是先算距離,但是這里不同的是算扇形原點和英雄之間的向量,因為現在存在角度需求,我們必須用向量,因為向量有大小有方向,我們能算出角度,這樣才符合需求。讓燈塔的Z軸永遠處於照射角度的中分線上,做燈塔圓心與英雄之間的向量AB,之后AB的單位向量與Z的單位向量做向量的點乘(不明白的去看一下向量的知識,由AB 點乘 Z = |AB| |Z| COSX 變形而來),這樣可以得到兩個向量之間的角度余弦值,通過反三角函數Acos得到弧度,之后弧度轉角度得到向量之間的夾角,AB的模就是圓心距離英雄的距離,那么現在夾角有了,距離有了,就完事具備了。

 

 1  /// <summary>
 2     /// 扇形攻擊邏輯判斷
 3     /// </summary>
 4     /// <param name="hero">英雄坐標</param>
 5     /// <param name="attackAngle">攻擊角度</param>
 6     /// <param name="attackRadius">攻擊半徑</param>
 7     void SectorAttack(Transform hero,float attackAngle,float attackRadius)
 8     {
 9         Vector3 tmpVec = hero.position - transform.position;
10         float cosValue = Vector3.Dot(tmpVec.normalized, transform.forward);
11         float realAngle = Mathf.Acos(cosValue) * Mathf.Rad2Deg;
12         if (realAngle <= attackAngle / 2 && tmpVec.magnitude <= attackRadius)
13         {
14             //攻擊
15         }
16     }

 

 

三、矩形攻擊判斷

       做完了上面那些,那么恭喜你,策划同學又該來找你了(哈哈哈哈哈哈),這次策划同學說我們不做防御塔,也不做燈塔了,我們改防御強吧。需求是這樣的,牆面向外延伸發電,進到觸犯范圍就直接放電攻擊。這下好了,扇形,圓形都不能用了,給你來方形了,半圓是不能代替矩形,這樣就會導致我還沒進入范圍,你就開始攻擊,這不合邏輯。於是就有了矩形攻擊判定,思想是一樣的,做向量,然后向量點乘,這里對比扇形的向量計算又是不一樣的,注意了!還是前面一樣,做牆根節點與英雄的向量AB,然后與牆前方的單位向量做點乘(這里為什么是前方呢,你見過哪個防御強是防着牆后自己人的...),注意啦!!!這里我沒有說AB的單位向量!!!而是直接用AB向量來點乘!!!還是上面的公式變形,當兩個向量點乘,其中一個向量為單位向量時,得到的是另外一條向量在這條單位向量方向上投影長,而矩形攻擊正式用到這個概念。現在沒有半徑,那我們就算英雄是否牆前方規定的范圍內,AB點乘牆的forward,得到AB在不在牆的防御范圍內,也得到了在牆的前方還是后方,沒錯,這個點乘出來的值是有正有負的,前面說到,兩個向量點乘,也能得到其夾角的余弦值,這也很好的反應了身前身后的問題,算出來的值,以牆的forward的0度,0-90 大於0, 90-270小於0, 270-360大於0,這既是投影長也是余弦值。同樣的方法再用於左右兩側,就能知道到底在不在范圍了。

 

 1 /// <summary>
 2     /// 矩形攻擊判定
 3     /// </summary>
 4     /// <param name="hero">英雄</param>
 5     /// <param name="forwardAttack">前方防御范圍</param>
 6     /// <param name="sizeAttack">左右防御范圍</param>
 7     void RectAttack(Transform hero, float forwardAttack, float sizeAttack)
 8     {
 9         Vector3 delteA = hero.position - transform.position;
10         float forwardDis = Vector3.Dot(delteA, transform.forward);
11         if (forwardDis <= forwardAttack && forwardDis > 0)
12         {
13             float bothSize = Mathf.Abs(Vector3.Dot(delteA, transform.right));//能進到這里說明前方滿足條件,而左右兩邊正負都行,所以只判斷距離
14             if (bothSize < sizeAttack)
15             {
16                 //攻擊
17             }
18         }
19     }

 

 最后,這里面都是用的向量的知識,我只能這么說,如果你做Unity開發,向量,矩陣是必須會的東西,不用深刻理解,但至少得明白什么意思,這些知識不止運用於方位坐標的運算,包括shader的頂點計算,像素計算都會使用到,不明白的建議補一下該方面的知識

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM