mirror of
https://github.com/RHeavenStudio/HeavenStudio.git
synced 2025-06-12 11:27:39 +02:00
Playback visualization + started on timeline in editor
This commit is contained in:
@ -10,44 +10,40 @@ namespace RhythmHeavenMania
|
||||
// [RequireComponent(typeof(AudioSource))]
|
||||
public class Conductor : MonoBehaviour
|
||||
{
|
||||
//Song beats per minute
|
||||
//This is determined by the song you're trying to sync up to
|
||||
// Song beats per minute
|
||||
// This is determined by the song you're trying to sync up to
|
||||
public float songBpm;
|
||||
|
||||
//The number of seconds for each song beat
|
||||
// The number of seconds for each song beat
|
||||
public float secPerBeat;
|
||||
|
||||
//Current song position, in seconds
|
||||
// Current song position, in seconds
|
||||
public float songPosition;
|
||||
|
||||
//Current song position, in beats
|
||||
// Current song position, in beats
|
||||
public float songPositionInBeats;
|
||||
|
||||
//How many seconds have passed since the song started
|
||||
public float dspSongTime;
|
||||
// How many seconds have passed since the song started
|
||||
public float startTime;
|
||||
|
||||
//an AudioSource attached to this GameObject that will play the music.
|
||||
private float pauseTime;
|
||||
|
||||
// Current time of the song
|
||||
private float time;
|
||||
|
||||
// an AudioSource attached to this GameObject that will play the music.
|
||||
public AudioSource musicSource;
|
||||
|
||||
//The offset to the first beat of the song in seconds
|
||||
// The offset to the first beat of the song in seconds
|
||||
public float firstBeatOffset;
|
||||
|
||||
//the number of beats in each loop
|
||||
public float beatsPerLoop;
|
||||
|
||||
//the total number of loops completed since the looping clip first started
|
||||
public int completedLoops = 0;
|
||||
|
||||
//The current position of the song within the loop in beats.
|
||||
public float loopPositionInBeats;
|
||||
|
||||
//The current relative position of the song within the loop measured between 0 and 1.
|
||||
public float loopPositionInAnalog;
|
||||
|
||||
//Conductor instance
|
||||
// Conductor instance
|
||||
public static Conductor instance;
|
||||
|
||||
private AudioDspTimeKeeper timeKeeper;
|
||||
public bool isPlaying;
|
||||
public bool isPaused;
|
||||
|
||||
// private AudioDspTimeKeeper timeKeeper;
|
||||
|
||||
void Awake()
|
||||
{
|
||||
@ -56,25 +52,42 @@ namespace RhythmHeavenMania
|
||||
|
||||
void Start()
|
||||
{
|
||||
//Load the AudioSource attached to the Conductor GameObject
|
||||
musicSource = GetComponent<AudioSource>();
|
||||
|
||||
timeKeeper = GetComponent<AudioDspTimeKeeper>();
|
||||
|
||||
//Calculate the number of seconds in each beat
|
||||
secPerBeat = 60f / songBpm;
|
||||
|
||||
//Record the time when the music starts
|
||||
// dspSongTime = (float)musicSource.time;
|
||||
|
||||
//Start the music
|
||||
// musicSource.Play();
|
||||
}
|
||||
|
||||
public void Play(float startBeat)
|
||||
public void Play()
|
||||
{
|
||||
timeKeeper.Play();
|
||||
SetTime(startBeat);
|
||||
float lastTime = pauseTime - startTime;
|
||||
|
||||
startTime = Time.time;
|
||||
|
||||
time = startTime + lastTime;
|
||||
|
||||
isPlaying = true;
|
||||
isPaused = false;
|
||||
|
||||
musicSource.PlayScheduled(startTime);
|
||||
}
|
||||
|
||||
public void Pause()
|
||||
{
|
||||
pauseTime = time;
|
||||
|
||||
isPlaying = false;
|
||||
isPaused = true;
|
||||
|
||||
musicSource.Pause();
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
time = 0;
|
||||
isPlaying = false;
|
||||
isPaused = false;
|
||||
|
||||
musicSource.Stop();
|
||||
}
|
||||
|
||||
public void SetTime(float startBeat)
|
||||
@ -86,22 +99,14 @@ namespace RhythmHeavenMania
|
||||
|
||||
public void Update()
|
||||
{
|
||||
if (!musicSource.isPlaying) return;
|
||||
if (isPlaying)
|
||||
{
|
||||
time += Time.deltaTime * musicSource.pitch;
|
||||
|
||||
//determine how many seconds since the song started
|
||||
// songPosition = (float)(timeKeeper.dspTime - dspSongTime - firstBeatOffset);
|
||||
songPosition = (float)timeKeeper.GetCurrentTimeInSong();
|
||||
songPosition = time - startTime - firstBeatOffset;
|
||||
|
||||
//determine how many beats since the song started
|
||||
songPositionInBeats = songPosition / secPerBeat;
|
||||
|
||||
|
||||
//calculate the loop position
|
||||
if (songPositionInBeats >= (completedLoops + 1) * beatsPerLoop)
|
||||
completedLoops++;
|
||||
loopPositionInBeats = songPositionInBeats - completedLoops * beatsPerLoop;
|
||||
|
||||
loopPositionInAnalog = loopPositionInBeats / beatsPerLoop;
|
||||
songPositionInBeats = songPosition / secPerBeat;
|
||||
}
|
||||
}
|
||||
|
||||
public float GetLoopPositionFromBeat(float startBeat, float length)
|
||||
@ -123,6 +128,7 @@ namespace RhythmHeavenMania
|
||||
|
||||
public float SongLengthInBeats()
|
||||
{
|
||||
if (!musicSource.clip) return 0;
|
||||
return musicSource.clip.length / secPerBeat;
|
||||
}
|
||||
}
|
||||
|
@ -83,14 +83,14 @@ namespace RhythmHeavenMania
|
||||
private IEnumerator Begin()
|
||||
{
|
||||
yield return new WaitForSeconds(startOffset);
|
||||
Conductor.instance.Play(startBeat);
|
||||
// Conductor.instance.Play(startBeat);
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (Beatmap.entities.Count < 1)
|
||||
return;
|
||||
if (!Conductor.instance.musicSource.isPlaying)
|
||||
if (!Conductor.instance.isPlaying)
|
||||
return;
|
||||
|
||||
if (Input.GetKeyDown(KeyCode.A))
|
||||
|
@ -19,12 +19,12 @@ namespace RhythmHeavenMania.Games.Spaceball
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (Conductor.instance.musicSource.isPlaying && !isShowing)
|
||||
if (Conductor.instance.isPlaying && !isShowing)
|
||||
{
|
||||
anim.Play("AlienSwing", 0, Conductor.instance.loopPositionInAnalog * 2);
|
||||
// anim.Play("AlienSwing", 0, Conductor.instance.loopPositionInAnalog * 2);
|
||||
anim.speed = 0;
|
||||
}
|
||||
else if (!Conductor.instance.musicSource.isPlaying)
|
||||
else if (!Conductor.instance.isPlaying)
|
||||
{
|
||||
anim.Play("AlienIdle", 0, 0);
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ namespace RhythmHeavenMania
|
||||
Conductor.name = "Conductor";
|
||||
Conductor.AddComponent<AudioSource>().clip = music;
|
||||
Conductor.AddComponent<Conductor>();
|
||||
Conductor.AddComponent<AudioDspTimeKeeper>();
|
||||
// Conductor.AddComponent<AudioDspTimeKeeper>();
|
||||
|
||||
if (editor)
|
||||
{
|
||||
|
56
Assets/Scripts/LevelEditor/BeatGrid.cs
Normal file
56
Assets/Scripts/LevelEditor/BeatGrid.cs
Normal file
@ -0,0 +1,56 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
using TMPro;
|
||||
|
||||
namespace RhythmHeavenMania.Editor
|
||||
{
|
||||
public class BeatGrid : MonoBehaviour
|
||||
{
|
||||
private RectTransform rectTransform;
|
||||
|
||||
public float snap;
|
||||
public float count;
|
||||
|
||||
private float lastPosX;
|
||||
|
||||
private List<GameObject> Lines = new List<GameObject>();
|
||||
|
||||
private void Start()
|
||||
{
|
||||
rectTransform = GetComponent<RectTransform>();
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
GameObject line = Instantiate(transform.GetChild(0).gameObject, transform);
|
||||
line.transform.localPosition = new Vector3(i, line.transform.localPosition.y);
|
||||
line.SetActive(true);
|
||||
|
||||
Lines.Add(line);
|
||||
}
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
var pos = new Vector2(Mathf.RoundToInt(Mathf.Abs(transform.parent.localPosition.x) / 100) - 1, transform.localPosition.y);
|
||||
transform.localPosition = pos;
|
||||
|
||||
if (pos.x != lastPosX)
|
||||
UpdateGridNum();
|
||||
|
||||
lastPosX = transform.localPosition.x;
|
||||
}
|
||||
|
||||
private void UpdateGridNum()
|
||||
{
|
||||
for (int i = 0; i < Lines.Count; i++)
|
||||
{
|
||||
var line = Lines[i];
|
||||
float newNum = transform.localPosition.x + i;
|
||||
line.transform.GetChild(0).GetComponent<TMP_Text>().text = newNum.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
11
Assets/Scripts/LevelEditor/BeatGrid.cs.meta
Normal file
11
Assets/Scripts/LevelEditor/BeatGrid.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9c7a9db66b8fb65479a81158697db051
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -18,7 +18,10 @@ namespace RhythmHeavenMania.Editor
|
||||
private float lastBeatPos = 0;
|
||||
|
||||
[Header("Timeline Components")]
|
||||
[SerializeField] private Slider TimelineSlider;
|
||||
[SerializeField] private RectTransform TimelineSlider;
|
||||
[SerializeField] private RectTransform TimelineContent;
|
||||
[SerializeField] private RectTransform TimelineSongPosLineRef;
|
||||
private RectTransform TimelineSongPosLine;
|
||||
|
||||
#region Initializers
|
||||
|
||||
@ -33,7 +36,7 @@ namespace RhythmHeavenMania.Editor
|
||||
SongBeat.text = $"Beat {string.Format("{0:0.000}", Conductor.instance.songPositionInBeats)}";
|
||||
SongPos.text = FormatTime(Conductor.instance.songPosition);
|
||||
|
||||
isPlaying = Conductor.instance.musicSource.isPlaying;
|
||||
isPlaying = Conductor.instance.isPlaying;
|
||||
|
||||
if (Input.GetKeyDown(KeyCode.Space))
|
||||
{
|
||||
@ -54,11 +57,10 @@ namespace RhythmHeavenMania.Editor
|
||||
|
||||
private void SliderControl()
|
||||
{
|
||||
TimelineSlider.maxValue = Conductor.instance.SongLengthInBeats();
|
||||
|
||||
if (isPlaying)
|
||||
if (TimelineSongPosLine != null)
|
||||
{
|
||||
TimelineSlider.value = Conductor.instance.songPositionInBeats;
|
||||
TimelineSongPosLine.transform.localPosition = new Vector3(Conductor.instance.songPositionInBeats, TimelineSlider.transform.localPosition.y);
|
||||
TimelineSongPosLine.transform.localScale = new Vector3(1f / TimelineContent.transform.localScale.x, TimelineSlider.transform.localScale.y, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -67,14 +69,14 @@ namespace RhythmHeavenMania.Editor
|
||||
{
|
||||
if (fromStart)
|
||||
{
|
||||
if (isPlaying && Conductor.instance.musicSource.clip)
|
||||
if (isPlaying)
|
||||
Play(true);
|
||||
else
|
||||
Stop();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!isPlaying && Conductor.instance.musicSource.clip)
|
||||
if (!isPlaying)
|
||||
{
|
||||
Play(false);
|
||||
}
|
||||
@ -88,22 +90,30 @@ namespace RhythmHeavenMania.Editor
|
||||
public void Play(bool fromStart)
|
||||
{
|
||||
if (fromStart) Stop();
|
||||
// isPaused = false;
|
||||
Conductor.instance.musicSource.Play();
|
||||
|
||||
if (!Conductor.instance.isPaused)
|
||||
{
|
||||
TimelineSongPosLine = Instantiate(TimelineSongPosLineRef, TimelineSongPosLineRef.parent).GetComponent<RectTransform>();
|
||||
TimelineSongPosLine.gameObject.SetActive(true);
|
||||
}
|
||||
|
||||
Conductor.instance.Play();
|
||||
}
|
||||
|
||||
public void Pause()
|
||||
{
|
||||
// isPaused = true;
|
||||
Conductor.instance.musicSource.Pause();
|
||||
Conductor.instance.Pause();
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
// isPaused = true;
|
||||
// timelineSlider.value = 0;
|
||||
Conductor.instance.musicSource.time = 0;
|
||||
Conductor.instance.musicSource.Stop();
|
||||
|
||||
Destroy(TimelineSongPosLine.gameObject);
|
||||
|
||||
Conductor.instance.Stop();
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
@ -8,8 +8,6 @@ namespace RhythmHeavenMania.Tests
|
||||
{
|
||||
private void Update()
|
||||
{
|
||||
this.gameObject.transform.rotation = Quaternion.Euler(0, 0, Mathf.Lerp(0, 360, Conductor.instance.loopPositionInAnalog));
|
||||
print(Conductor.instance.loopPositionInAnalog);
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user