众所周知moba中的每个英雄都有一套自己的技能的攻击范围方式,有如廉颇一样的圆形范围,有火舞一样的直线范围,吕布的扇形方天戟范围,还有上图的牛魔大招时的矩形范围等等。

一些技能是通过物理的碰撞检测来判断的,一些则是通过这样的范围来检测的。物理检测的诟病就在于开销过大,在能考虑不用物理来检测的情况下更倾向来自己通过算法模拟实现。

小菜的学习研究中,将这些自己算法检测的攻击范围划分了几种类型,并做了几个demo的演示。

如上演示,小菜简单的讲这些类型划分成了如下几类:

1). Circle                        圆形

2). Triangle                    三角形

3). Fanshaped                扇形

4). Rectangle                 矩形

5). Sector                       扇面

6). Ring                          环形

[Circle 圆形]

这应该是最简单的类型,只要去判断self和target的distance就可以做到了。

我们希望能直观看到范围的情况,故使用Debug.DrawLine做了调试的绘制。

绘制编码:

小菜不想由于各个对象高度的不同带来的检测差异,故用NormalizePosition将位置的y信息都归置成了0。

范围检测编码:

[Triangle 三角形]

三角形范围的判定,实际就是点在三角形内的判定。

数学上检测点在三角形内有三种推论方法。内角和法/同向法/重心法。

对数学感兴趣的可以参考:https://www.cnblogs.com/graphics/archive/2010/08/05/1793393.html

小菜这里直接套用了重心法检测。

检测编码:

绘制编码:

[Fanshaped 扇形]

扇形的范围检测我们实际可以抽象成两个步骤。

1).判断self和target的distance.

2).由于点乘,使用点乘dot来计算self到target的单位向量,与self的forward向量(本身也是单位向量)来计算得夹角cos值。使用Mathf.Acos将其转化为弧度,再转换成角度做一次判断就好了。

绘制编码:

范围检测编码:

[Rectangle 矩形]

矩形的检测小菜大概是有两种方法:

1).通过点在矩形内的数学推导公式来计算。

2).通过点乘和distance来计算。

还是先将矩形绘制出来吧。

绘制编码:

范围检测:

通过点在矩形内的数学推导公式来计算矩形范围

判断一个点是否在两条线段之间夹着就转化成,判断一个点是否在某条线段的一边上,就可以利用叉乘的方向性,来判断夹角是否超过了180度 。

只要判断(AB X AE ) * (CDX CE)  >= 0 就说明E在AB,CD中间夹着,同理计算另两边DA和BC就可以了。

最后就是只需要判断

(AB X AE ) * (CD X CE)  >= 0 && (DA X DE ) * (BC X BE) >= 0 。

范围检测编码:

通过点乘和distance来计算矩形范围

还是先上一张图辅助理解吧。

两次点乘的结果在于判断target的前后和左右关系。

编码看似比上面的少很多,实际关联的理解可一点都不简单

[Sector 扇面]

扇面和扇形的检测很相似,不同的只是多了一层距离的检测。

绘制编码:

范围检测编码:

[Ring 环形]

环形和圆形的检测很相似,也只是多了一层距离的检测。

绘制编码:

范围检测编码:

附上完整代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public enum CheckType
{None,/// <summary> 圆形 </summary>Circle,/// <summary> 三角形 </summary>Triangle,/// <summary> 扇形 </summary>Fanshaped,/// <summary> 矩形 </summary>Rectangle,/// <summary> 扇面 </summary>Sector,/// <summary> 环形 </summary>Ring,
}[ExecuteInEditMode]
public class RangeCheckScript : MonoBehaviour
{public CheckType currType = CheckType.None;public Transform mPalyer;public Transform mTarget;public bool mCheckOpen = true;void Update(){if (!mCheckOpen)return;if (null != mPalyer)Debug.DrawLine(mPalyer.position, mPalyer.position + mPalyer.forward * 8,Color.yellow);bool bResult = false;switch (currType){case CheckType.None:break;case CheckType.Circle:bResult = CircleCheck(mPalyer, mTarget, 6);break;case CheckType.Triangle:bResult = TriangleCheck(mPalyer, mTarget, 1, 10);break;case CheckType.Fanshaped:bResult = FanshapedCheck(mPalyer, mTarget, 45, 5);break;case CheckType.Rectangle://bResult = SimulateRectangleCheck(mPalyer, mTarget, 2, 8);bResult = RectangleCheck(mPalyer, mTarget, 2, 8);break;case CheckType.Sector:bResult = SectorCheck(mPalyer, mTarget, 45, 5, 8);break;case CheckType.Ring:bResult = RingCheck(mPalyer, mTarget, 4, 8);break;default:break;}if (bResult)Debug.LogError("检测到目标");}/// <summary>/// 圆形范围检测/// </summary>private bool CircleCheck(Transform self, Transform target, float distance){if (null == self || null == target)return false;//---------------------绘制图形-----------------------------------Vector3 selfPosition = NormalizePosition(self.position);Vector3 targetPosition = NormalizePosition(target.position);int nCircleDentity = 360;Vector3 beginPoint = selfPosition;Vector3 endPoint = Vector3.zero;float tempStep = 2 * Mathf.PI / nCircleDentity;bool bFirst = true;for (float step = 0; step < 2 * Mathf.PI; step += tempStep){float x = distance * Mathf.Cos(step);float z = distance * Mathf.Sin(step);endPoint.x = selfPosition.x + x;endPoint.z = selfPosition.z + z;if (bFirst)bFirst = false;elseDebug.DrawLine(beginPoint, endPoint, Color.red);beginPoint = endPoint;}//---------------------范围检测-----------------------------------float currDistance = Vector3.Distance(selfPosition, targetPosition);if (currDistance <= distance)return true;return false;}/// <summary>/// 三角形范围检测/// </summary>private bool TriangleCheck(Transform self, Transform target, float halfWidth,float distance){if (null == self || null == target)return false;//---------------------绘制图形-----------------------------------Vector3 selfPosition = NormalizePosition(self.position);Vector3 targetPosition = NormalizePosition(target.position);Quaternion tempQuat = self.rotation;//三角形的三个点Vector3 leftPoint = selfPosition + (tempQuat * Vector3.left) * halfWidth;Vector3 rightPoint = selfPosition + (tempQuat * Vector3.right) * halfWidth;Vector3 forwardPoint = selfPosition + (tempQuat * Vector3.forward) * distance;Debug.DrawLine(leftPoint,rightPoint,Color.red);Debug.DrawLine(rightPoint, forwardPoint, Color.red);Debug.DrawLine(forwardPoint, leftPoint, Color.red);//---------------------范围检测-----------------------------------bool bResult = IsPointInTriangle(leftPoint, forwardPoint, rightPoint, targetPosition);return bResult;}/// <summary>/// 扇形范围检测/// </summary>private bool FanshapedCheck(Transform self, Transform target, float halfAngle, float distance){if (null == self || null == target)return false;//---------------------绘制图形-----------------------------------Vector3 selfPosition = NormalizePosition(self.position);Vector3 targetPosition = NormalizePosition(target.position);Quaternion selfQuat = self.rotation;int nCircleDentity = 360;Vector3 firstPoint = Vector3.zero;Vector3 beginPoint = selfPosition;Vector3 endPoint = Vector3.zero;float tempStep = 2 * Mathf.PI / nCircleDentity;float leftRadian =  Mathf.PI / 2  + Mathf.Deg2Rad * halfAngle;float rightRadian = Mathf.PI / 2 - Mathf.Deg2Rad * halfAngle;bool bFirst = true;for (float step = 0; step < 2 * Mathf.PI; step += tempStep){float x = distance * Mathf.Cos(step);float z = distance * Mathf.Sin(step);endPoint.x = selfPosition.x + x;endPoint.z = selfPosition.z + z;if (step >= rightRadian && step <= leftRadian){if (bFirst){firstPoint = endPoint;bFirst = false;}Debug.DrawLine(beginPoint, endPoint, Color.red);beginPoint = endPoint;}}Debug.DrawLine(selfPosition, firstPoint, Color.red);Debug.DrawLine(selfPosition, beginPoint, Color.red);//---------------------范围检测-----------------------------------//计算距离float currDis = Vector3.Distance(selfPosition, targetPosition);if (currDis > distance)return false;//计算self到target的向量Vector3 dir = targetPosition - selfPosition;//点乘dir向量和自身的forward向量 cosqfloat dotForward = Vector3.Dot(dir.normalized, (selfQuat * Vector3.forward).normalized);//得到夹角弧度并转换成角度float radian = Mathf.Acos(dotForward);float currAngle = Mathf.Rad2Deg * radian;if (Mathf.Abs(currAngle) <= halfAngle)return true;return false;}/// <summary>///  矩形范围检测(数学点和矩形关系判断)/// </summary>private bool SimulateRectangleCheck(Transform self, Transform target, float halfWidth, float distance){if (null == self || null == target)return false;//---------------------绘制图形-----------------------------------Vector3 selfPosition = NormalizePosition(self.position);Vector3 targetPosition = NormalizePosition(target.position);Vector3 selfEulerAngles = self.rotation.eulerAngles;Quaternion selfQuat = self.rotation;//矩形的四个点Vector3 leftPoint = selfPosition + (selfQuat * Vector3.left) * halfWidth;Vector3 rightPoint = selfPosition + (selfQuat * Vector3.right) * halfWidth;Vector3 leftUpPoint = leftPoint + (selfQuat * Vector3.forward) * distance;Vector3 rightUpPoint = rightPoint + (selfQuat * Vector3.forward) * distance;Debug.DrawLine(selfPosition, leftPoint, Color.red);Debug.DrawLine(selfPosition, rightPoint, Color.red);Debug.DrawLine(leftPoint, leftUpPoint, Color.red);Debug.DrawLine(rightPoint, rightUpPoint, Color.red);Debug.DrawLine(leftUpPoint, rightUpPoint, Color.red);//---------------------范围检测-----------------------------------Vector2 point = Vector2.zero;point.x = targetPosition.x;point.y = targetPosition.z;Vector2 point1 = Vector2.zero;point1.x = leftUpPoint.x;point1.y = leftUpPoint.z;Vector2 point2 = Vector2.zero;point2.x = rightUpPoint.x;point2.y = rightUpPoint.z;Vector2 point3 = Vector2.zero;point3.x = rightPoint.x;point3.y = rightPoint.z;Vector2 point4 = Vector2.zero;point4.x = leftPoint.x;point4.y = leftPoint.z;bool bResult = IsPointInRectangle(point1, point2, point3, point4, point);return bResult;}/// <summary>/// 矩形范围检测(点乘方式)/// </summary>private bool RectangleCheck(Transform self, Transform target, float halfWidth, float distance){if (null == self || null == target)return false;//---------------------绘制图形-----------------------------------Vector3 selfPosition = NormalizePosition(self.position);Vector3 targetPosition = NormalizePosition(target.position);Vector3 selfEulerAngles = self.rotation.eulerAngles;Quaternion selfQuat = self.rotation;//矩形的四个点Vector3 leftPoint = selfPosition + (selfQuat * Vector3.left) * halfWidth;Vector3 rightPoint = selfPosition + (selfQuat * Vector3.right) * halfWidth;Vector3 leftUpPoint = leftPoint + (selfQuat * Vector3.forward) * distance;Vector3 rightUpPoint = rightPoint + (selfQuat * Vector3.forward) * distance;Debug.DrawLine(selfPosition, leftPoint, Color.red);Debug.DrawLine(selfPosition, rightPoint, Color.red);Debug.DrawLine(leftPoint, leftUpPoint, Color.red);Debug.DrawLine(rightPoint, rightUpPoint, Color.red);Debug.DrawLine(leftUpPoint, rightUpPoint, Color.red);//---------------------范围检测-----------------------------------//计算self到target的向量Vector3 dir = targetPosition - selfPosition;//点乘dir向量和自身的forward向量float dotForward = Vector3.Dot(dir, (selfQuat * Vector3.forward).normalized);//target处于self的前方的height范围if (dotForward > 0 && dotForward <= distance){float dotRight = Vector3.Dot(dir, (selfQuat * Vector3.right).normalized);//target处于self的左右halfWidth的范围if (Mathf.Abs(dotRight) <= halfWidth)return true;}return false;}/// <summary>/// 扇面范围检测/// </summary>private bool SectorCheck(Transform self, Transform target, float halfAngle, float nearDis, float farDis){if (null == self || null == target)return false;if (nearDis > farDis){float tempDis = nearDis;nearDis = farDis;farDis = tempDis;}//---------------------绘制图形-----------------------------------Vector3 selfPosition = NormalizePosition(self.position);Vector3 targetPosition = NormalizePosition(target.position);Quaternion selfQuat = self.rotation;int nCircleDentity = 360;Vector3 nearFirstPoint = Vector3.zero;Vector3 nearBeginPoint = selfPosition;Vector3 nearEndPoint = Vector3.zero;Vector3 farFirstPoint = Vector3.zero;Vector3 farBeginPoint = selfPosition;Vector3 farEndPoint = Vector3.zero;float tempStep = 2 * Mathf.PI / nCircleDentity;float leftRadian = Mathf.PI / 2 + Mathf.Deg2Rad * halfAngle;float rightRadian = Mathf.PI / 2 - Mathf.Deg2Rad * halfAngle;bool bFirst = true;for (float step = 0; step < 2 * Mathf.PI; step += tempStep){float nearX = nearDis * Mathf.Cos(step);float nearZ = nearDis * Mathf.Sin(step);float farX = farDis * Mathf.Cos(step);float farZ = farDis * Mathf.Sin(step);if (step >= rightRadian && step <= leftRadian){//-------绘制近扇面nearEndPoint.x = selfPosition.x + nearX;nearEndPoint.z = selfPosition.z + nearZ;//-------绘制远扇面farEndPoint.x = selfPosition.x + farX;farEndPoint.z = selfPosition.z + farZ;if (bFirst){nearFirstPoint = nearEndPoint;farFirstPoint = farEndPoint;bFirst = false;}else{Debug.DrawLine(nearBeginPoint, nearEndPoint, Color.red);Debug.DrawLine(farBeginPoint, farEndPoint, Color.red);}nearBeginPoint = nearEndPoint;farBeginPoint = farEndPoint;}}Debug.DrawLine(nearFirstPoint, farFirstPoint, Color.red);Debug.DrawLine(nearEndPoint, farEndPoint, Color.red);Debug.DrawLine(selfPosition, nearFirstPoint, Color.blue);Debug.DrawLine(selfPosition, nearEndPoint, Color.blue);//---------------------范围检测-----------------------------------//计算距离float currDis = Vector3.Distance(selfPosition, targetPosition);if (currDis < nearDis ||  currDis > farDis)return false;//计算self到target的向量Vector3 dir = targetPosition - selfPosition;//点乘dir向量和自身的forward向量 cosqfloat dotForward = Vector3.Dot(dir.normalized, (selfQuat * Vector3.forward).normalized);//得到夹角弧度并转换成角度float radian = Mathf.Acos(dotForward);float currAngle = Mathf.Rad2Deg * radian;if (Mathf.Abs(currAngle) <= halfAngle)return true;return false;}/// <summary>/// 双圆范围检测/// </summary>private bool RingCheck(Transform self, Transform target, float nearDis, float farDis){if (null == self || null == target)return false;if (nearDis > farDis){float tempDis = nearDis;nearDis = farDis;farDis = tempDis;}//---------------------绘制图形-----------------------------------Vector3 selfPosition = NormalizePosition(self.position);Vector3 targetPosition = NormalizePosition(target.position);int nCircleDentity = 360;Vector3 nearBeginPoint = selfPosition;Vector3 nearEndPoint = Vector3.zero;Vector3 farBeginPoint = selfPosition;Vector3 farEndPoint = Vector3.zero;float tempStep = 2 * Mathf.PI / nCircleDentity;bool bFirst = true;for (float step = 0; step < 2 * Mathf.PI; step += tempStep){float nearX = nearDis * Mathf.Cos(step);float nearZ = nearDis * Mathf.Sin(step);nearEndPoint.x = selfPosition.x + nearX;nearEndPoint.z = selfPosition.z + nearZ;float farX = farDis * Mathf.Cos(step);float farZ = farDis * Mathf.Sin(step);farEndPoint.x = selfPosition.x + farX;farEndPoint.z = selfPosition.z + farZ;if (bFirst)bFirst = false;else{Debug.DrawLine(nearBeginPoint, nearEndPoint, Color.red);Debug.DrawLine(farBeginPoint, farEndPoint, Color.red);}nearBeginPoint = nearEndPoint;farBeginPoint = farEndPoint;}//---------------------范围检测-----------------------------------float currDistance = Vector3.Distance(selfPosition, targetPosition);if (currDistance >= nearDis && currDistance <= farDis )return true;return false;}/// <summary>/// 规范位置(去除高度带来的影响)/// </summary>private Vector3 NormalizePosition(Vector3 position,float hight = 0.0f){Vector3 tempPosition = Vector3.zero;tempPosition.x = position.x;tempPosition.y = hight;tempPosition.z = position.z;return tempPosition;}/// <summary>/// 三角形检查/// </summary>private bool IsPointInTriangle(Vector3 point1, Vector3 point2, Vector3 point3, Vector3 targetPoint){Vector3 v0 = point2 - point1;Vector3 v1 = point3 - point1;Vector3 v2 = targetPoint - point1;float dot00 = Vector3.Dot(v0, v0);float dot01 = Vector3.Dot(v0, v1);float dot02 = Vector3.Dot(v0, v2);float dot11 = Vector3.Dot(v1, v1);float dot12 = Vector3.Dot(v1, v2);float inverDeno = 1 / (dot00 * dot11 - dot01 * dot01);float u = (dot11 * dot02 - dot01 * dot12) * inverDeno;if (u < 0 || u > 1)return false;float v = (dot00 * dot12 - dot01 * dot02) * inverDeno;if (v < 0 || v > 1)return false;return u + v <= 1;}/// <summary>/// 判断点p是否在p1 p2 p3 p4构成的矩形内/// </summary>private bool IsPointInRectangle(Vector2 point1, Vector2 point2, Vector2 point3, Vector2 point4, Vector2 point){return GetCross(point1, point2, point) * GetCross(point3, point4, point) >= 0&& GetCross(point2, point3, point) * GetCross(point4, point1, point) >= 0;}/// <summary>/// 计算 |p1 p2| X |p1 p|/// </summary>private float GetCross(Vector2 point1, Vector2 point2, Vector2 point){return ((point2.x - point1.x) * (point.y - point1.y) - (point.x - point1.x) * (point2.y - point1.y));}
}

Unity 攻击范围检测相关推荐

  1. mysql %3c%3e sql优化_SQL注入技术和跨站脚本攻击的检测(2)

    2.3 典型的 SQL 注入攻击的正则表达式 /\w*((\%27)|(\'))((\%6F)|o|(\%4F))((\%72)|r|(\%52))/ix 解释: \w* - 零个或多个字符或者下划线 ...

  2. 【传统网络】与【SDN】的【DDos攻击与检测】

    DDos攻击 什么是 DDoS 攻击? 又有那些著名的案例? 拒绝服务(DoS)攻击可使目标计算机上的系统资源过期.停止服务并使其正常用户无法访问.当黑客使用网络上的两台或多台受攻击的计算机作为傀儡计 ...

  3. 直播笔记 | Unity中射线检测详解

    本文首发于洪流学堂微信公众号. 洪流学堂,学Unity快人几步 你好,我是郑洪智,你的技术探路者. 这周三我们直播剖析了Unity中射线检测的功能,以下是直播内容精华部分笔记. 完整录播:https: ...

  4. 基于SDN环境下的DDoS异常攻击的检测与缓解--实验

    基于SDN环境下的DDoS异常攻击的检测与缓解--实验 基于SDN环境下的DDoS异常攻击的检测与缓解--实验 1.安装floodlight 2.安装sFlow-RT流量监控设备 3.命令行安装cur ...

  5. DDoS攻击流量检测方法

    DDoS攻击流量检测方法 检测分类 1)误用检测 误用检测主要是根据已知的攻击特征直接检测入侵行为.首先对异常信息源建模分析提取特征向量,根据特征设计针对性的特征检测算法,若新数据样本检测出相应的特征 ...

  6. 攻击入侵检测NIDS分析

    时间:2004-06-13 来源:http://www.ccw.com.cn/ 在网络安全发展的今天,IDS即入侵检测系统在网络环境中的使用越来越普遍,当hacker在攻击一个装有IDS的网络服务器时 ...

  7. unity鼠标滑动检测

    Unity鼠标滑动检测 private Vector2 first = Vector2.zero; private Vector2 second = Vector2.zero; void Update ...

  8. Unity官方性能检测工具UPR使用心得

    Unity官方性能检测工具UPR使用心得 UPR是Unity官方推出的免费性能检测工具,近来功能较之前版本完善了许多,经笔者在正式项目中试用,与UWA的免费性能检测工具GPM作对比,发现UPR相较GP ...

  9. 【安全与风险】恶意软件:概念、攻击和检测

    恶意软件:概念.攻击和检测 恶意软件的定义 恶意软件的类型 易损性 如何防范恶意软件:终端用户的观点 不足 防病毒软件 基于主机的恶意软件检测 特征检测 启发式检测 数据收集挑战 沙箱分析 蜜罐 恶意 ...

最新文章

  1. 什么是python第三方库
  2. 手机 html5评测,三款主流手机浏览器HTML5性能横向评测
  3. leetcode 470. 用 Rand7() 实现 Rand10()
  4. [网络安全提高篇] 一一〇.强网杯CTF的Web Write-Up(上) 寻宝、赌徒、EasyWeb、pop_master
  5. java 放行文件_springmvc中关于静态资源的放行
  6. 8-字符串的压缩存储
  7. rc.local介绍(linux启动系列之一)
  8. 网贷大数据什么时候会好_为什么大数据待遇那么好 如何入门大数据行业
  9. 科学网—语音识别技术发展史
  10. 从零实现Word2Vec(上)
  11. SAPJCO3升级3.1后报错java.lang.UnsatisfiedLinkError: sapjco3.dll解决
  12. c语言文件指针重新定向,C语言rewind()函数:将文件指针重新指向文件开头
  13. 计算机管理无法格式化硬盘,自己动手 解决SSD硬盘无法格式化的问题
  14. 运维工程师是桥的护栏_高速公路护栏有哪几种类型?
  15. Java导出Excel每列求和,POI导出excel执行自动求和
  16. Zynga任命Noel Watson为董事会成员
  17. 【知识兔】自学Excel之1:了解Excel 中的基本功能
  18. 关于弹性布局flex
  19. cs/bs以及优缺点
  20. 生产者和消费者问题(单一生产者和单一消费者)

热门文章

  1. python文件处理基础_第六篇:python基础之文件处理
  2. Kamailio nats模块编译
  3. 精心整理!最全的100个Python精选库,建议收藏!
  4. Android获取本机蓝牙地址
  5. 【以太网硬件一】802.3xx标准怎么这么多?它们有什么关系?
  6. nexus5 博通芯片WIFI详解 (2)
  7. 概率论的学习和整理8: 几何分布
  8. 苹果Mac隐藏壁纸在哪里?Mac隐藏壁纸查找教程
  9. 华为手机时间用长了会卡吗?
  10. robotframework框架ui自动化测试上传附件问题