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

【unity实战】使用Unity实现动作游戏的攻击 连击 轻重攻击和打击感

最终效果

在这里插入图片描述

文章目录

  • 最终效果
  • 前言
  • 素材下载:
  • 玩家移动跳跃控制
  • 攻击动画配置
    • 轻攻击
    • 重攻击
  • 攻击时禁止移动和攻击移动补偿
  • 敌人击退和播放受击动画
  • 受击特效
  • 攻击停顿和屏幕震动
  • 局部顿帧(补充)
  • 参考
  • 源码
  • 完结

前言

注意本文为自己的学习记录笔记,主要是对游戏攻击 连击 轻重攻击和打击感进行探究,其中打击感实现一般依靠播放受击动画、击退、攻击特效、时停和屏幕震动反馈等来实现,如果你有其他的好方法也欢迎补充。

素材下载:

人物
https://legnops.itch.io/red-hood-character
在这里插入图片描述

敌人
https://jesse-m.itch.io/skeleton-pack
在这里插入图片描述

环境
https://szadiart.itch.io/pixel-fantasy-caves
在这里插入图片描述

攻击特效
https://v-ktor.itch.io/pixelated-attackhit-animations
在这里插入图片描述

玩家移动跳跃控制

public class PlayerController : MonoBehaviour
{[Header("移动和跳跃参数")] public float moveSpeed; // 移动速度public float jumpForce; // 跳跃力量new private Rigidbody2D rigidbody; // 刚体组件private Animator animator; // 动画控制器private float input; // 输入private bool isGround; // 是否在地面上[SerializeField] private LayerMask layer; // 地面碰撞层[SerializeField] private Vector3 check; // 地面检测向量void Start(){rigidbody = GetComponent<Rigidbody2D>();animator = GetComponent<Animator>();}void Update(){input = Input.GetAxisRaw("Horizontal");isGround = Physics2D.OverlapCircle(transform.position + new Vector3(check.x, check.y, 0), check.z, layer);animator.SetFloat("Horizontal", rigidbody.velocity.x);animator.SetFloat("Vertical", rigidbody.velocity.y);animator.SetBool("isGround", isGround);Move();Attack();}void Move(){// 根据输入来移动角色rigidbody.velocity = new Vector2(input * moveSpeed, rigidbody.velocity.y);// 处理跳跃if (Input.GetButtonDown("Jump") && isGround){rigidbody.velocity = new Vector2(0, jumpForce);animator.SetTrigger("Jump"); // 触发跳跃动画}// 根据水平速度方向更新角色朝向if (rigidbody.velocity.x < 0)transform.localScale = new Vector3(-1, 1, 1); // 向左else if (rigidbody.velocity.x > 0)transform.localScale = new Vector3(1, 1, 1); // 向右}private void OnDrawGizmos(){Gizmos.DrawWireSphere(transform.position + new Vector3(check.x, check.y, 0), check.z);}}

攻击动画配置

攻击动画分为轻攻击和重攻击

轻攻击

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

重攻击

在这里插入图片描述

[Header("攻击")]
public float interval = 2f; // 攻击间隔时间
private float timer; // 计时器
private bool isAttack; // 是否正在攻击
private string attackType; // 攻击类型
private int comboStep; // 连击步骤void Update()
{//...Attack();
}void Attack()
{// 轻攻击输入检测if (Input.GetKeyDown(KeyCode.Return) && !isAttack){isAttack = true;attackType = "Light";comboStep++; // 连击步骤加一if (comboStep > 3)comboStep = 1; // 连击步骤循环timer = interval; // 设置计时器animator.SetTrigger("LightAttack"); // 触发轻攻击动画animator.SetInteger("ComboStep", comboStep); // 设置连击步骤参数}// 重攻击输入检测if (Input.GetKeyDown(KeyCode.RightShift) && !isAttack){isAttack = true;attackType = "Heavy";comboStep++; // 连击步骤加一if (comboStep > 3)comboStep = 1; // 连击步骤循环timer = interval; // 设置计时器animator.SetTrigger("HeavyAttack"); // 触发重攻击动画animator.SetInteger("ComboStep", comboStep); // 设置连击步骤参数}// 处理连击计时器if (timer != 0){timer -= Time.deltaTime;if (timer <= 0){timer = 0;comboStep = 0; // 重置连击步骤}}
}//攻击结束
public void AttackOver()
{isAttack = false;
}

配置每个攻击动画,在执行的位置执行攻击结束事件,通常攻击结束事件都不会放在动画的最后一帧,因为连击一般都存在预输入,也就是在上一个动画还未结束时就进行输入,这样能很好的提升combo的连贯性
在这里插入图片描述
效果
在这里插入图片描述

攻击时禁止移动和攻击移动补偿

攻击时我们不希望玩家还能移动,但是简单粗暴的禁止移动又会影响我们的攻击操作手感,在死亡细胞等游戏中,攻击时会朝前方以一个较小的速度移动,这样可以一定程度的补偿攻击时无法移动的缺陷
在这里插入图片描述

[Header("攻击补偿速度")]
public float lightSpeed; // 轻攻击速度
public float heavySpeed; // 重攻击速度void Move()
{// 如果玩家没有在攻击状态下,根据输入来移动角色if (!isAttack)rigidbody.velocity = new Vector2(input * moveSpeed, rigidbody.velocity.y);else{// 如果正在攻击,则根据攻击类型设置速度if (attackType == "Light")rigidbody.velocity = new Vector2(transform.localScale.x * lightSpeed, rigidbody.velocity.y);else if (attackType == "Heavy")rigidbody.velocity = new Vector2(transform.localScale.x * heavySpeed, rigidbody.velocity.y);}// ...
}

配置
在这里插入图片描述
效果
在这里插入图片描述

敌人击退和播放受击动画

配置敌人受击动画
在这里插入图片描述
配置玩家每个动画的攻击范围
在这里插入图片描述
新增Enemy 敌人脚本,实现击退和受击动画

public class Enemy : MonoBehaviour
{public float speed;                 // 敌人的移动速度private Vector2 direction;          // 受击时的移动方向private bool isHit;                 // 是否正在受击状态private AnimatorStateInfo info;     // 动画状态信息private Animator animator;          // 敌人的主动画控制器new private Rigidbody2D rigidbody;  // 敌人的刚体组件void Start(){// 获取组件的引用animator = transform.GetComponent<Animator>();rigidbody = transform.GetComponent<Rigidbody2D>();}void Update(){info = animator.GetCurrentAnimatorStateInfo(0); // 获取当前动画状态信息if (isHit){rigidbody.velocity = direction * speed; // 根据受击方向设置速度if (info.normalizedTime >= .6f)isHit = false; // 当动画播放超过60%时结束受击状态}}// 外部调用,使敌人进入受击状态public void GetHit(Vector2 direction){transform.localScale = new Vector3(-direction.x, 1, 1); // 根据受击方向调整朝向isHit = true; // 进入受击状态this.direction = direction; // 设置受击方向animator.SetTrigger("Hit"); // 播放主动画的受击动画状态}
}

修改PlayerController,调用击退敌人

private void OnTriggerEnter2D(Collider2D other)
{if (other.CompareTag("Enemy")){// 根据角色朝向确定敌人受击方向if (transform.localScale.x > 0)other.GetComponent<Enemy>().GetHit(Vector2.right); // 右侧受击else if (transform.localScale.x < 0)other.GetComponent<Enemy>().GetHit(Vector2.left); // 左侧受击}
}

效果
在这里插入图片描述

受击特效

在这里插入图片描述
特效动画配置
在这里插入图片描述
修改Enemy

private Animator hitAnimator;       // 敌人的受击特效动画控制器hitAnimator = transform.GetChild(0).GetComponent<Animator>(); // 敌人的受击特效动画控制器在子对象中// 外部调用,使敌人进入受击状态public void GetHit(Vector2 direction){//...hitAnimator.SetTrigger("Hit"); // 播放受击特效动画}

效果
在这里插入图片描述

攻击停顿和屏幕震动

新增AttackSense

public class AttackSense : MonoBehaviour
{private static AttackSense instance;public static AttackSense Instance{get{if (instance == null)instance = FindObjectOfType<AttackSense>(); // 查找当前场景中的 AttackSense 实例return instance;}}private bool isShake; // 是否正在进行摄像机震动// 暂停游戏一段时间public void HitPause(int duration){StartCoroutine(Pause(duration));}// 使用协程实现暂停功能IEnumerator Pause(int duration){float pauseTime = duration / 60f; // 将帧数转换为实际暂停时间Time.timeScale = 0.2f; // 将游戏时间缩放设为0.2yield return new WaitForSecondsRealtime(pauseTime); // 等待指定的暂停时间Time.timeScale = 1; // 恢复游戏时间正常}// 触发摄像机震动效果public void CameraShake(float duration, float strength){if (!isShake) // 如果当前没有进行震动StartCoroutine(Shake(duration, strength));}// 使用协程实现摄像机震动效果IEnumerator Shake(float duration, float strength){isShake = true; // 标记正在进行震动Transform camera = Camera.main.transform; // 获取主摄像机的 Transform 组件Vector3 startPosition = camera.position; // 记录摄像机震动前的初始位置while (duration > 0){// 将摄像机位置随机偏移一定范围来模拟震动效果camera.position = Random.insideUnitSphere * strength + startPosition;duration -= Time.deltaTime; // 每帧减去时间yield return null; // 等待下一帧}camera.position = startPosition; // 震动结束后将摄像机位置恢复到初始位置isShake = false; // 结束震动状态}
}

修改PlayerController调用

[Header("打击感")]
public float shakeTime; // 摇晃时间
public int lightPause; // 轻攻击暂停时间
public float lightStrength; // 轻攻击相机震动强度
public int heavyPause; // 重攻击暂停时间
public float heavyStrength; // 重攻击相机震动强度private void OnTriggerEnter2D(Collider2D other)
{if (other.CompareTag("Enemy")){// 根据攻击类型处理打击感if (attackType == "Light"){AttackSense.Instance.HitPause(lightPause); // 轻攻击暂停AttackSense.Instance.CameraShake(shakeTime, lightStrength); // 相机震动}else if (attackType == "Heavy"){AttackSense.Instance.HitPause(heavyPause); // 重攻击暂停AttackSense.Instance.CameraShake(shakeTime, heavyStrength); // 相机震动}// 根据角色朝向确定敌人击退方向if (transform.localScale.x > 0)other.GetComponent<Enemy>().GetHit(Vector2.right); // 右侧受击else if (transform.localScale.x < 0)other.GetComponent<Enemy>().GetHit(Vector2.left); // 左侧受击}
}

配置参数
在这里插入图片描述
最终效果
在这里插入图片描述

局部顿帧(补充)

前面的顿帧这个思路其实不太好,可以看看有的游戏,他们不是所有物体都停顿的,一般是攻击者和受击者停顿,其他的不受影响。animator有个scale播放速度scale值应该可以实现这种效果,连续攻击可能用局部顿帧好一点,下面大概分享一下思路

public class AttackController : MonoBehaviour
{public Animator animator;public float slowMotionTimeScale = 0.5f; // 慢动作时的时间缩放值public void PerformAttack(){StartCoroutine(AttackCoroutine());}IEnumerator AttackCoroutine(){// 播放攻击动画前先设置慢动作animator.speed = slowMotionTimeScale;// 等待攻击动画播放完成yield return new WaitForSeconds(animator.GetCurrentAnimatorStateInfo(0).length / slowMotionTimeScale);// 恢复正常时间缩放animator.speed = 1f;}
}

在这个示例中,PerformAttack 方法可以被调用来开始攻击动作。在攻击动作开始时,时间缩放被设置为 slowMotionTimeScale,然后通过 Coroutine 等待攻击动画播放完成后,再恢复为正常速度。

通过这种方法,你可以在游戏中实现局部的动画停顿效果,而不是整体减速,从而增强游戏的视觉冲击力和玩家的体验。

参考

https://www.bilibili.com/video/BV1fX4y1G7tv

源码

整理好我会放上来

完结

赠人玫瑰,手有余香!如果文章内容对你有所帮助,请不要吝啬你的点赞评论和关注,以便我第一时间收到反馈,你的每一次支持都是我不断创作的最大动力。当然如果你发现了文章中存在错误或者有更好的解决方法,也欢迎评论私信告诉我哦!

好了,我是向宇,https://xiangyu.blog.csdn.net

一位在小公司默默奋斗的开发者,出于兴趣爱好,最近开始自学unity,闲暇之余,边学习边记录分享,站在巨人的肩膀上,通过学习前辈们的经验总是会给我很多帮助和启发!php是工作,unity是生活!如果你遇到任何问题,也欢迎你评论私信找我, 虽然有些问题我也不一定会,但是我会查阅各方资料,争取给出最好的建议,希望可以帮助更多想学编程的人,共勉~
在这里插入图片描述

相关文章:

【unity实战】使用Unity实现动作游戏的攻击 连击 轻重攻击和打击感

最终效果 文章目录 最终效果前言素材下载&#xff1a;玩家移动跳跃控制攻击动画配置轻攻击重攻击 攻击时禁止移动和攻击移动补偿敌人击退和播放受击动画受击特效攻击停顿和屏幕震动局部顿帧&#xff08;补充&#xff09;参考源码完结 前言 注意本文为自己的学习记录笔记&#…...

ELK 企业实战7

ELKkafkafilebeat企业内部日志分析系统 1、组件介绍 1、Elasticsearch&#xff1a; 是一个基于Lucene的搜索服务器。提供搜集、分析、存储数据三大功能。它提供了一个分布式多用户能力的全文搜索引擎&#xff0c;基于RESTful web接口。Elasticsearch是用Java开发的&#xff…...

linux 下neo4j的安装

一、neo4j简介 Neo4j 是一个高性能的 NoSQL 图形数据库,它将结构化数据存储在网络(从数学角度叫做图)上而不是表中。Neo4j 也可以被看作是一个高性能的图引擎,该引擎具有成熟数据库的所有特性。 neo4j与jdk版本对应 neo4j的版本需要与jdk版本相适配,否则容易出现安装失…...

Flink ProcessFunction不同流异同及应用场景

ProcessFunction系列对比概览 函数类别关键特性应用场景示例ProcessFunction基础类&#xff0c;处理单个事件&#xff0c;支持事件时间、水位线、状态管理、定时器。单独处理每个事件&#xff0c;执行复杂逻辑&#xff0c;如基于事件内容动态响应。KeyedProcessFunction基于键…...

Matplotlib 文本

可以使用 xlabel、ylabel、text向图中添加文本 mu, sigma 100, 15 x mu sigma * np.random.randn(10000)# the histogram of the data n, bins, patches plt.hist(x, 50, densityTrue, facecolorg, alpha0.75)plt.xlabel(Smarts) plt.ylabel(Probability) plt.title(Histo…...

信创产业政策,信创测试方面

信创产业的政策支持主要体现在多个方面&#xff0c;这些政策旨在推动产业的快速发展&#xff0c;加强自主创新能力&#xff0c;保障国家信息安全&#xff0c;以及促进产业结构的优化升级。 首先&#xff0c;政府通过财政支持、税收优惠等方式&#xff0c;加大对信创产业的资金…...

微信云数据库迁移到unicloud云数据库

背景 早期只有一个微信小程序&#xff0c;后来了解到uniapp的跨端解决方案&#xff0c;开始从小程序代码迁移到uniapp。对于后端采用的微信云开发方案&#xff0c;迁移的时候主要要解决从openid的用户体系转移到unicloud提供的uni-id体系(使用uid)。 方案 利用微信云数据库的…...

快速上手文心一言指令

“文心一言”指的是百度公司开发的自然语言处理与生成技术&#xff0c;它类似于ChatGPT&#xff0c;是一种基于大规模语言模型的AI对话系统&#xff0c;能够理解和生成自然语言文本&#xff0c;进行问答、创作等多种任务。由于“文心一言”是一个复杂的系统&#xff0c;其内部指…...

零基础STM32单片机编程入门(五)FreeRTOS实时操作系统详解及实战含源码视频

文章目录 一.概要二.什么是实时操作系统三.FreeRTOS的特性四.FreeRTOS的任务详解1.任务函数定义2.任务的创建3.任务的调度原理 五.CubeMX配置一个FreeRTOS例程1.硬件准备2.创建工程3.调试FreeRTOS任务调度 六.CubeMX工程源代码下载七.讲解视频链接地址八.小结 一.概要 FreeRTO…...

leetCode.96. 不同的二叉搜索树

leetCode.96. 不同的二叉搜索树 题目思路 代码 // 方法一&#xff1a;直接用卡特兰数就行 // 方法二&#xff1a;递归方法 class Solution { public:int numTrees(int n) {// 这里把 i当成整个结点&#xff0c;j当成左子树最左侧结点,并一次当根节点尝试// f[ i ] f[ j - 1…...

PyAutoGUI 使用详解

文章目录 简介PyAutoGUI 的原理安装 PyAutoGUI基本使用示例鼠标控制键盘控制截屏图像识别消息框 高级功能防止误操作多屏幕支持鼠标平滑移动 结论 简介 PyAutoGUI 是一个用于自动化控制鼠标和键盘的 Python 库。它可以帮助开发者编写脚本&#xff0c;以模拟用户在计算机上的操…...

MySQL——备份

为什么要备份&#xff1f; 保证重要的数据不丢失 方便数据转移 MySQL数据库备份方式&#xff1a; 1. 直接拷贝物理文件 2. 在可视化工具中手动导出 —— 在想要导出的表或者库中&#xff0c;右键选择备份或导出 3. 使用命令行导出 mysqldump ——cmd打开命令行 —…...

科东软件精彩亮相华南工博会,展现未来工业前沿技术

近日&#xff0c;华南国际工业博览会在深圳成功举办。科东软件携众多前沿技术、解决方案及最新应用案例精彩亮相&#xff0c;为参展观众带来了一场工业智能的科技盛宴。 鸿道操作系统&#xff08;Intewell&#xff09; 科东软件重点展示了鸿道操作系统&#xff08;Intewell&…...

详解flink sql, calcite logical转flink logical

文章目录 背景示例FlinkLogicalCalcConverterBatchPhysicalCalcRuleStreamPhysicalCalcRule其它算子FlinkLogicalAggregateFlinkLogicalCorrelateFlinkLogicalDataStreamTableScanFlinkLogicalDistributionFlinkLogicalExpandFlinkLogicalIntermediateTableScanFlinkLogicalInt…...

PostgreSQL的系统视图pg_statio_all_indexes

PostgreSQL的系统视图pg_statio_all_indexes 在 PostgreSQL 数据库中&#xff0c;pg_statio_all_indexes 视图提供了有关所有索引的 I/O 活动的统计信息。这些统计信息对于了解索引的使用情况和性能调优非常有帮助。 pg_statio_all_indexes 视图的结构 以下是 pg_statio_all…...

【C++ Primer Plus学习记录】函数和C-风格字符串

将字符串作为参数时意味着传递的是地址&#xff0c;但可以使用const来禁止对字符串参数进行修改。 假设要将字符串作为参数传递给函数&#xff0c;则表示字符串的方式有三种&#xff1a; &#xff08;1&#xff09;char数组 &#xff08;2&#xff09;用引号括起来的字符串常…...

力扣双指针算法题目:移动零

1.题目 . - 力扣&#xff08;LeetCode&#xff09; 2.思路解析 这个题目的思路和“使用递归排序快速排序解决数组的排序问题”相同 class solution { public:void QuickSort(vector<int>& nums, int left, int right){if (left > right) return;int key left…...

day60---面试专题(微服务面试题-参考回答)

微服务面试题 **面试官&#xff1a;**Spring Cloud 5大组件有哪些&#xff1f; 候选人&#xff1a; 早期我们一般认为的Spring Cloud五大组件是 Eureka : 注册中心Ribbon : 负载均衡Feign : 远程调用Hystrix : 服务熔断Zuul/Gateway : 网关 随着SpringCloudAlibba在国内兴起 , …...

laravel+phpoffice+easyexcel实现导入

资源包下载地址 https://download.csdn.net/download/QiZong__BK/89503486 easy-excel下载&#xff1a; "dcat/easy-excel": "^1.0", 命令行&#xff1a; composer require dcat/easy-excel 前端代码 <!doctype html> <html lang"en&…...

Spring Boot集成多数据源的最佳实践

Spring Boot集成多数据源的最佳实践 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01; 为什么需要多数据源&#xff1f; 在实际的应用开发中&#xff0c;有时候…...

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周&#xff0c;有很多同学在写期末Java web作业时&#xff0c;运行tomcat出现乱码问题&#xff0c;经过多次解决与研究&#xff0c;我做了如下整理&#xff1a; 原因&#xff1a; IDEA本身编码与tomcat的编码与Windows编码不同导致&#xff0c;Windows 系统控制台…...

Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器

第一章 引言&#xff1a;语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域&#xff0c;文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量&#xff0c;支撑着搜索引擎、推荐系统、…...

Python爬虫(二):爬虫完整流程

爬虫完整流程详解&#xff08;7大核心步骤实战技巧&#xff09; 一、爬虫完整工作流程 以下是爬虫开发的完整流程&#xff0c;我将结合具体技术点和实战经验展开说明&#xff1a; 1. 目标分析与前期准备 网站技术分析&#xff1a; 使用浏览器开发者工具&#xff08;F12&…...

多模态大语言模型arxiv论文略读(108)

CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文标题&#xff1a;CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文作者&#xff1a;Sayna Ebrahimi, Sercan O. Arik, Tejas Nama, Tomas Pfister ➡️ 研究机构: Google Cloud AI Re…...

Swagger和OpenApi的前世今生

Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章&#xff0c;二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑&#xff1a; &#x1f504; 一、起源与初创期&#xff1a;Swagger的诞生&#xff08;2010-2014&#xff09; 核心…...

MySQL账号权限管理指南:安全创建账户与精细授权技巧

在MySQL数据库管理中&#xff0c;合理创建用户账号并分配精确权限是保障数据安全的核心环节。直接使用root账号进行所有操作不仅危险且难以审计操作行为。今天我们来全面解析MySQL账号创建与权限分配的专业方法。 一、为何需要创建独立账号&#xff1f; 最小权限原则&#xf…...

Python Ovito统计金刚石结构数量

大家好,我是小马老师。 本文介绍python ovito方法统计金刚石结构的方法。 Ovito Identify diamond structure命令可以识别和统计金刚石结构,但是无法直接输出结构的变化情况。 本文使用python调用ovito包的方法,可以持续统计各步的金刚石结构,具体代码如下: from ovito…...

现有的 Redis 分布式锁库(如 Redisson)提供了哪些便利?

现有的 Redis 分布式锁库&#xff08;如 Redisson&#xff09;相比于开发者自己基于 Redis 命令&#xff08;如 SETNX, EXPIRE, DEL&#xff09;手动实现分布式锁&#xff0c;提供了巨大的便利性和健壮性。主要体现在以下几个方面&#xff1a; 原子性保证 (Atomicity)&#xff…...

【Redis】笔记|第8节|大厂高并发缓存架构实战与优化

缓存架构 代码结构 代码详情 功能点&#xff1a; 多级缓存&#xff0c;先查本地缓存&#xff0c;再查Redis&#xff0c;最后才查数据库热点数据重建逻辑使用分布式锁&#xff0c;二次查询更新缓存采用读写锁提升性能采用Redis的发布订阅机制通知所有实例更新本地缓存适用读多…...

多模态图像修复系统:基于深度学习的图片修复实现

多模态图像修复系统:基于深度学习的图片修复实现 1. 系统概述 本系统使用多模态大模型(Stable Diffusion Inpainting)实现图像修复功能,结合文本描述和图片输入,对指定区域进行内容修复。系统包含完整的数据处理、模型训练、推理部署流程。 import torch import numpy …...