欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 教育 > 锐评 > unity 2d 近战攻击判定的三种方式

unity 2d 近战攻击判定的三种方式

2024/10/25 12:25:04 来源:https://blog.csdn.net/zhuanggenhua/article/details/142700437  浏览:    关键词:unity 2d 近战攻击判定的三种方式

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);}}}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com