当前位置: 首页 > news >正文

unity 2d 近战攻击判定的三种方式以及精确获取碰撞点

精确获取碰撞点

核心是获取武器碰撞盒最顶点,然后获取敌人碰撞盒距离该点最近的点

/// <summary>/// 获取获取武器前端位置   碰撞盒最左或最右顶点/// </summary>/// <param name="collider"></param>/// <param name="facingRight"></param>/// <returns></returns>public static Vector3 GetCollider2DEdgePoint(Transform deployer, bool facingRight){var collider = deployer.GetChild(0).GetComponentInChildren<CapsuleCollider2D>();// 获取碰撞器的包围盒Bounds bounds = collider.bounds;// 计算面向的方向向量(右或左)Vector2 attackDirection = facingRight ? Vector2.right : Vector2.left;// 根据面向方向和碰撞器的边界来获取边缘点Vector3 edgePoint = bounds.center + (Vector3)(attackDirection * bounds.extents.x);// 如果需要在局部空间中获取边缘点,需要将世界坐标转换为局部坐标// edgePoint = deployer.InverseTransformPoint(edgePoint);return edgePoint;}//使用public void CreateHit(Collider2D other, CharacterStats target, bool isCrit = false)Vector3 edgePoint = Tool.GetCollider2DEdgePoint(transform, Entity.facingRight);var hitPosition = other.ClosestPoint(edgePoint);

1. 给攻击帧添加碰撞盒

优点:配置直观,无需事件触发
缺点:无法定制,效率低

检测放在子物体,可以控制旋转
在这里插入图片描述

添加触发器事件

注意OnTriggerEnter2D只会在挂载了collider的组件上触发

protected virtual void OnTriggerEnter2D(Collider2D other){Debug.Log(this.name + "命中" + other);entity.AttackTrigger(other);}
在角色脚本执行攻击检测
 public override void AttackTrigger(Collider2D other){if (other.gameObject.layer == LayerMask.NameToLayer("Enemy")){base.AttackTrigger(other);AttackColliderCheck<Enemy>(other, (enemy) => enemy.BeDamage(stats));}}

2. 为每个攻击动画状态使用射线检测

优点:效率高于碰撞盒,可以定制,比如增加攻击范围
缺点:配置麻烦不直观

部分代码,仅供参考

定义每个动画的检测范围
[Header("攻击状态对应的碰撞盒")]public Dictionary<Entity.States, AttackRanges> attackRangeDict = new();//索引是攻击的状态 + 连击数,获取对应攻击的范围
[System.Serializable]
public class AttackRanges
{/// <summary>/// 对应的连击次数  作为索引/// </summary>public AttackRange[] ranges = new AttackRange[1];//索引器public AttackRange this[int index]{get{// return ranges.FirstOrDefault(x => x.combo == index);//如果没有,默认用第一个if (index >= ranges.Length)return ranges[0];return ranges[index];}}
}[System.Serializable]
public class AttackRange
{public SerializableVector2 offset = new();public SerializableVector2 size = new();public float rotation = 0;public UnityEngine.Vector2 Offset => offset.ToVector2();public UnityEngine.Vector2 Size => size.ToVector2();
}
添加帧事件
private void AttackTrigger(){entity.AttackTrigger();}
执行检测与绘制范围
 /// <summary>/// 攻击检测/// </summary>/// <typeparam name="T"></typeparam>/// <param name="action"></param>protected void AttackColliderCheck<T>(Action<T> action) where T : Entity{AttackRange attackRange = stats.attackRangeDict[States.PrimaryAttack][ComboCounter];var offset = facingRight ? attackRange.offset.ToVector2() : new Vector2(-attackRange.offset.x, attackRange.offset.y);var rotation = facingRight ? attackRange.rotation : -attackRange.rotation;Collider2D[] colliders = Physics2D.OverlapBoxAll(offset, attackRange.size.ToVector2(), rotation);foreach (Collider2D hit in colliders){if (hit.TryGetComponent<T>(out T entity)){action?.Invoke(entity);}}}// 默认情况下就会在编辑模式下运行protected virtual void OnDrawGizmos(){// Vector3 boxCenter = groundCheck.position + Vector3.down * groundCheckDistance / 2;// Gizmos.DrawCube(boxCenter, new Vector3(groundCheckWidth, groundCheckDistance, 0));Gizmos.DrawLine(groundCheck.position, new Vector3(groundCheck.position.x, groundCheck.position.y - groundCheckDistance));//绘制一条从 from(前面的) 开始到 to(后面的) 的线。Gizmos.DrawLine(wallCheck.position, new Vector3(wallCheck.position.x + wallCheckDistance, wallCheck.position.y));//绘制一条从 from(前面的) 开始到 to(后面的) 的线。if (stats == null) return;Gizmos.color = Color.red;var attackRange = stats.attackRangeDict.ContainsKey(States.PrimaryAttack) ? stats.attackRangeDict?[States.PrimaryAttack]?[ComboCounter] : new AttackRange();Vector3 center = (Vector3)attackRange.Offset;// 设置 Gizmos 的变换矩阵Matrix4x4 oldMatrix = Gizmos.matrix;Gizmos.matrix = Matrix4x4.TRS(center, Quaternion.Euler(0, 0, attackRange.rotation), Vector3.one);Gizmos.DrawWireCube(transform.position + (Vector3)attackRange.Offset, (Vector3)attackRange.Size);// 恢复原来的矩阵Gizmos.matrix = oldMatrix;}

3. 所有动画共用一个射线检测

优点:简单
缺点:不精确

不推荐使用

在帧事件触发,调用检测方法即可
 /// <summary>/// 攻击检测/// </summary>/// <typeparam name="T"></typeparam>/// <param name="action"></param>protected void AttackColliderCheck<T>(Action<T> action) where T : Entity{Collider2D[] colliders = Physics2D.OverlapCircleAll(attackCheck.position, attckCheckRadius);foreach (Collider2D hit in colliders){if (hit.TryGetComponent<T>(out T entity)){action?.Invoke(entity);}}}
http://www.lryc.cn/news/459357.html

相关文章:

  • 矩形函数的傅里叶变换——从一维到二维,从连续到离散
  • 潜水打捞系统助力,破解汽车打捞难题
  • 【深度学习】经典的深度学习模型-01 开山之作:CNN卷积神经网络LeNet-5
  • LeetCode 每日一题 2024/10/7-2024/10/13
  • ZYNQ使用XGPIO驱动外设模块(前半部分)
  • 【FastAdmin】全栈视角下的页面跳转实现:从原生html、javascrpt、php技术到jQuery、FastAdmin框架
  • 从零开始搭建一个node.js后端服务项目
  • 自定义注解和组件扫描在Spring Boot中动态注册Bean(一)
  • 如何在 IDEA 中导入 Java 项目的 Git 仓库并启动
  • BIO与NIO学习
  • 麒麟操作系统:解决umount命令卸载USB存储设备时报“device is busy”错误
  • Git客户端使用之TortoiseGit和Git
  • regionprops函数详解及应用
  • FPAG学习(5)-三种方法实现LED流水灯
  • 科迅网络阅卷系统存在存储型XSS漏洞
  • 【AAOS】Android Automotive 11模拟器源码下载及编译
  • 鹏哥C语言74---第12次作业:OJ题练习
  • Light灯光组件+组件的相关操作+游戏资源的加载
  • 离岗睡岗预警系统 值班室离岗识别系统Python 结合 OpenCV 库
  • 在Centos中安装、配置与使用atop监控工具
  • 前端框架对比与选择:详尽分析
  • FLINK SQL时区问题
  • LibreOffice SDK是LibreOffice软件的开发工具包
  • 第十五届蓝桥杯C/C++学B组(解)
  • 在docker的容器内如何查看Ubuntu系统版本
  • Google Play服务端获取订单和核销订单
  • Spring Security 与 OAuth 2.0 登录实现指南
  • 02 django管理系统 - base.html模板的搭建
  • ES6语法有哪些
  • 每天一个数据分析题(五百零四)- 抽取样本