[Unity]类似节奏地牢的音游旋律系统的搭建记录

本文记录了使用Unity搭建类似节奏地牢音游节奏系统的全过程,包括初期方案的实现与不足,以及后续的改进措施。初期方案涉及Note类、RhythmManager的创建,遇到的问题包括按键记录、性能浪费和时间精度。改进方案集中了性能,使用每秒播放一拍提高精度,并尝试加入减速、提速效果,但遇到了帧数问题。最终通过调整更新逻辑解决了动画同步问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

[Unity]类似节奏地牢的音游节奏系统的搭建

近期发现之前写的一些文章看的人还是有不少,但大部分都是找了解决方案然后转述了一遍罢了,心想既然有人看不如做点使用的东西出来,于是结合现在正好在做音游的demo,而音游节奏一块正好是我没接触过的,所以可以记录下来并给大家一同参考下。如果有人能发现有不足之处可以评论指出,我看到了会尽快更改。


前言

该demo借鉴了啪嗒砰、节奏地牢的相关玩法即设定。demo的游戏类型是横版+rpg+roguelite+音游元素。

一、最初的方案(不太可行,缺点多)

我对于常见的音游的认知就几处,跟着节奏,在到达节奏的那个点附近的时候按下Tap键触发。想起来很简单,好,于是上手做。

1. 需求

  1. 类似于节奏地牢的节奏条,在开启节奏模式时可以在Start位置生成音符Note并匀速运动到End位置,在经过TapLine附近时,按下即可触发Node的事件,并记录下按键的keycode。在距离TapLine不同距离(位置)按下Tap键触发反馈对应的Tap品质, 对象池回收音符Note。如下图节奏条示意图
  2. 音乐/节奏,我们选了后者,循环播放一段节拍音频,可以和音符到达TapLine的时间对上

2.实现与缺点

  1. 实现
    为了实现节奏条,我创建了Note类和RhythmManager,如下,基本思路是在按下Space进入奏乐模式MusicMode时为noteQueue入队noteIdx所对应集合里的Note并激活和显示(nodeIdx++),激活后的NoteremainTime随时间减少,并在对应的阶段按下Tap键时调用API取出队首Note调用它的API,来检测Tap品质和隐藏Note。(注:仅为隐藏,在移动到end点时不会重置,因为激活下一个Note需要当前NoteremainTime等于1f,为了保证后续Note的持续出现只可采用这种方法。)在重置阶段将把Note的位置重新定位到start点,remainTime重设为duration,bool值全部归为默认值,这样就可在下次激活时继续使用,实现了对象池的功能。而记录Tap的按键由string来记录。
    遇到的问题
    记录按键功能我一开始用了List集合,后续理所应当的比较是总为false,原因在于两个集合的值虽然一样但地址不同,所以两个集合不相等,可以实际举例,由a集合赋值给b集合,那b集合就等于a集合,对b集合的修改就相当于修改a集合(简单的数据结构,但当时脑抽了),后续用string来记录虽解决了比较问题,但仍留下了不同按键对应Tap品质的储存问题,这部分就留在后续更新中探讨吧。
    缺点
    性能的浪费:很多属性和功能可以集中在RhythmManager中,而非单个Note中,部分单例可由回调替代。
    时间精度问题:暂时发现不出问题,但是肯定存在
public class Note : MonoBehaviour
{
   
    private float remainTime;
    private float duration = 2;
    private float perfectTime = 1;
    private float perfectTimeOffset = 0.05f;
    private float greatTimeOffset = 0.15f;
    private float moveSpeed = 1f;
    //这两处有些不合理,应该用同一管理器传值,而不是每个单独脚本重新拖入位置
    private RectTransform startLine;
    private RectTransform endLine;
    //
    private RectTransform rectTrans;
    public bool isActivated;
    public bool isShow;
    public bool hasStartedNextNote;
    public bool hasTapped;
	private void Update()
    {
   
        if (isActivated)
        {
   
            remainTime -= Time.deltaTime;
            
            if (remainTime < perfectTime - greatTimeOffset && isShow && !hasTapped)
            {
   
                HideNote();
                RhythmManager.Instance.NoteDeQueue();
                //TODO: combo断连
                RhythmManager.Instance.BreakCombo();
            }
            if(remainTime 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值