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

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; }#endregionprotected 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.rhkb.cn/news/471819.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

前端学习八股资料CSS(二)

更多详情&#xff1a;爱米的前端小笔记&#xff0c;更多前端内容&#xff0c;等你来看&#xff01;这些都是利用下班时间整理的&#xff0c;整理不易&#xff0c;大家多多&#x1f44d;&#x1f49b;➕&#x1f914;哦&#xff01;你们的支持才是我不断更新的动力&#xff01;找…

云计算研究实训室建设方案

一、引言 随着云计算技术的迅速发展和广泛应用&#xff0c;职业院校面临着培养云计算领域专业人才的迫切需求。本方案旨在构建一个先进的云计算研究实训室&#xff0c;为学生提供一个集理论学习、实践操作、技术研发与创新于一体的综合性学习平台&#xff0c;以促进云计算技术…

通过Python 调整Excel行高、列宽

在Excel中&#xff0c;默认的行高和列宽可能不足以完全显示某些单元格中的内容&#xff0c;特别是当内容较长时。通过调整行高和列宽&#xff0c;可以确保所有数据都能完整显示&#xff0c;避免内容被截断。合理的行高和列宽可以使表格看起来更加整洁和专业&#xff0c;尤其是在…

【代码审计】常见漏洞专项审计-业务逻辑漏洞审计

❤️博客主页&#xff1a; iknow181 &#x1f525;系列专栏&#xff1a; 网络安全、 Python、JavaSE、JavaWeb、CCNP &#x1f389;欢迎大家点赞&#x1f44d;收藏⭐评论✍ 0x01 漏洞介绍 1、 原理 业务逻辑漏洞是一类特殊的安全漏洞&#xff0c;业务逻辑漏洞属于设计漏洞而非实…

Wordpress常用配置,包括看板娘跨域等

一个Wordpress的博客已经搭建完成了&#xff0c;那么为了让它看起来更有人间烟火气一点&#xff0c;有一些常用的初始配置&#xff0c;这里整理一下。 修改页脚 页脚这里默认会显示Powered by Wordpress&#xff0c;还有一个原因是这里要加上备案信息。在主题里找到页脚&…

数据库范式、MySQL 架构、算法与树的深入解析

一、数据库范式 在数据库设计中&#xff0c;范式是一系列规则&#xff0c;用于确保数据的组织和存储具有良好的结构、完整性以及最小化的数据冗余。如果不遵循范式设计&#xff0c;数据可能会以平铺式罗列&#xff0c;仅使用冒号、分号等简单分隔。这种方式存在诸多弊端&#…

Taro React-Native IOS 打包发布

http网络请求不到 配置 fix react-native facebook::flipper::SocketCertificateProvider‘ (aka ‘int‘) is not a function or func_rn运行debug提示flipper-CSDN博客 Xcode 15&#xff08;iOS17&#xff09;编译适配报错_no template named function in namespace std-CS…

基于yolov8、yolov5的车型检测识别系统(含UI界面、训练好的模型、Python代码、数据集)

摘要&#xff1a;车型识别在交通管理、智能监控和车辆管理中起着至关重要的作用&#xff0c;不仅能帮助相关部门快速识别车辆类型&#xff0c;还为自动化交通监控提供了可靠的数据支撑。本文介绍了一款基于YOLOv8、YOLOv5等深度学习框架的车型识别模型&#xff0c;该模型使用了…

从python源码到可自动更新软件

相关阅读 标题链接如何打包python程序为exebczl【auto-py-to-exe 可视化打包python到exe】51CTO ZATA 1. python源码 打包时需要特别注意的源码编写规范 除了基本的 Python 编码规范之外,在准备程序进行打包时,还需要特别注意以下几点: 1.1 依赖管理 确保 requirements.t…

javaWeb小白项目--学生宿舍管理系统

目录 一、检查并关闭占用端口的进程 二、修改 Tomcat 的端口配置 三、重新启动 Tomcat 一、javaw.exe的作用 二、结束javaw.exe任务的影响 三、如何判断是否可以结束 结尾&#xff1a; 这个错误提示表明在本地启动 Tomcat v9.0 服务器时遇到了问题&#xff0c;原因是所需…

k8s笔记——核心概念

什么是K8s Kubernetes 也称为 K8s&#xff0c;是用于自动部署、扩缩和管理容器化应用程序的开源系统。 Kubernetes 最初是由 Google 工程师作为 Borg 项目开发和设计的&#xff0c;后于 2015 年捐赠给 云原生计算基金会&#xff08;CNCF&#xff09;。 什么是 Kubernetes 集群…

SkyWalking-安装

SkyWalking-简单介绍 是一个开源的分布式追踪系统&#xff0c;用于检测、诊断和优化分布式系统的功能。 支持 ElasticSearch、H2、MySQL、PostgreSql 等数据库 基于 ElasticSearch 的情况 ElasticSearch&#xff08;ES&#xff09; 安装 1、下载并解压 https://www.elastic…

怎么样绑定域名到AWS(亚马逊云)服务器

1&#xff0c;拿着你买的域名去亚马逊申请一个证书。申请证书分两种&#xff0c;一种是去亚马逊后台填域名手动申请 &#xff0c;另一种是通过API来申请&#xff0c;类似如下代码&#xff1a; 2、证验证书。有两种方式&#xff1a;一种是通过邮件&#xff0c;另一种去到域名提供…

C++常用的新特性-->day06

时间间隔duration duration表示一段时间间隔&#xff0c;用来记录时间长度&#xff0c;可以表示几秒、几分钟、几个小时的时间间隔。duration的原型如下 // 定义于头文件 <chrono> template<class Rep,class Period std::ratio<1> > class duration;Rep&…

云服务器端口开放

云服务器一般除了必要端口&#xff0c;其它端口默认都是关闭的&#xff0c;要想进行网络通信就必须开放指定的端口。下面以腾讯云服务器为例来进行详细说明。 腾讯云的轻量服务器是没有安全组的&#xff0c;这里有的只是防火墙&#xff0c;开放端口也是通过防火墙来设置的。首先…

[Linux网络编程]10-http协议,分别使用epoll和libevent两种方式实现B/S服务器

一.HTTP协议&#xff0c;Request请求和Response响应 二.常用状态码 接下来使用两种方式构建B/S模型,实现浏览器向客户端请求文件的功能。 浏览器向构建好的服务器发送请求&#xff0c;在请求行中请求具体文件&#xff0c;服务器连通客户端(浏览器)后&#xff0c;检查文件是否存…

C#从入门到放弃

C#和.NET的区别 C# C#是一个编程语言 .NET .NET是一个在window下创建程序的框架 .NET框架不仅局限于C#,它还可以支持很多语言 .NET包括了2个组件&#xff0c;一个叫CLR(通用语言运行时)&#xff0c;另一个是用来构建程序的类库 CLR 用C写一个程序&#xff0c;在一台8688的机器…

Suricata

02-Suricata 一 ICMP流量预警 一条ICMP报文有四个重要内容&#xff0c;可与相应的ICMP关键字相匹配。它们是&#xff1a;消息的类型、代码、ID和序列。 通过ICMP的type进行匹配 alert icmp any any <> any any (msg:"icmp流量预警";itype:8;threshold:type t…

在 WPF 中,如何实现数据的双向绑定?

在 WPF 中&#xff0c;数据绑定是一个非常重要的特性&#xff0c;它允许 UI 与数据源之间自动同步。双向绑定是一种常见的绑定方式&#xff0c;当数据源更新时&#xff0c;UI 会自动更新&#xff1b;同样&#xff0c;当 UI 中的元素&#xff08;如文本框&#xff09;发生改变时…

2、 家庭网络发展现状

上一篇我们讲了了解家庭网络历史(https://blog.csdn.net/xld_hung/article/details/143639618?spm1001.2014.3001.5502),感兴趣的同学可以看对应的文章&#xff0c;本章我们主要讲家庭网络发展现状。 关于家庭网络发展现状&#xff0c;我们会从国内大户型和小户型的网络说起&…