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