# SkillRang **Repository Path**: shirln/skill-rang ## Basic Information - **Project Name**: SkillRang - **Description**: 技能攻击范围判断 - **Primary Language**: C# - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 1 - **Created**: 2021-10-14 - **Last Updated**: 2023-02-24 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ## 前言 最近英雄联盟手游开启不删档测试,对于忠实的lol玩家来说,又激起了我对手游的兴趣。赶紧趁着开服,果断删掉所有手游,清理一波内存,开启我的手游版lol体验。(没办法手机内存太小了)。果断跳过新手教程开始匹配赛,终于到达10级了,又赶紧体验了几把排位赛,虽然体验后觉得端游更胜一筹,但是就凭手游方便的特点,我依然把它保留在了手机了。 激烈的混战中,出现如下画面: 本队小姐姐一个接一个的送人头,这时候暴躁哥出现了,开始一顿狂bibi。 小姐姐也很无奈:她的手太长了,为什么我就打不到他~。 ## 攻击范围定义 作为一个lol忠实粉丝and游戏开发者来,我必须来为大家分析一下攻击范围:顾名思义,攻击范围就是释放技能后,会对进入这个范围的敌方单位造成伤害一定英雄,包括伤害,眩晕等。 那么我方释放了一个技能,该技能存在一个攻击范围,如何判断敌方是否在该范围内受到影响? ## 矩形攻击范围 向正前方释放一个技能,当攻击范围为一个矩形(a,b)时,判断敌方是否受到伤害,需满足三个条件 (1)敌方位于我放方正前方 (2)敌方位于a长度内 (3)敌方位于b宽度内 游戏中场景转换成如下示意图: ![在这里插入图片描述](https://img-blog.csdnimg.cn/1e5b20d04733461e906a9b56e4b626a7.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA54ix5LiK5ri45oiP5byA5Y-R,size_19,color_FFFFFF,t_70,g_se,x_16) 翻译成数学语言: (1)两向量点积>0 (2)在a上的投影0) { } ``` (2)水平方向投影判断 ```java float horizontal = Vector3.Project(direction, hero_a.right).magnitude;//水平方向投影 if (horizontal <= length/2) { } ``` (3)垂直方向投影判断 ```java float vertical = Vector3.Project(direction, hero_a.forward).magnitude;//垂直方向投影 if (vertical <= width) { } ``` (4)绘制攻击范围 ```java private void OnDrawGizmos() { Handles.color = isShow ? Color.cyan : Color.red; Vector3 cornerA = hero_a.position + Vector3.left * width * .5f; Vector3 cornerB = hero_a.position + Vector3.right * width * .5f; Vector3 cornerC = cornerB + Vector3.forward * length; Vector3 cornerD = cornerA + Vector3.forward * length; Handles.DrawLine(cornerA, cornerB); Handles.DrawLine(cornerB, cornerC); Handles.DrawLine(cornerC, cornerD); Handles.DrawLine(cornerD, cornerA); } ``` ![在这里插入图片描述](https://img-blog.csdnimg.cn/1cfce40cd06741358e51139fd2e51d55.gif#pic_center) 完整脚本: ```java using UnityEngine; using UnityEditor; public class SkillRang : MonoBehaviour { public float length = 1f;//矩形长 public float width = 1f;//矩形宽 private bool isShow = false;//是否处于攻击范围 private Transform hero_a;//我方英雄 private Transform hero_b;//敌方英雄 // Start is called before the first frame update void Start() { hero_a = GameObject.Find("hero_a").transform; hero_b = GameObject.Find("hero_b").transform; } // Update is called once per frame void Update() { RectRang(); } private void RectRang() { //方形区域 Vector3 forward = hero_a.forward; Vector3 direction = hero_b.position - hero_a.position; float dot = Vector3.Dot(forward,direction); if (dot >0) { //在前方 float vertical = Vector3.Project(direction, hero_a.forward).magnitude;//垂直方向投影 float horizontal = Vector3.Project(direction, hero_a.right).magnitude;//水平方向投影 if (vertical <= width && horizontal <= length/2) { isShow = true; return; } } isShow = false; } private void OnDrawGizmos() { Handles.color = isShow ? Color.cyan : Color.red; Vector3 cornerA = hero_a.position + Vector3.left * length * .5f; Vector3 cornerB = hero_a.position + Vector3.right * length * .5f; Vector3 cornerC = cornerB + Vector3.forward * width; Vector3 cornerD = cornerA + Vector3.forward * width; Handles.DrawLine(cornerA, cornerB); Handles.DrawLine(cornerB, cornerC); Handles.DrawLine(cornerC, cornerD); Handles.DrawLine(cornerD, cornerA); } } ``` ## 圆形攻击范围 释放一个技能,当攻击范围为一个矩形(半径为r)时,判断敌方是否受到伤害,需满足一个条件: (1)敌人处在一个圆内或者圆上。该圆是以释放技能处未圆心,r为半径的圆。 游戏中场景转换成如下示意图: ![在这里插入图片描述](https://img-blog.csdnimg.cn/35e97dce88f0416aafde791467e26463.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA54ix5LiK5ri45oiP5byA5Y-R,size_18,color_FFFFFF,t_70,g_se,x_16) 翻译成数学语言: (1)![在这里插入图片描述](https://img-blog.csdnimg.cn/44e3faa03f9342c0b2b2366a1d41dfc6.png) 假设攻击范围半径为radius (1)距离计算 ```java Vector3 pos_a = hero_a.position; Vector3 pos_b = hero_b.position; float distence = Mathf.Sqrt((pos_a.x-pos_b.x)*(pos_a.x-pos_b.x)+(pos_a.y-pos_b.y)*(pos_a.y-pos_b.y)); ``` (2)距离判断 ```java if (distence <= radius) { } ``` (3)绘制攻击范围 ```java private void OnDrawGizmos() { Handles.color = isShow ? Color.cyan : Color.red; Handles.CircleHandleCap(0,hero_a.position,hero_a.rotation * Quaternion.LookRotation(Vector3.up),radius,EventType.Repaint); } ``` ![在这里插入图片描述](https://img-blog.csdnimg.cn/4355285d0e1b4cc884c02a6f2bc1aae7.gif#pic_center) 完整脚本: ```java using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEditor; public class SkillRang : MonoBehaviour { public float radius = 1f;//圆形半径 private bool isShow = false;//是否处于攻击范围 private Transform hero_a;//我方英雄 private Transform hero_b;//敌方英雄 // Start is called before the first frame update void Start() { hero_a = GameObject.Find("hero_a").transform; hero_b = GameObject.Find("hero_b").transform; } // Update is called once per frame void Update() { CricleRang(); } private void CricleRang() { // 圆形区域 Vector3 pos_a = hero_a.position; Vector3 pos_b = hero_b.position; float distence = Mathf.Sqrt((pos_a.x-pos_b.x)*(pos_a.x-pos_b.x)+(pos_a.y-pos_b.y)*(pos_a.y-pos_b.y)); if (distence <= radius) { isShow = true; } else { isShow = false; } } private void OnDrawGizmos() { Handles.color = isShow ? Color.cyan : Color.red; Handles.CircleHandleCap(0,hero_a.position,hero_a.rotation * Quaternion.LookRotation(Vector3.up),radius,EventType.Repaint); } } ``` 注意:本文参考自https://blog.csdn.net/qq_42139931/article/details/120712908