In Naninovel 1.19, there is new feature called ITime
where we can use custom time rather than use built-in UnityEngine.Time
.
Benefit of using custom time, we can decrease or increase time in custom minigame without affecting Naninovel objects like dialogue, transition, typing effect, tweener, etc and vice versa.
You can copy the code below or download from my gist https://gist.github.com/restush/43b800a ... 07fa7d1cd8
Here is CustomTime.cs
Code: Select all
/// <summary> Custom Unity Time based on <see cref="System.Diagnostics.Stopwatch"/> </summary>
public class CustomTime : ITime
{
public float TimeScale { get; set; }
public float Time { get; private set; }
public float DeltaTime { get; private set; }
public float UnscaledTime { get; private set; }
public float UnscaledDeltaTime { get; private set; }
public int FrameCount { get; private set; }
private readonly System.Diagnostics.Stopwatch stopwatch;
private readonly float defaultTimeScale; // default `TimeScale` that set in first instance
private float lastTimeScale; // last `TimeScale` before changed
private long lastElapsedTicks; // last Stopwatch's ticks in Update method
public CustomTime(float timeScale = 1f)
{
stopwatch = new System.Diagnostics.Stopwatch();
stopwatch.Start();
lastElapsedTicks = stopwatch.ElapsedTicks;
TimeScale = timeScale;
lastTimeScale = timeScale;
defaultTimeScale = timeScale;
}
/// <summary>Calculate `Time` and `DeltaTime` based on current frame.</summary>
/// <remarks>Important: Call this method in Monobehaviour.Update()</remarks>
public void Update()
{
CalculateDeltaTime();
FrameCount++;
void CalculateDeltaTime()
{
long currentElapsedTicks = stopwatch.ElapsedTicks;
UnscaledTime = stopwatch.ElapsedMilliseconds * 0.001f;
UnscaledDeltaTime = (currentElapsedTicks - lastElapsedTicks) * (1.0f / System.Diagnostics.Stopwatch.Frequency);
DeltaTime = UnscaledDeltaTime * TimeScale;
Time += DeltaTime;
lastElapsedTicks = currentElapsedTicks;
}
}
/// <summary>Freeze the time.</summary>
/// <remarks>Info: Before changed, the `TimeScale` cached to <see cref="lastTimeScale"/>.</remarks>
public void Pause()
{
lastTimeScale = TimeScale;
TimeScale = 0;
}
/// <summary>Resume the time.</summary>
/// <remarks>Info: Resume the time based on lastTimeScale.</remarks>
public void Resume()
{
TimeScale = lastTimeScale;
}
/// <summary>Set default `TimeScale` that set in first instance.</summary>
public void SetDefaultSpeed() => TimeScale = defaultTimeScale;
public void Speed1x() => TimeScale = 1;
public void Speed2x() => TimeScale = 2;
public void Speed5x() => TimeScale = 5;
public void Speed10x() => TimeScale = 10;
}
Here is how to implement it. Make sure attach Initialize.cs class in one of GameObject in Scene then disable Initialize On Application Load
in Naninovel setting.
Code: Select all
public class Initialize : MonoBehaviour
{
private ITime time;
private async UniTask Start()
{
time = new CustomTime();
await RuntimeInitializer.InitializeAsync(time: time);
}
private void Update()
{
if (this.time is CustomTime time)
time.Update();
}
}
Updated 21/10/2023