You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity 2D钢琴游戏音符录制与回放功能实现咨询

嘿,作为Unity和C#新手能完成大部分钢琴游戏开发已经超棒了!录制和回放功能的核心其实就是记录音符的触发信息和时间点,之后再按时间顺序还原这些操作就行。我来给你一步步拆解实现方法,直接套进你的现有脚本里就行:

核心思路

录制时,我们把每个按下的音符的音频片段、动画触发参数,以及这个音符相对于录制开始的时间戳存起来;回放时,通过协程跟踪时间,到了对应时间就触发对应的音符播放和动画。

具体实现步骤

1. 定义存储录制数据的结构体

首先在你的NotePlay脚本里加一个可序列化的结构体,用来存每个音符的关键信息:

// 用来存储单个录制音符的信息,可序列化方便在Inspector里查看
[System.Serializable]
public struct RecordedNote
{
    public AudioClip noteClip;       // 对应的音符音频
    public float timestamp;          // 相对于录制开始的时间(秒)
    public string animTriggerName;   // 对应的动画触发参数名
}

2. 添加录制和回放的核心变量

在NotePlay类里补充这些变量,用来控制录制状态、存储录制数据、管理回放流程:

public class NotePlay : MonoBehaviour 
{
    Animator anim;
    public AudioClip noteA;
    // 记得把你其他的音符音频也在这里声明,比如noteB、noteC等
    public AudioClip noteB;
    public AudioClip noteC;

    // 录制相关
    private bool isRecording = false;
    private float recordingStartTime;
    private List<RecordedNote> recordedNotes = new List<RecordedNote>();

    // 回放相关
    private bool isPlayingBack = false;
    private int currentPlaybackIndex = 0;
    private float playbackStartTime;

    void Awake()
    {
        anim = GetComponent<Animator>();
    }

3. 实现录制开关逻辑

写一个方法绑定到你的录制按钮上,用来开始/停止录制:

// 绑定到录制按钮的OnClick事件
public void ToggleRecording()
{
    if (isRecording)
    {
        // 停止录制
        isRecording = false;
        Debug.Log($"录制结束,共记录了{recordedNotes.Count}个音符");
    }
    else
    {
        // 开始录制前清空之前的记录
        isRecording = true;
        recordedNotes.Clear();
        recordingStartTime = Time.time;
        Debug.Log("开始录制啦!");
    }
}

4. 重构音符播放方法,加入录制逻辑

把你原来的单个音符播放方法(比如PlayNoteA)改成通用方法,这样既可以处理正常播放,也能在录制时自动记录数据:

// 播放A音的方法,绑定到A键UI按钮
public void PlayNoteA()
{
    PlayNote(noteA, "PlayA"); // 这里的"PlayA"是你Animator里的动画触发参数名,要改成你自己的
}

// 播放B音的方法,绑定到B键UI按钮
public void PlayNoteB()
{
    PlayNote(noteB, "PlayB");
}

// 通用的音符播放逻辑,复用性更强
private void PlayNote(AudioClip clip, string triggerName)
{
    // 播放音符音频
    AudioSource.PlayClipAtPoint(clip, transform.position);
    // 触发音符动画
    if (anim != null)
    {
        anim.SetTrigger(triggerName);
    }

    // 如果正在录制,就把这个音符的信息存起来
    if (isRecording)
    {
        float timeSinceRecordStart = Time.time - recordingStartTime;
        recordedNotes.Add(new RecordedNote
        {
            noteClip = clip,
            timestamp = timeSinceRecordStart,
            animTriggerName = triggerName
        });
    }
}

5. 实现回放逻辑

用协程来处理回放的时间控制,这样可以精准按时间触发音符:

// 绑定到播放按钮的OnClick事件
public void StartPlayback()
{
    // 避免录制/回放同时进行
    if (isRecording || isPlayingBack)
    {
        Debug.Log("当前正在录制或回放,先结束当前操作哦!");
        return;
    }

    // 没有录制内容就不触发回放
    if (recordedNotes.Count == 0)
    {
        Debug.Log("还没录制任何音符呢,先录一段吧!");
        return;
    }

    isPlayingBack = true;
    currentPlaybackIndex = 0;
    playbackStartTime = Time.time;
    StartCoroutine(PlaybackCoroutine());
}

// 协程负责按时间回放音符
private IEnumerator PlaybackCoroutine()
{
    while (currentPlaybackIndex < recordedNotes.Count)
    {
        RecordedNote currentNote = recordedNotes[currentPlaybackIndex];
        float timeSincePlaybackStart = Time.time - playbackStartTime;

        // 当回放时间到达该音符的录制时间点时,触发播放
        if (timeSincePlaybackStart >= currentNote.timestamp)
        {
            PlayNote(currentNote.noteClip, currentNote.animTriggerName);
            currentPlaybackIndex++;
        }

        yield return null; // 等待下一帧,避免卡死
    }

    // 回放结束,重置状态
    isPlayingBack = false;
    Debug.Log("回放完成!");
}

6. 可选:添加停止回放的方法

如果需要中途停止回放,可以加这个方法绑定到停止按钮:

// 绑定到停止回放按钮的OnClick事件
public void StopPlayback()
{
    if (isPlayingBack)
    {
        StopCoroutine(PlaybackCoroutine());
        isPlayingBack = false;
        currentPlaybackIndex = 0;
        Debug.Log("回放已停止");
    }
}
最后要注意的小细节
  • 确保你的每个音符UI按钮都正确绑定了对应的PlayNoteX方法(比如A按钮绑定PlayNoteA)
  • 录制、播放、停止按钮分别绑定ToggleRecording、StartPlayback、StopPlayback方法
  • 动画触发参数名要和你Animator组件里的参数完全一致,不然动画不会播放
  • 如果你想把录制的内容保存下来(比如退出游戏后还能回放),可以用JSON把recordedNotes序列化成字符串,存在PlayerPrefs里,之后再反序列化读取,这个可以等你熟悉基础功能后再扩展

内容的提问来源于stack exchange,提问作者deep

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 03:43:30