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

news2024/10/6 8:47:07

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.coloradmin.cn/o/2191519.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

介绍一款开源的 Modern GUI PySide6 / PyQt6的使用

首先附上大神的开源地址&#xff08;自行克隆吧&#xff09;&#xff1a; https://github.com/Wanderson-Magalhaes/Modern_GUI_PyDracula_PySide6_or_PyQt6 步骤一&#xff1a;安装PySide6库 pip install PySide6 步骤二&#xff1a;运行main文件 python main.py 就得…

vite学习教程04、vue集成axios封装request工具类及应用

文章目录 前言1、安装axios2、封装request工具类3、封装api请求工具4、实战&#xff1a;vue中使用api请求工具类资料获取 前言 博主介绍&#xff1a;✌目前全网粉丝3W&#xff0c;csdn博客专家、Java领域优质创作者&#xff0c;博客之星、阿里云平台优质作者、专注于Java后端技…

Java | Leetcode Java题解之第459题重复的子字符串

题目&#xff1a; 题解&#xff1a; class Solution {public boolean repeatedSubstringPattern(String s) {return kmp(s s, s);}public boolean kmp(String query, String pattern) {int n query.length();int m pattern.length();int[] fail new int[m];Arrays.fill(fa…

不小心误删了虚拟环境.venv的目录文件夹,导致无法运行指定目录下的 Python 解释器怎么办?

创建虚拟环境步骤&#xff08;Windows 系统&#xff09;&#xff1a; 1、打开cmd命令 2、进入项目目录&#xff0c;在命令行中输入&#xff1a;cd 项目所在的路径 3、创建新的虚拟环境&#xff08;python3.3以上的版本&#xff09;,在当前目录下创建一个名为 .myvenv 的新虚…

SQL专项练习第三天

在大数据处理中&#xff0c;Hive 是一个常用的工具&#xff0c;它可以对大规模数据进行高效的查询和分析。本文将介绍五个 Hive 数据处理问题的解决方案&#xff0c;并通过实际案例进行演示。 先在home文件夹下建一个hivedata文件夹&#xff0c;把我们所需的数据写成txt文件导…

Springboot 整合 logback 日志框架

文章目录 整合 Logback 日志框架第一步&#xff1a;导入依赖第二步&#xff1a;导入配置&#xff08;logback.xml&#xff09;详解 使用&#xff08;记录日志&#xff09; 遇到问题一解决方案 整合 Logback 日志框架 第一步&#xff1a;导入依赖 &#xff08;Springboot 会自己…

网站开发的发展(后端路由/前后端分离/前端路由)

1.后端路由阶段 在早期的网站开发中 网页的渲染工作其实是交由服务器完成的 所以该渲染也被称之为后端渲染 具体的过程就是&#xff1a;浏览器发送url给服务器 服务器解析该url 使用后端路由(在服务器中 用于储存url和页面映射关系的路由)获取指定url对应的页面 然后交由jsp去…

洛谷每日一题(P1229 遍历问题)

原题目链接&#xff1a; P1229 遍历问题 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 原题目截图&#xff1a; 思路分析&#xff1a; 1、为什么会出现多个不同序列&#xff1f; 前序遍历和后序遍历序列无法唯一确定一棵二叉树的原因主要在于这两种遍历方式都缺少了关于…

linux基础 超级笔记

1.Linux系统的组成 Linux系统内核&#xff1a;提供系统最核心的功能&#xff0c;如软硬件和资源调度。 系统及应用程序&#xff1a;文件、任务管理器。 2.Linux发行版 通过修改内核代码自行集成系统程序&#xff0c;即封装。比如Ubuntu和centos这种。不过基础命令是完全相…

Android.mk中宏定义的高级用法剖析-安卓framework高级实战

背景&#xff1a; 前面的blog有讲解如何在Android.mk中进行控制安卓cpp源码中ifdef定义变量-干货技能分享&#xff0c;主要就是针对c代码中经常出现的#ifdef判断进行了剖析和实战 但是仅仅有上面的ifdef判断这个宏是否存在是不是对宏定义作用没有发挥到最大&#xff0c;是否可…

esp8266 at指令链接wifi时一直connect disconnest

那是你的连接wifi的名字密码有误或者热点有问题&#xff0c;看看热点是不是把设备拉入黑名单或者设置为5G或者连了校园网或者设置了最多链接设备

vAPI靶场

前言 自行去搭建vAPI靶场&#xff0c;配合postman使用 vapi1 创建用户 第一个用户 {"username": "shi","name": "shi1","course": "nihao","id": 10 } 第二个用户 {"username": "hui…

Pandas -----------------------基础知识(主要matplotlib知识)(七)

Dataframe变形 转置 T import pandas as pddata {2022: [10, 30, 15, 20], 2023: [40, 50, 36, 21]} df1 pd.DataFrame(data, index[q1, q2, q3, q4]) print("原始数据框&#xff1a;") print(df1)df2 df1.Tprint("转换后数据框&#xff1a;") print(df…

并查集——从LeetCode题海中总结常见套路

目录 并查集定义 LeetCode128.最长连续序列 先去重再sort&#xff1a; 改进去重的方法&#xff1a; 参考&#xff1a; 并查集定义 在计算机科学中&#xff0c;并查集是一种树型的数据结构&#xff0c;用于处理一些不交集&#xff08;Disjoint Sets&#xff09;的合并及查…

毕业设计选题:基于ssm+vue+uniapp的医院管理系统小程序

开发语言&#xff1a;Java框架&#xff1a;ssmuniappJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;M…

管道内裂缝检测数据集 2000张 管道裂缝 带标注voc yol

管道内裂缝检测数据集 2000张 管道裂缝 带标注voc yol 管道内裂缝检测数据集 (Pipeline Crack Detection Dataset) 数据集概述 该数据集是一个专门用于训练和评估管道内裂缝检测模型的数据集。数据集包含2000张图像&#xff0c;每张图像都带有标注信息&#xff0c;标注格式为…

JavaScript中的高阶函数

高阶函数 所谓高阶函数&#xff0c;就是操作函数的函数&#xff0c;它接收一个或多个函数作为参数&#xff0c;并返回一个新函数&#xff1a; 来看一个mapper()函数&#xff0c;将一个数组映射到另一个使用这个函数的数组上&#xff1a; 更常见的例子&#xff0c;它接收两个函…

【Kubernetes】常见面试题汇总(五十六)

目录 123. pod 创建失败&#xff1f; 124. kube-flannel-ds-amd64-ndsf7 插件 pod 的 status 为 Init:0/1 &#xff1f; 特别说明&#xff1a; 题目 1-68 属于【Kubernetes】的常规概念题&#xff0c;即 “ 汇总&#xff08;一&#xff09;~&#xff08;二十二&#x…

5G NR物理信号

文章目录 NR 物理信号与LTE的区别上行参考信号DMRS (UL)SRSPT-RS(UL) 下行参考信号DMRS(DL)PT-RS(DL)CSI-RSPSSSSS NR 物理信号与LTE的区别 用SSS、CSI-RS和DMRS 取代了CRS信号。下行业务信道采用TM1波束赋形传输模式。基于SSB 或者CSI-RS进行RSRP和SINR测量。基于DMRS 进行共…

Golang | Leetcode Golang题解之第457题环形数组是否存在循环

题目&#xff1a; 题解&#xff1a; func circularArrayLoop(nums []int) bool {n : len(nums)next : func(cur int) int {return ((curnums[cur])%n n) % n // 保证返回值在 [0,n) 中}for i, num : range nums {if num 0 {continue}slow, fast : i, next(i)// 判断非零且方…