Chart Seek Bugfix (#545)
* fix lag spike when starting playback from middle of chart further optimization to GameManager which considerably reduces garbage generation * let dsp offset be calculated on playback start if needed
This commit is contained in:
parent
60d29f19c6
commit
dd461216d9
|
@ -170,11 +170,8 @@ namespace HeavenStudio
|
|||
var chart = GameManager.instance.Beatmap;
|
||||
double offset = chart.data.offset;
|
||||
double dspTime = AudioSettings.dspTime;
|
||||
absTimeAdjust = 0;
|
||||
dspStart = dspTime;
|
||||
startTime = DateTime.Now;
|
||||
|
||||
GameManager.instance.SortEventsList();
|
||||
dspStart = dspTime;
|
||||
|
||||
startPos = GetSongPosFromBeat(beat);
|
||||
firstBeatOffset = offset;
|
||||
|
@ -188,20 +185,21 @@ namespace HeavenStudio
|
|||
{
|
||||
musicScheduledTime = dspTime + musicStartDelay / SongPitch;
|
||||
musicScheduledPitch = SongPitch;
|
||||
musicSource.PlayScheduled(musicScheduledTime);
|
||||
}
|
||||
else
|
||||
{
|
||||
musicScheduledTime = dspTime;
|
||||
musicScheduledPitch = SongPitch;
|
||||
|
||||
musicSource.Play();
|
||||
}
|
||||
musicSource.PlayScheduled(musicScheduledTime);
|
||||
}
|
||||
|
||||
songPosBeat = GetBeatFromSongPos(time);
|
||||
startBeat = songPosBeat;
|
||||
|
||||
absTimeAdjust = 0;
|
||||
startTime = DateTime.Now;
|
||||
|
||||
isPlaying = true;
|
||||
isPaused = false;
|
||||
}
|
||||
|
|
|
@ -108,6 +108,27 @@ namespace HeavenStudio
|
|||
}
|
||||
}
|
||||
|
||||
static bool StringStartsWith(string a, string b)
|
||||
{
|
||||
int aLen = a.Length;
|
||||
int bLen = b.Length;
|
||||
|
||||
int ap = 0; int bp = 0;
|
||||
|
||||
while (ap < aLen && bp < bLen && a [ap] == b [bp])
|
||||
{
|
||||
ap++;
|
||||
bp++;
|
||||
}
|
||||
|
||||
return (bp == bLen);
|
||||
}
|
||||
|
||||
public static bool IsGameSwitch(RiqEntity entity)
|
||||
{
|
||||
return StringStartsWith(entity.datamodel, "gameManager/switchGame");
|
||||
}
|
||||
|
||||
public static List<RiqEntity> GetAllInGameManagerList(string gameName, string[] include)
|
||||
{
|
||||
List<RiqEntity> temp1 = GameManager.instance.Beatmap.Entities.FindAll(c => c.datamodel.Split('/')[0] == gameName);
|
||||
|
|
|
@ -55,6 +55,7 @@ namespace HeavenStudio
|
|||
bool ChartLoadError;
|
||||
|
||||
List<double> eventBeats, tempoBeats, volumeBeats, sectionBeats;
|
||||
List<RiqEntity> allGameSwitches;
|
||||
|
||||
public event Action<double> onBeatChanged;
|
||||
public event Action<RiqEntity> onSectionChange;
|
||||
|
@ -163,8 +164,9 @@ namespace HeavenStudio
|
|||
|
||||
if (Beatmap.Entities.Count >= 1)
|
||||
{
|
||||
SetCurrentGame(Beatmap.Entities[0].datamodel.Split(0));
|
||||
SetGame(Beatmap.Entities[0].datamodel.Split(0));
|
||||
string game = Beatmap.Entities[0].datamodel.Split(0);
|
||||
SetCurrentGame(game);
|
||||
SetGame(game);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -289,8 +291,9 @@ namespace HeavenStudio
|
|||
|
||||
if (Beatmap.Entities.Count >= 1)
|
||||
{
|
||||
SetCurrentGame(Beatmap.Entities[0].datamodel.Split(0));
|
||||
SetGame(Beatmap.Entities[0].datamodel.Split(0));
|
||||
string game = Beatmap.Entities[0].datamodel.Split(0);
|
||||
SetCurrentGame(game);
|
||||
SetGame(game);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -330,26 +333,33 @@ namespace HeavenStudio
|
|||
TimingAccuracyDisplay.instance.MakeAccuracyVfx(time, late);
|
||||
}
|
||||
|
||||
static bool StringStartsWith(string a, string b)
|
||||
{
|
||||
int aLen = a.Length;
|
||||
int bLen = b.Length;
|
||||
|
||||
int ap = 0; int bp = 0;
|
||||
|
||||
while (ap < aLen && bp < bLen && a [ap] == b [bp])
|
||||
{
|
||||
ap++;
|
||||
bp++;
|
||||
}
|
||||
|
||||
return (bp == bLen);
|
||||
}
|
||||
|
||||
public void SeekAheadAndPreload(double start, float seekTime = 8f)
|
||||
{
|
||||
List<RiqEntity> entitiesAtSameBeat = ListPool<RiqEntity>.Get();
|
||||
List<RiqEntity> gameSwitchs = ListPool<RiqEntity>.Get();
|
||||
Minigames.Minigame inf;
|
||||
|
||||
//seek ahead to preload games that have assetbundles
|
||||
//check game switches first
|
||||
foreach (RiqEntity entity in Beatmap.Entities)
|
||||
if (currentPreSwitch < allGameSwitches.Count && currentPreSwitch >= 0)
|
||||
{
|
||||
if (entity.datamodel.Split(1) == "switchGame")
|
||||
if (start + seekTime >= allGameSwitches[currentPreSwitch].beat)
|
||||
{
|
||||
gameSwitchs.Add(entity);
|
||||
}
|
||||
}
|
||||
if (currentPreSwitch < gameSwitchs.Count && currentPreSwitch >= 0)
|
||||
{
|
||||
if (start + seekTime >= gameSwitchs[currentPreSwitch].beat)
|
||||
{
|
||||
string gameName = gameSwitchs[currentPreSwitch].datamodel.Split(2);
|
||||
string gameName = allGameSwitches[currentPreSwitch].datamodel.Split('/')[2];
|
||||
inf = GetGameInfo(gameName);
|
||||
if (inf != null && inf.usesAssetBundle && !inf.AssetsLoaded)
|
||||
{
|
||||
|
@ -389,7 +399,6 @@ namespace HeavenStudio
|
|||
}
|
||||
|
||||
ListPool<RiqEntity>.Release(entitiesAtSameBeat);
|
||||
ListPool<RiqEntity>.Release(gameSwitchs);
|
||||
}
|
||||
|
||||
public void SeekAheadAndDoPreEvent(double start)
|
||||
|
@ -408,8 +417,10 @@ namespace HeavenStudio
|
|||
}
|
||||
SortEventsByPriority(entitiesAtSameBeat);
|
||||
|
||||
string[] seekEntityDatamodel = seekEntity.datamodel.Split('/');
|
||||
|
||||
float seekTime = eventCaller.GetGameAction(
|
||||
eventCaller.GetMinigame(seekEntity.datamodel.Split(0)), seekEntity.datamodel.Split(1)).preFunctionLength;
|
||||
eventCaller.GetMinigame(seekEntityDatamodel[0]), seekEntityDatamodel[1]).preFunctionLength;
|
||||
|
||||
if (start + seekTime >= eventBeats[currentPreSequence])
|
||||
{
|
||||
|
@ -474,8 +485,7 @@ namespace HeavenStudio
|
|||
float seekTime = 8f;
|
||||
//seek ahead to preload games that have assetbundles
|
||||
SeekAheadAndPreload(cond.songPositionInBeatsAsDouble, seekTime);
|
||||
|
||||
SeekAheadAndDoPreEvent(Conductor.instance.songPositionInBeatsAsDouble);
|
||||
SeekAheadAndDoPreEvent(cond.songPositionInBeatsAsDouble);
|
||||
|
||||
if (currentEvent < Beatmap.Entities.Count && currentEvent >= 0)
|
||||
{
|
||||
|
@ -592,7 +602,6 @@ namespace HeavenStudio
|
|||
yield return new WaitForSeconds(delay);
|
||||
bool paused = Conductor.instance.isPaused;
|
||||
|
||||
Conductor.instance.Play(beat);
|
||||
if (paused)
|
||||
{
|
||||
Util.SoundByte.UnpauseOneShots();
|
||||
|
@ -604,11 +613,13 @@ namespace HeavenStudio
|
|||
Conductor.instance.firstBeatOffset = Beatmap.data.offset;
|
||||
SetCurrentEventToClosest(beat);
|
||||
KillAllSounds();
|
||||
}
|
||||
|
||||
Minigame miniGame = currentGameO.GetComponent<Minigame>();
|
||||
if (miniGame != null)
|
||||
miniGame.OnPlay(beat);
|
||||
Minigame miniGame = currentGameO?.GetComponent<Minigame>();
|
||||
if (miniGame != null)
|
||||
miniGame.OnPlay(beat);
|
||||
}
|
||||
|
||||
Conductor.instance.Play(beat);
|
||||
}
|
||||
|
||||
public void Pause()
|
||||
|
@ -700,16 +711,23 @@ namespace HeavenStudio
|
|||
tempoBeats = Beatmap.TempoChanges.Select(c => c.beat).ToList();
|
||||
volumeBeats = Beatmap.VolumeChanges.Select(c => c.beat).ToList();
|
||||
sectionBeats = Beatmap.SectionMarkers.Select(c => c.beat).ToList();
|
||||
|
||||
allGameSwitches = EventCaller.GetAllInGameManagerList("gameManager", new string[] { "switchGame" });
|
||||
}
|
||||
|
||||
void SortEventsByPriority(List<RiqEntity> entities)
|
||||
{
|
||||
string[] xDatamodel;
|
||||
string[] yDatamodel;
|
||||
entities.Sort((x, y) =>
|
||||
{
|
||||
Minigames.Minigame xGame = eventCaller.GetMinigame(x.datamodel.Split(0));
|
||||
Minigames.GameAction xAction = eventCaller.GetGameAction(xGame, x.datamodel.Split(1));
|
||||
Minigames.Minigame yGame = eventCaller.GetMinigame(y.datamodel.Split(0));
|
||||
Minigames.GameAction yAction = eventCaller.GetGameAction(yGame, y.datamodel.Split(1));
|
||||
xDatamodel = x.datamodel.Split('/');
|
||||
yDatamodel = y.datamodel.Split('/');
|
||||
|
||||
Minigames.Minigame xGame = eventCaller.GetMinigame(xDatamodel[0]);
|
||||
Minigames.GameAction xAction = eventCaller.GetGameAction(xGame, xDatamodel[1]);
|
||||
Minigames.Minigame yGame = eventCaller.GetMinigame(yDatamodel[0]);
|
||||
Minigames.GameAction yAction = eventCaller.GetGameAction(yGame, yDatamodel[1]);
|
||||
|
||||
return yAction.priority.CompareTo(xAction.priority);
|
||||
});
|
||||
|
@ -768,7 +786,7 @@ namespace HeavenStudio
|
|||
currentPreEvent = GetIndexAfter(eventBeats, beat);
|
||||
currentPreSequence = GetIndexAfter(eventBeats, beat);
|
||||
|
||||
var gameSwitchs = Beatmap.Entities.FindAll(c => c.datamodel.Split(1) == "switchGame");
|
||||
var gameSwitchs = Beatmap.Entities.FindAll(c => c.datamodel.Split("/")[1] == "switchGame");
|
||||
|
||||
string newGame = Beatmap.Entities[Math.Min(currentEvent, eventBeats.Count - 1)].datamodel.Split(0);
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ using UnityEngine;
|
|||
using HeavenStudio.InputSystem;
|
||||
|
||||
using static JSL;
|
||||
using HeavenStudio.Games;
|
||||
|
||||
namespace HeavenStudio.InputSystem
|
||||
{
|
||||
|
@ -186,6 +187,11 @@ namespace HeavenStudio
|
|||
/*--------------------*/
|
||||
/* MAIN INPUT METHODS */
|
||||
/*--------------------*/
|
||||
|
||||
public static bool GetIsAction(string action)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// BUTTONS
|
||||
//TODO: refactor for controller and custom binds, currently uses temporary button checks
|
||||
|
|
|
@ -501,6 +501,16 @@ namespace HeavenStudio
|
|||
}
|
||||
}
|
||||
|
||||
public class InputAction
|
||||
{
|
||||
public string name;
|
||||
public List<InputActionEntry> mappings;
|
||||
}
|
||||
|
||||
public class InputActionEntry
|
||||
{
|
||||
}
|
||||
|
||||
public delegate void EventCallback();
|
||||
public delegate void ParamChangeCallback(string paramName, object paramValue, RiqEntity entity);
|
||||
|
||||
|
|
Loading…
Reference in a new issue