【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是生活!如果你遇到任何问题,也欢迎你评论私信找我, 虽然有些问题我也不一定会,但是我会查阅各方资料,争取给出最好的建议,希望可以帮助更多想学编程的人,共勉~
在这里插入图片描述

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

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

相关文章

Android平台崩溃和 ANR 问题进行符号化解析、解析崩溃日志的内存地址

使用Android Logcat Stacktrace Utility | Android Logcat | 1.2.3 1.设置so库路径 2.打开Stacktrace Utility工具 3.在Original粘贴报错内存地址 4.点击Resolve Stacktraces,就会解析出内存地址 如果是红色,解析失败了,缺少原生so库,可以在第一步添加so库文件再次尝试…

c语言回顾-内存操作函数

目录 前言 1.memcpy 函数 1.1函数介绍 1.2与strcpy的区别 1.3memcpy的模拟 2.memmove 函数 2.1函数介绍和使用 2.2函数的模拟 3.memset函数 3.1函数介绍 3.2函数的模拟 4.memcmp函数 4.1函数的使用 4.2函数的模拟 结束语 前言 在动态内存的章节中小编详细讲解了动…

代码随想录算法训练营第69天:图论7[1]

代码随想录算法训练营第69天&#xff1a;图论7 109. 冗余连接II 卡码网题目链接&#xff08;ACM模式&#xff09;(opens new window) 题目描述 有向树指满足以下条件的有向图。该树只有一个根节点&#xff0c;所有其他节点都是该根节点的后继。该树除了根节点之外的每一个节…

【Arduino】ESP8266开发环境配置(图文)

ESP8266与ESP32开发很类似&#xff0c;相当于是低配版本的ESP32&#xff0c;其同样具有无线网络连接能力&#xff0c;功能强大&#xff0c;而且价格比ESP32更具有优势。接下来我们就来设置一下ESP8266的开发环境。 使用Arduino开发平台软件&#xff0c;选择首选项进行设置。 h…

ASP.NET Core 6.0 使用 Action过滤器

Action过滤器 在ASP.NET Core中&#xff0c;Action过滤器用于在执行Action方法之前或之后执行逻辑。你可以创建自定义的Action过滤器来实现这一点。 继承 ActionFilterAttribute 类&#xff1a; [TypeFilter(typeof(CustomAllActionResultFilterAttribute))]public IActionRe…

67.WEB渗透测试-信息收集- WAF、框架组件识别(7)

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 内容参考于&#xff1a; 易锦网校会员专享课 上一个内容&#xff1a;66.WEB渗透测试-信息收集- WAF、框架组件识别&#xff08;6&#xff09;-CSDN博客 关于w…

第四届数字安全大会:AI时代数据安全策略与天空卫士创新实践

2024年6月22日&#xff0c;以 “新质•真能力”为主题的第四届数字安全大会在北京隆重召开。这场由数世咨询和CIO时代联合主办的行业盛会&#xff0c;集中探讨了大模型、数据治理与流通、以及安全运营等当前最前沿的议题。大会吸引了来自不同行业的首席信息官&#xff08;CIO&a…

2024Datawhale-AI夏令营——机器学习挑战赛——学习笔记

#ai夏令营#datawhale#夏令营 Day1:入门级demo运行 这个其实比较简单&#xff0c;按照操作来做就行了&#xff0c;特征工程和调参暂时都没有做&#xff0c;后续的才是重头戏。 Day2:正式比赛开始 赛题&#xff1a;数据挖掘赛道——利用机器学习方法根据给定的特征判断PROTACs…

【EFK】efk 8收集docker容器日志测试

前言 目前&#xff0c;efk 全家桶已经更新到版本8 了&#xff0c;本章节我们使用8版本的elk搭建日志收集系统&#xff0c;了解它的配置运行过程&#xff0c;方便以后在更复杂的环境中更好的使用。 版本默认就是8最新的&#xff0c;也可以自己指定其他8的版本 elasticsearch: …

vs 远程链接ssh 开发 简单实验

1.概要 动态编译语言&#xff0c;跨平台必须做分别的编译&#xff0c;比如linux和windows。如何再windows环境下开发编译出linux平台的程序呢&#xff0c;vs支持远程链接编辑&#xff0c;就是再vs中写代码&#xff0c;但是编译确是链接远程的环境编译的。 2.环境准备 2.1 vs…

R语言学习,入门

我是一名6年开发经验的程序员&#xff0c;后端&#xff0c;大数据&#xff0c;前端都会。 现在加入了医疗行业&#xff0c;要做数据分析&#xff0c;前同事的实验室生信专业的&#xff0c;用的是R语言&#xff0c;为了跑通他的程序。就来学一下吧&#xff0c;看了一下好像挺简…

关于软件本地化,您应该了解什么?

软件本地化是调整软件应用程序以满足目标市场的语言、文化和技术要求的过程。它不仅仅涉及翻译用户界面&#xff1b;它包含一系列活动&#xff0c;以确保软件在目标语言环境中可用且相关。以下是您应该了解的有关软件本地化的一些关键方面&#xff1a; 了解范围 软件本地化是…

水利水电安全员C证考试题库资料,2024年全国考试通用!

1.安全生产民事责任&#xff0c;是指责任主体违反安全生产法律规定造成&#xff08;&#xff09;&#xff0c;由人民法院依照民事法律强制其行使民事赔偿的一种法律责任。民事责任追究的目的是为了最大限度的维护当事人受到民事损害时享有获得民事赔偿的权利。 A.民事损伤 B.…

针对SVN、GIT版本管理工具进行源代码加密保护

针对SVN、GIT版本管理工具进行源代码加密保护 在软件开发过程中&#xff0c;版本管理工具如SVN和GIT是不可或缺的组成部分&#xff0c;它们帮助团队管理源代码的变更和版本。然而&#xff0c;这些工具也面临着源代码泄露的安全风险。如果不针对数据进行加密保护&#xff0c;很…

如何从腾讯云迁移到AWS

随着跨境出海潮不断扩大&#xff0c;企业越来越意识到将工作负载迁移到海外节点的必要性&#xff0c;以获取更多功能、灵活性和性能。然而&#xff0c;顺利迁移业务主机并确保业务稳定访问是一项具有挑战性的任务。在此挑战中&#xff0c;借助AWS迁移工具和迁移流程的强大支持&…

如何检查购买的Facebook账号优劣?

Facebook 是全球最受欢迎的社交网络之一,为品牌广告提供了巨大的潜力。许多公司和营销人员使用 Facebook 来推广他们的产品和服务&#xff0c;经常会购买账号。当然也分出了很多账号&#xff0c;比如个人号&#xff0c;BM号&#xff0c;广告号&#xff0c;小黑号等等。 但是,有…

实现点击Button,改变背景颜色(多个按钮互斥显示)

一 功能描述 在界面中&#xff0c;有一组button&#xff0c;现在需要实现下面功能&#xff1a;点击其中一个&#xff0c;改变被点击button的背景颜色。当点击下一个之后&#xff0c;之前点击过的按钮背景颜色还原&#xff0c;当前被点击的button背景色又被改变。效果如下图&…

【JavaEE】多线程代码案例(2)

&#x1f38f;&#x1f38f;&#x1f38f;个人主页&#x1f38f;&#x1f38f;&#x1f38f; &#x1f38f;&#x1f38f;&#x1f38f;JavaEE专栏&#x1f38f;&#x1f38f;&#x1f38f; &#x1f38f;&#x1f38f;&#x1f38f;上一篇文章&#xff1a;多线程代码案例(1)&a…

女性经济崛起,天润融通用客户感知挖掘市场潜力

每逢一年一度的国际妇女节&#xff0c;“女性”话题都会被郑重地讨论。 从消费市场上来说&#xff0c;最近几年女性群体正在拥有越来越大的影响力&#xff0c;甚至出现了“她经济”这样的专属词汇在最近几年被市场反复讨论。 毫无疑问&#xff0c;女性消费群体的崛起已经成为…

监控平台—Zabbix对接grafana

目录 一、安装grafana并启动 二.浏览器访问 三、导入zabbix数据&#xff0c;对接grafana 四.如何导入模版 一、安装grafana并启动 添加一台服务器192.168.80.102 初始化操作 systemctl disable --now firewalld setenforce 0 vim /etc/selinux/config SELINUXdisabled cd /…