에셋 포함 #3

Merged
sharedacc520k merged 3 commits from CatsRhythmGame into main 2026-06-12 07:29:50 +00:00
6 changed files with 93 additions and 15 deletions
Showing only changes of commit 1e0483f210 - Show all commits

View File

@@ -3,7 +3,7 @@
public class Note
{
public float Time;
[HideInInspector] public float Time;
}
[CreateAssetMenu(fileName = "RhythmChart", menuName = "CatsRoom/RhythmChart")]

View File

@@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;
using UnityEngine;
@@ -6,10 +7,19 @@ public class RhythmManager : MonoBehaviour
{
[SerializeField] private AudioSource _audioSource;
[SerializeField] private RhythmChart _currentChart;
private float SongTime => _audioSource.time; // 모든 타이밍의 기준
[SerializeField] private RhythmNoteSpawner _spawner;
[SerializeField] private float _leadTime = 2f; // 노트가 생성돼 판정선까지 흐르는 시간(초)
public float SongTime => _audioSource.time; // 모든 타이밍의 기준
private List<Note> SongNoteList;
private int _nextNoteIndex; // 다음에 소환할 노트 인덱스
private bool _isPlaying; //곡이 재생 중인지 (종료 감지용)
private Func<float> _songTimeProvider; // 노트에 넘길 시간 제공자 (매 스폰마다 람다 재생성 방지용 캐시)
private void Awake()
{
_songTimeProvider = () => SongTime; // 한 번만 만들어 모든 노트가 공유
}
private void Start()
{
@@ -22,6 +32,23 @@ private void Update()
if (_isPlaying && !_audioSource.isPlaying)
{
StopSong();
return;
}
if (_isPlaying) SpawnDueNotes();
}
// SongTime 기준으로 소환할 때가 된 노트들을 순서대로 생성
private void SpawnDueNotes()
{
// 판정 시각보다 _leadTime 먼저 생성해야 박자에 맞춰 판정선에 도달
while (_nextNoteIndex < SongNoteList.Count && //총 노트수보다 노트인덱스가 작고
SongTime >= SongNoteList[_nextNoteIndex].Time - _leadTime) //노래길이가 다음 노트의 노트타임 - 리드타임 보다 작을때까지만
{
Note note = SongNoteList[_nextNoteIndex];
// spawnTime은 실제 프레임 시각이 아니라 이론값(note.Time - _leadTime)으로 줘야 보간이 정확
_spawner.SpawnNote(note, note.Time - _leadTime, _songTimeProvider, OnNoteMissed);
_nextNoteIndex++;
}
}
@@ -34,6 +61,7 @@ public void ChangeSong()
public void StartSong()
{
SongNoteList = _currentChart.GenerateNotes();
_nextNoteIndex = 0;
_audioSource.Play();
_isPlaying = true;
@@ -51,9 +79,15 @@ public void StopSong()
if (SoundManager.Instance != null) SoundManager.Instance.ExitMinigameMode();
}
// 노트가 판정선을 지나쳐 스스로 Miss 처리될 때 호출
private void OnNoteMissed(RhythmNoteInstance note)
{
// TODO: 점수/콤보 시스템 연결 시 Miss 반영
}
public void OnPlayerInput()
{
}
public Result Judge(float diff)

View File

@@ -1,12 +1,47 @@
using System;
using UnityEngine;
public class RhythmNoteInstance : MonoBehaviour
{
public float HitTime; // 이 노트의 도달 시각
public float HitTime; // 이 노트의 도달 시각
[SerializeField] private float _missWindow = 0.15f; // 판정선을 이만큼 지나면 자동 Miss
private Vector3 _start; // 출발점
private Vector3 _target; // 목적지(판정선)
private float _spawnTime; // 생성된 시각 (= HitTime - leadTime)
private Func<float> _songTime; // 오디오 기준 현재 곡 시간 제공자
private Action<RhythmNoteInstance> _onMiss; // 지나쳐서 Miss 났을 때 통지
// 스폰 시 목적지·타이밍 주입 (B 방식)
public void Setup(Vector3 start, Vector3 target, float spawnTime, float hitTime,
Func<float> songTime, Action<RhythmNoteInstance> onMiss = null)
{
_start = start;
_target = target;
_spawnTime = spawnTime;
HitTime = hitTime;
_songTime = songTime;
_onMiss = onMiss;
transform.position = start;
}
private void Update()
{
// 판정선 향해 이동
// 너무 지나가면 Miss 처리 후 자기 파괴
if (_songTime == null) return;
float now = _songTime();
// SongTime 기반 보간: spawnTime → HitTime 구간을 0→1로
float t = Mathf.InverseLerp(_spawnTime, HitTime, now);
transform.position = Vector3.LerpUnclamped(_start, _target, t);
// 판정선을 missWindow 이상 지나치면 Miss 처리 후 자기 파괴
if (now > HitTime + _missWindow)
{
_onMiss?.Invoke(this);
Destroy(gameObject);
}
}
}

View File

@@ -1,10 +1,19 @@
using System;
using UnityEngine;
public class RhythmNoteSpawner : MonoBehaviour
{
// 노트 프리팹 생성, 도달시간 주입
public void SpawnNote(Note note)
[SerializeField] private RhythmNoteInstance _notePrefab; // 생성할 노트 프리팹
[SerializeField] private Transform _spawnPoint; // 노트가 생겨나는 위치(미지정 시 자기 위치)
[SerializeField] private Transform _judgmentLine; // 목적지(판정선)
// 노트 프리팹 생성, 목적지·타이밍 주입
public RhythmNoteInstance SpawnNote(Note note, float spawnTime,
Func<float> songTime, Action<RhythmNoteInstance> onMiss = null)
{
}
Transform origin = _spawnPoint != null ? _spawnPoint : transform;
RhythmNoteInstance instance = Instantiate(_notePrefab, origin.position, origin.rotation, transform);
instance.Setup(origin.position, _judgmentLine.position, spawnTime, note.Time, songTime, onMiss);
return instance;
}
}

Binary file not shown.