Unity教程(十八)战斗系统 攻击逻辑

news2024/12/23 19:49:09

Unity开发2D类银河恶魔城游戏学习笔记

Unity教程(零)Unity和VS的使用相关内容
Unity教程(一)开始学习状态机
Unity教程(二)角色移动的实现
Unity教程(三)角色跳跃的实现
Unity教程(四)碰撞检测
Unity教程(五)角色冲刺的实现
Unity教程(六)角色滑墙的实现
Unity教程(七)角色蹬墙跳的实现
Unity教程(八)角色攻击的基本实现
Unity教程(九)角色攻击的改进

Unity教程(十)Tile Palette搭建平台关卡
Unity教程(十一)相机
Unity教程(十二)视差背景

Unity教程(十三)敌人状态机
Unity教程(十四)敌人空闲和移动的实现
Unity教程(十五)敌人战斗状态的实现
Unity教程(十六)敌人攻击状态的实现
Unity教程(十七)敌人战斗状态的完善

Unity教程(十八)战斗系统 攻击逻辑
Unity教程(十九)战斗系统 受击反馈


如果你更习惯用知乎
Unity开发2D类银河恶魔城游戏学习笔记目录


文章目录

  • Unity开发2D类银河恶魔城游戏学习笔记
  • 前言
  • 一、概述
  • 二、攻击逻辑的实现
    • (1)攻击检测
    • (2)伤害函数
    • (2)攻击触发器
  • 三、解决碰撞问题
  • 总结 完整代码
    • Entity.cs
    • PlayerAnimationTriggers.cs
    • Enemy_SkeletonAnimationTriggers.cs


前言

本文为Udemy课程The Ultimate Guide to Creating an RPG Game in Unity学习笔记,如有错误,欢迎指正。

本节实现战斗系统的攻击逻辑部分。

Udemy课程地址

对应视频:
Attack Logic
Collider’s collision exception


一、概述

本节我们先实现战斗的逻辑,即在攻击动画播放过程中找到攻击对象并造成伤害,这里伤害我们先用控制台信息代表,后续再进行具体实现。
在这里插入图片描述
在这里插入图片描述

二、攻击逻辑的实现

(1)攻击检测

在实体Entity类中添加攻击检测和攻击距离两个变量,并在OnDrawGizmos函数中绘制出攻击范围。

Gizmos函数详情见Unity官方手册
Gizmos可以绘制图形的图形如下表:

函数功能
DrawCube使用 center 和 size 绘制一个实心盒体。
DrawFrustum绘制一个摄像机视锥体,并且将当前设置的 Gizmos.matrix 用于其位置和旋转。
DrawGUITexture在该场景中绘制一个纹理。
DrawIcon在 Scene 视图中的某个位置绘制一个图标。
DrawLine绘制一条从 from 开始到 to 的线。
DrawMesh绘制一个网格。
DrawRay绘制一条从 from 开始到 from + direction 的射线。
DrawSphere使用 center 和 radius 绘制一个实心球体。
DrawWireCube使用 center 和 size 绘制一个线框盒体。
DrawWireMesh绘制一个线框网格。
DrawWireSphere使用 center 和 radius 绘制一个线框球体。

Entity类中添加代码如下:
添加变量:

    [Header("Collision Info")]
    public Transform attackCheck;
    public float attackCheckRadius;
    [SerializeField] protected Transform groundCheck;
    [SerializeField] protected float groundCheckDistance;
    [SerializeField] protected Transform wallCheck;
    [SerializeField] protected float wallCheckDistance;
    [SerializeField] protected LayerMask whatIsGround;

绘制攻击范围:

    protected virtual void OnDrawGizmos()
    {
        Gizmos.DrawLine(groundCheck.position, new Vector3(groundCheck.position.x, groundCheck.position.y - groundCheckDistance));
        Gizmos.DrawLine(wallCheck.position, new Vector3(wallCheck.position.x + wallCheckDistance, wallCheck.position.y));
        Gizmos.DrawWireSphere(attackCheck.position, attackCheckRadius);
    }

在Player下创建空物体attackCheck用于攻击检测。
将空物体attackCheck拖入变量,并给attackCheckRadius设置合适的值。
在这里插入图片描述
在这里插入图片描述
移动attackCheck到Player身前合适位置,圆圈绘制出的就是Player的攻击范围。
在这里插入图片描述
同理,设置小怪的攻击检测。
在这里插入图片描述

(2)伤害函数

在Entity中添加伤害函数Damage(),实现受击后的反馈。目前不进行具体实现,先输出一条调试信息代替。

    public virtual void Damage()
    {
        Debug.Log(gameObject.name + " was damaged");
    }

(2)攻击触发器

我们先以Player的攻击为例。
在玩家触发器PlayerAnimationTriggers类中,添加攻击触发器attackTrigger函数。
每次攻击时,要记录所有在攻击范围内的敌人。然后每个攻击范围内的敌人将调用自己的Damage函数实现受伤的反馈。

检测攻击范围内的敌人调用Physics2D.OverlapCircleAll函数,它会返回圆内的所有碰撞体。
Collider2D[] OverlapCircleAll (Vector2 point, float radius, int layerMask, float minDepth, float maxDepth);
参数表如下

参数介绍
point圆形的中心。
radius圆形的半径。
layerMask筛选器,用于检查仅在指定层上的对象。
minDepth仅包括 Z 坐标(深度)大于或等于该值的对象。
maxDepth仅包括 Z 坐标(深度)小于或等于该值的对象。

在PlayerAnimationTriggers中添加代码:

    private void AttackTrigger()
    {
        Collider2D[] colliders = Physics2D.OverlapCircleAll(player.attackCheck.position, player.attackCheckRadius);

        foreach(var hit in colliders)
        {
            if (hit.GetComponent<Enemy>() != null)
                hit.GetComponent<Enemy>().Damage();
        }
    }

在触发攻击伤害的帧添加事件调用attackTrigger

如需添加事件帧的详细介绍请见
Unity教程(八)角色基本攻击的实现

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
可以看到,在玩家攻击时,控制台输出对骷髅产生伤害
在这里插入图片描述
敌人的攻击触发器实现与玩家一样,代码如下:

    private void AttackTrigger()
    {
        Collider2D[] colliders = Physics2D.OverlapCircleAll(enemy.attackCheck.position, enemy.attackCheckRadius);

        foreach (var hit in colliders)
        {
            if (hit.GetComponent<Player>() != null)
                hit.GetComponent<Player>().Damage();
        }
    }

同样设置事件帧

在这里插入图片描述
在这里插入图片描述

三、解决碰撞问题

现在攻击时,因为两者之间存在碰撞,骷髅会推着玩家走,而玩家甚至可以在骷髅头上走,这看起来很不对劲。
在这里插入图片描述
在制作游戏时,有些会采用碰撞伤害,有些则只有攻击时造成伤害。在这里我们采用第二种,让玩家可以穿过敌人,只在被攻击击中时受到伤害。
解决方式很简单,只需要调整层次之间的碰撞即可。
首先必须确保玩家和敌人处于各自层级。

在这里插入图片描述
在这里插入图片描述
调整层次碰撞矩阵,将Player和Enemy层次间的碰撞勾掉
Edit -> Project Settings -> Physics 2D -> Layer Collision Matrix

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
目前存在一个问题,在骷髅与玩家重合时会不停碰撞导致骷髅抽搐,这个问题会在后续解决。
在这里插入图片描述

总结 完整代码

Entity.cs

添加攻击检测变量和绘制函数,添加伤害函数。

//Entity:实体类
using System.Collections;
using System.Collections.Generic;
using Unity.IO.LowLevel.Unsafe;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.UI;

public class Entity : MonoBehaviour
{

    [Header("Flip Info")]
    protected bool facingRight = true;
    public int facingDir { get; private set; } = 1;



    [Header("Collision Info")]
    public Transform attackCheck;
    public float attackCheckRadius;
    [SerializeField] protected Transform groundCheck;
    [SerializeField] protected float groundCheckDistance;
    [SerializeField] protected Transform wallCheck;
    [SerializeField] protected float wallCheckDistance;
    [SerializeField] protected LayerMask whatIsGround;


    #region 组件
    public Rigidbody2D rb { get; private set; }
    public Animator anim { get; private set; }
    #endregion

    protected virtual void Awake()
    {

    }

    //获取组件
    protected virtual void Start()
    {
        rb= GetComponent<Rigidbody2D>();
        anim= GetComponentInChildren<Animator>();
    }

    // 更新
    protected virtual void Update()
    {
        
    }

    public virtual void Damage()
    {
        Debug.Log(gameObject.name + " was damaged");
    }

    #region 速度设置
    //速度置零
    public void ZeroVelocity() => rb.velocity = new Vector2(0, 0);

    //设置速度
    public void SetVelocity(float _xVelocity, float _yVelocity)
    {
        rb.velocity = new Vector2(_xVelocity, _yVelocity);
        FlipController(_xVelocity);
    }
    #endregion

    #region 翻转
    //翻转实现
    public virtual void Flip()
    {
        facingDir = -1 * facingDir;
        facingRight = !facingRight;
        transform.Rotate(0, 180, 0);
    }
    //翻转控制
    public virtual void FlipController(float _x)
    {
        if (_x > 0 && !facingRight)
            Flip();
        else if (_x < 0 && facingRight)
            Flip();
    }
    #endregion

    #region 碰撞
    //碰撞检测
    public virtual bool isGroundDetected() => Physics2D.Raycast(groundCheck.position, Vector2.down, groundCheckDistance, whatIsGround);
    public virtual bool isWallDetected() => Physics2D.Raycast(wallCheck.position, Vector2.right * facingDir, wallCheckDistance, whatIsGround);


    //绘制碰撞检测
    protected virtual void OnDrawGizmos()
    {
        Gizmos.DrawLine(groundCheck.position, new Vector3(groundCheck.position.x, groundCheck.position.y - groundCheckDistance));
        Gizmos.DrawLine(wallCheck.position, new Vector3(wallCheck.position.x + wallCheckDistance, wallCheck.position.y));
        Gizmos.DrawWireSphere(attackCheck.position, attackCheckRadius);
    }
    #endregion
}


PlayerAnimationTriggers.cs

添加攻击触发器

//PlayerAnimationTriggers:触发器组件
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerAnimationTriggers : MonoBehaviour
{
    private Player player => GetComponentInParent<Player>();
    private void AnimationTrigger()
    {
        player.AnimationTrigger();
    }

    private void AttackTrigger()
    {
        Collider2D[] colliders = Physics2D.OverlapCircleAll(player.attackCheck.position, player.attackCheckRadius);

        foreach(var hit in colliders)
        {
            if (hit.GetComponent<Enemy>() != null)
                hit.GetComponent<Enemy>().Damage();
        }
    }
}

Enemy_SkeletonAnimationTriggers.cs

//Enemy_SkeletonAnimationTriggers:触发器组件
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Enemy_SkeletonAnimationTriggers : MonoBehaviour
{

    private Enemy_Skeleton enemy => GetComponentInParent<Enemy_Skeleton>();
    private void AnimationTrigger()
    {
        enemy.AnimationTrigger();
    }
    private void AttackTrigger()
    {
        Collider2D[] colliders = Physics2D.OverlapCircleAll(enemy.attackCheck.position, enemy.attackCheckRadius);

        foreach (var hit in colliders)
        {
            if (hit.GetComponent<Player>() != null)
                hit.GetComponent<Player>().Damage();
        }
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2241774.html

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

相关文章

【软件测试】设计测试用例的方法(正交法、判定表法、错误猜测法),测试文档的写法

文章目录 正交法正交表设计正交表 判定表法判定表 设计测试用例的步骤 错误猜测法测试文档 正交法 正交试验设计(Orthogonal experimentaldesign)是研究多因素多⽔平的⼀种设计⽅法&#xff0c;它是根据正交性&#xff0c;由试验因素的全部⽔平组合中挑选出部分有代表性的点进…

MySQL技巧之跨服务器数据查询:进阶篇-从A数据库复制到B数据库的表中

MySQL技巧之跨服务器数据查询&#xff1a;进阶篇-从A数据库复制到B数据库的表中 基础篇已经描述&#xff1a;借用微软的SQL Server ODBC 即可实现MySQL跨服务器间的数据查询。 而且还介绍了如何获得一个在MS SQL Server 可以连接指定实例的MySQL数据库的连接名: MY_ODBC_MYSQ…

网络安全练习之 ctfshow_web

文章目录 VIP题目限免&#xff08;即&#xff1a;信息泄露题&#xff09;源码泄露前台JS绕过协议头信息泄露robots后台泄露phps源码泄露源码压缩包泄露版本控制泄露源码(git)版本控制泄露源码2(svn)vim临时文件泄露cookie泄露域名txt记录泄露敏感信息公布内部技术文档泄露编辑器…

Elasticsearch retrievers 通常与 Elasticsearch 8.16.0 一起正式发布!

作者&#xff1a;来自 Elastic Panagiotis Bailis Elasticsearch 检索器经过了重大改进&#xff0c;现在可供所有人使用。了解其架构和用例。 在这篇博文中&#xff0c;我们将再次深入探讨检索器&#xff08;retrievers&#xff09;。我们已经在之前的博文中讨论过它们&#xf…

debug笔记:gpustat显示没有进程运行,但是GPU显存被占用

1 问题描述 使用gpustat之后&#xff0c;虽然显示除了gpu5之外别的都没有进程&#xff0c;但是GPU显存却被占用了 2 解决方法 原因是存在僵尸进程&#xff0c;已经运行完&#xff0c;但是内存并没有释放 fuser -v /dev/nvidia* 这个指令查看僵尸进程 然后kill掉即可&#…

【Chapter 3】Machine Learning Classification Case_Prediction of diabetes-XGBoost

文章目录 1、XGBoost Algorithm2、Comparison of algorithm implementation between Python code and Sentosa_DSML community edition(1) Data reading and statistical analysis(2)Data preprocessing(3)Model Training and Evaluation(4)Model visualization 3、summarize 1…

Android OpenGL ES详解——立方体贴图

目录 一、概念 二、如何使用 1、创建立方体贴图 2、生成纹理 3、设置纹理环绕和过滤方式 4、激活和绑定立方体贴图 三、应用举例——天空盒 1、概念 2、加载天空盒 3、显示天空盒 4、优化 四、应用举例——环境映射:反射 五、应用举例——环境映射:折射 六、应用…

聊天服务器(9)一对一聊天功能

目录 一对一聊天离线消息服务器异常处理 一对一聊天 先新添一个消息码 在业务层增加该业务 没有绑定事件处理器的话消息会派发不出去 聊天其实是服务器做一个中转 现在同时登录两个账号 收到了聊天信息 再回复一下 离线消息 声明中提供接口和方法 张三对离线的李…

T6识别好莱坞明星

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 导入基础的包 from tensorflow import keras from tensorflow.keras import layers,models import os, PIL, pathlib import matplotlib.pyplot as pl…

Odoo :一款免费开源的日化行业ERP管理系统

文 / 开源智造Odoo亚太金牌服务 概述 构建以 IPD 体系作为核心的产品创新研发管控体系&#xff0c;增进企业跨部门业务协同的效率&#xff0c;支撑研发管控、智慧供应链、智能制造以及全渠道营销等行业的场景化&#xff0c;构筑行业的研产供销财一体化管理平台。 行业的最新…

48.第二阶段x86游戏实战2-鼠标点击call

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 本次游戏没法给 内容参考于&#xff1a;微尘网络安全 本人写的内容纯属胡编乱造&#xff0c;全都是合成造假&#xff0c;仅仅只是为了娱乐&#xff0c;请不要…

Vue 学习随笔系列十五 -- 数组遍历方法

数组遍历方法 文章目录 数组遍历方法1. for 循环2. forEach (不会修改数组本身)3. map (不修改数组本身)4. some(不修改数组本身&#xff09;5. every(不修改数组本身&#xff09;6. filter(不修改数组本身)7. find(不修改数组本身)8. findIndex拓展 9. reduce(累加)拓展 1. fo…

FreeRTOS的列表与列表项

目录 1.为什么要学列表&#xff1f; 2.什么是列表和列表项&#xff1f; 2.1 列表 2.2列表项 2.3&#xff0c;迷你列表项 3.列表与列表项的初始化 3.1 列表初始化 3.2列表项初始化 4.列表项的“增删查”&#xff08;插入、删除、遍历&#xff09; 4.1列表项的插入 4.1.1…

数字IC后端教程之Innovus hold violation几大典型问题

今天小编给大家分享下数字IC后端实现Physical Implementation过程中经常遇到的几个hold violation问题。每个问题都是小编自己在公司实际项目中遇到的。 数字后端实现静态时序分析STA Timing Signoff之min period violation Q1: 在Innouvs postCTS时序优化的log中我们经常会看…

VS2022编译32位OpenCV

使用环境 Visual Studio 2022 OpenCV: 4.7.0 cmake: 3.30.2一、使用CMake工具生成vs2022的openCV工程解决方案 打开cmake&#xff0c;选择opencv的源代码目录&#xff0c;创建一个文件夹&#xff0c;作为VS工程文件的生成目录 点击configure构建项目&#xff0c;弹出构建设置…

企业生产环境-麒麟V10(ARM架构)操作系统部署Zookeeper单节点集群版

前言&#xff1a;ZooKeeper是一个分布式协调服务&#xff0c;它为分布式应用提供一致性服务&#xff0c;是Apache Hadoop的子项目。它被设计为易于编程&#xff0c;同时具有高性能和高可靠性。ZooKeeper提供了一个简单的接口和一些基本的文件系统操作&#xff0c;使得开发者能够…

vue3 中直接使用 JSX ( lang=“tsx“ 的用法)

1. 安装依赖 npm i vitejs/plugin-vue-jsx2. 添加配置 vite.config.ts 中 import vueJsx from vitejs/plugin-vue-jsxplugins 中添加 vueJsx()3. 页面使用 <!-- 注意 lang 的值为 tsx --> <script setup lang"tsx"> const isDark ref(false)// 此处…

深度学习服务器租赁AutoDL

1. 根据需要选择租用的显卡 算力市场 1.1 显卡选择 1.2 环境配置 2. 服务器使用 2.1 上传文件 2.2 调试环境 2.3 跑代码 python train.py && /usr/bin/shutdown # && /usr/bin/shutdown表示代码成功运行结束后&#xff0c;自动关机3. 省钱绝招 省钱绝招 …

IDEA部署AI代写插件

前言 Hello大家好&#xff0c;当下是AI盛行的时代&#xff0c;好多好多东西在AI大模型的趋势下都变得非常的简单。 比如之前想画一幅风景画得先去采风&#xff0c;然后写实什么的&#xff0c;现在你只需描述出你想要的效果AI就能够根据你的描述在几分钟之内画出一幅你想要的风景…

【大数据技术基础 | 实验十】Hive实验:部署Hive

文章目录 一、实验目的二、实验要求三、实验原理四、实验环境五、实验内容和步骤&#xff08;一&#xff09;安装部署&#xff08;二&#xff09;配置HDFS&#xff08;三&#xff09;启动Hive 六、实验结果&#xff08;一&#xff09;启动结果&#xff08;二&#xff09;Hive基…