Unity 如何实现游戏中技能的扇形攻击范围

举报
CoderZ1010 发表于 2022/09/25 04:51:08 2022/09/25
【摘要】 假设人物A向正前方释放一个技能,攻击范围为一个扇形,如何判断人物B是否在该范围内受到攻击。         1. 向量A的正前方forward 与 A指向B的向量direction 的角度offsetAngle小于扇形角度的1/2        ...

假设人物A向正前方释放一个技能,攻击范围为一个扇形,如何判断人物B是否在该范围内受到攻击。

        1. 向量A的正前方forward 与 A指向B的向量direction 的角度offsetAngle小于扇形角度的1/2

        2. 向量direction的模长magnitude,即A到B的距离小于半径

        满足上面这两个条件即可判断B在扇形区域内,涉及的运算:点乘积、反余弦


  
  1. /// <summary>
  2. /// 判断target是否在扇形区域内
  3. /// </summary>
  4. /// <param name="sectorAngle">扇形角度</param>
  5. /// <param name="sectorRadius">扇形半径</param>
  6. /// <param name="attacker">攻击者的transform信息</param>
  7. /// <param name="target">目标</param>
  8. /// <returns>目标target在扇形区域内返回true 否则返回false</returns>
  9. public bool IsInRange(float sectorAngle, float sectorRadius, Transform attacker, Transform target)
  10. {
  11. //攻击者位置指向目标位置的向量
  12. Vector3 direction = target.position - attacker.position;
  13. //点乘积结果
  14. float dot = Vector3.Dot(direction.normalized, transform.forward);
  15. //反余弦计算角度
  16. float offsetAngle = Mathf.Acos(dot) * Mathf.Rad2Deg; //弧度转度
  17. return offsetAngle < sectorAngle * .5f && direction.magnitude < sectorRadius;
  18. }

扇形范围由扇形的角度和半径构成,定义变量:


  
  1. //扇形角度
  2. [SerializeField] private float angle = 80f;
  3. //扇形半径
  4. [SerializeField] private float radius = 3.5f;
  5. //物体B
  6. [SerializeField] private Transform b;

 定义bool类型变量flag,用来记录判断结果:


  
  1. private bool flag;
  2. private void Update()
  3. {
  4. flag = IsInRange(angle, radius, transform, b);
  5. }

完整测试脚本:


  
  1. using UnityEngine;
  2. using UnityEditor;
  3. public class Foo : MonoBehaviour
  4. {
  5. //扇形角度
  6. [SerializeField] private float angle = 80f;
  7. //扇形半径
  8. [SerializeField] private float radius = 3.5f;
  9. //物体B
  10. [SerializeField] private Transform b;
  11. private bool flag;
  12. private void Update()
  13. {
  14. flag = IsInRange(angle, radius, transform, b);
  15. }
  16. /// <summary>
  17. /// 判断target是否在扇形区域内
  18. /// </summary>
  19. /// <param name="sectorAngle">扇形角度</param>
  20. /// <param name="sectorRadius">扇形半径</param>
  21. /// <param name="attacker">攻击者的transform信息</param>
  22. /// <param name="target">目标</param>
  23. /// <returns>目标target在扇形区域内返回true 否则返回false</returns>
  24. public bool IsInRange(float sectorAngle, float sectorRadius, Transform attacker, Transform target)
  25. {
  26. //攻击者位置指向目标位置的向量
  27. Vector3 direction = target.position - attacker.position;
  28. //点乘积结果
  29. float dot = Vector3.Dot(direction.normalized, transform.forward);
  30. //反余弦计算角度
  31. float offsetAngle = Mathf.Acos(dot) * Mathf.Rad2Deg;
  32. return offsetAngle < sectorAngle * .5f && direction.magnitude < sectorRadius;
  33. }
  34. private void OnDrawGizmos()
  35. {
  36. Handles.color = flag ? Color.cyan : Color.red;
  37. float x = radius * Mathf.Sin(angle / 2f * Mathf.Deg2Rad);
  38. float y = Mathf.Sqrt(Mathf.Pow(radius, 2f) - Mathf.Pow(x, 2f));
  39. Vector3 a = new Vector3(transform.position.x - x, 0f, transform.position.z + y);
  40. Vector3 b = new Vector3(transform.position.x + x, 0f, transform.position.z + y);
  41. Handles.DrawLine(transform.position, a);
  42. Handles.DrawLine(transform.position, b);
  43. float half = angle / 2;
  44. for (int i = 0; i < half; i++)
  45. {
  46. x = radius * Mathf.Sin((half - i) * Mathf.Deg2Rad);
  47. y = Mathf.Sqrt(Mathf.Pow(radius, 2f) - Mathf.Pow(x, 2f));
  48. a = new Vector3(transform.position.x - x, 0f, transform.position.z + y);
  49. x = radius * Mathf.Sin((half - i - 1) * Mathf.Deg2Rad);
  50. y = Mathf.Sqrt(Mathf.Pow(radius, 2f) - Mathf.Pow(x, 2f));
  51. b = new Vector3(transform.position.x - x, 0f, transform.position.z + y);
  52. Handles.DrawLine(a, b);
  53. }
  54. for (int i = 0; i < half; i++)
  55. {
  56. x = radius * Mathf.Sin((half - i) * Mathf.Deg2Rad);
  57. y = Mathf.Sqrt(Mathf.Pow(radius, 2f) - Mathf.Pow(x, 2f));
  58. a = new Vector3(transform.position.x + x, 0f, transform.position.z + y);
  59. x = radius * Mathf.Sin((half - i - 1) * Mathf.Deg2Rad);
  60. y = Mathf.Sqrt(Mathf.Pow(radius, 2f) - Mathf.Pow(x, 2f));
  61. b = new Vector3(transform.position.x + x, 0f, transform.position.z + y);
  62. Handles.DrawLine(a, b);
  63. }
  64. }
  65. }

文章来源: coderz.blog.csdn.net,作者:CoderZ1010,版权归原作者所有,如需转载,请联系作者。

原文链接:coderz.blog.csdn.net/article/details/120699375

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。