Skip to content

Commit fbc8a32

Browse files
committed
Code documentation update, instant rewind fix
+Rounding values in Circular buffer due to float imprecisions +Code documentation update +Improved naming scheme +Fixed instant rewinds +Added more error logging when system is used improperly
1 parent 14bae79 commit fbc8a32

7 files changed

Lines changed: 65 additions & 56 deletions

File tree

Assets/TimeRewinder/ExampleScene/TimeRewindExample 2.unity

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3065,8 +3065,8 @@ MonoBehaviour:
30653065
trackParticles:
30663066
enabled: 0
30673067
value:
3068-
particleLimiter: 0
3069-
particleResetTo: 0
3068+
particleTrackingLimit: 0
3069+
particleRestartFrom: 0
30703070
particlesData: []
30713071
--- !u!4 &4475510621848781043 stripped
30723072
Transform:

Assets/TimeRewinder/TimeRewinderImplementation/Scripts/CircularBuffer.cs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ public T ReadLastValue()
5353
{
5454
return dataArray[bufferCurrentPosition];
5555
}
56+
5657
/// <summary>
5758
/// Read specified value from circular buffer
5859
/// </summary>
@@ -74,15 +75,16 @@ public T ReadFromBuffer(float seconds)
7475
}
7576
private void MoveLastBufferPosition(float seconds)
7677
{
77-
int howManyBeforeLast=(int)(howManyRecordsPerSecond*seconds);
78+
int howManyBeforeLast=Mathf.RoundToInt(howManyRecordsPerSecond*seconds);
7879

79-
if ((bufferCurrentPosition - howManyBeforeLast) < 0)
80+
int moveBy = - (howManyBeforeLast - bufferCurrentPosition) - 1;
81+
if (moveBy < 0)
8082
{
81-
bufferCurrentPosition = bufferCapacity - (howManyBeforeLast - bufferCurrentPosition);
83+
bufferCurrentPosition = bufferCapacity +moveBy;
8284
}
8385
else
8486
{
85-
bufferCurrentPosition -= howManyBeforeLast;
87+
bufferCurrentPosition -= (howManyBeforeLast+1);
8688
}
8789
}
8890
}

Assets/TimeRewinder/TimeRewinderImplementation/Scripts/ImplementedObjects/GenericRewind.cs

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,16 @@ public class GenericRewind : RewindAbstract
1313

1414
public override void Rewind(float seconds)
1515
{
16-
1716
if (trackTransform)
1817
RestoreTransform(seconds);
1918
if (trackVelocity)
2019
RestoreVelocity(seconds);
2120
if (trackAnimator)
2221
RestoreAnimator(seconds);
23-
if (trackParticles.Enabled)
24-
RestoreParticles(seconds);
25-
if(trackAudio)
22+
if (trackAudio)
2623
RestoreAudio(seconds);
24+
if (trackParticles.Enabled)
25+
RestoreParticles(seconds);
2726
}
2827

2928
public override void Track()
@@ -34,16 +33,15 @@ public override void Track()
3433
TrackVelocity();
3534
if (trackAnimator)
3635
TrackAnimator();
37-
if (trackParticles.Enabled)
38-
TrackParticles();
3936
if (trackAudio)
4037
TrackAudio();
38+
if (trackParticles.Enabled)
39+
TrackParticles();
4140
}
4241
private void Start()
4342
{
4443
if(trackParticles.Enabled)
4544
InitializeParticles(trackParticles.Value);
4645
}
47-
4846
}
4947

Assets/TimeRewinder/TimeRewinderImplementation/Scripts/ImplementedObjects/ScaleRewind.cs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,20 +25,17 @@ public override void Track()
2525
TrackObjectScale();
2626
}
2727

28-
2928
//In this method define, what will be restored on time rewinding. In our case we want to restore object scale
3029
public override void Rewind(float seconds)
3130
{
3231
RestoreObjectScale(seconds);
3332
}
3433

35-
3634
// This is an example of custom variable tracking
3735
public void TrackObjectScale()
3836
{
3937
trackedObjectScales.WriteLastValue(transform.localScale);
4038
}
41-
4239

4340
// This is an example of custom variable restoring
4441
public void RestoreObjectScale(float seconds)

Assets/TimeRewinder/TimeRewinderImplementation/Scripts/RewindAbstract.cs

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ public struct TransformValues
4545
}
4646

4747
/// <summary>
48-
/// Call this method in Track() if you want to track object Position and Rotation
48+
/// Call this method in Track() if you want to track object Transforms (position, rotation and scale)
4949
/// </summary>
5050
protected void TrackTransform()
5151
{
@@ -56,8 +56,9 @@ protected void TrackTransform()
5656
trackedTransformValues.WriteLastValue(valuesToWrite);
5757
}
5858
/// <summary>
59-
/// Call this method in GetSnapshotFromSavedValues() to restore Position and Rotation
59+
/// Call this method in Rewind() to restore Transform
6060
/// </summary>
61+
/// <param name="seconds">Use seconds parameter from Rewind() method</param>
6162
protected void RestoreTransform(float seconds)
6263
{
6364
TransformValues valuesToRead = trackedTransformValues.ReadFromBuffer(seconds);
@@ -74,6 +75,7 @@ public struct VelocityValues
7475
public float angularVelocity2D;
7576
}
7677
CircularBuffer<VelocityValues> trackedVelocities;
78+
7779
/// <summary>
7880
/// Call this method in Track() if you want to track velocity of Rigidbody
7981
/// </summary>
@@ -100,9 +102,11 @@ protected void TrackVelocity()
100102
Debug.LogError("Cannot find Rigidbody on the object, while TrackVelocity() is being called!!!");
101103
}
102104
}
105+
103106
/// <summary>
104-
/// Call this method in GetSnapshotFromSavedValues() to velocity of Rigidbody
107+
/// Call this method in Rewind() to restore velocity of Rigidbody
105108
/// </summary>
109+
/// <param name="seconds">Use seconds parameter from Rewind() method</param>
106110
protected void RestoreVelocity(float seconds)
107111
{
108112
if(body!=null)
@@ -149,9 +153,11 @@ protected void TrackAnimator()
149153
trackedAnimationTimes[i].WriteLastValue(valuesToWrite);
150154
}
151155
}
156+
152157
/// <summary>
153-
/// Call this method in GetSnapshotFromSavedValues() to restore Animator state
158+
/// Call this method in Rewind() to restore Animator state
154159
/// </summary>
160+
/// <param name="seconds">Use seconds parameter from Rewind() method</param>
155161
protected void RestoreAnimator(float seconds)
156162
{
157163
animator.speed = 0;
@@ -190,9 +196,11 @@ protected void TrackAudio()
190196

191197
trackedAudioTimes.WriteLastValue(dataToWrite);
192198
}
199+
193200
/// <summary>
194-
/// Call this method in GetSnapshotFromSavedValues() to restore Audio
201+
/// Call this method in Rewind() to restore Audio
195202
/// </summary>
203+
/// <param name="seconds">Use seconds parameter from Rewind() method</param>
196204
protected void RestoreAudio(float seconds)
197205
{
198206
AudioTrackedData readValues = trackedAudioTimes.ReadFromBuffer(seconds);
@@ -224,12 +232,10 @@ public struct ParticleTrackedData
224232
public float particleTime;
225233
}
226234

227-
228235
private List<ParticleData> particleSystemsData;
229236

230237
/// <summary>
231-
/// particle system and its enabler, which is for tracking if particle system game object is enabled or disabled
232-
/// particle
238+
/// particle system and its main object for tracking if particle system game object is enabled or disabled
233239
/// </summary>
234240
[Serializable]
235241
public struct ParticleData
@@ -255,14 +261,12 @@ public struct ParticlesSetting
255261
/// <summary>
256262
/// Use this method first when using particle rewinding implementation
257263
/// </summary>
258-
/// <param name="particleDataList">Data defining which particles will be tracked</param>
259-
/// <param name="particleTimeLimiter">For long lasting particle systems, set time tracking limiter to drastically improve performance </param>
260-
/// <param name="resetParticleTo">Variable defining to which second should tracking return to after particle tracking limit was hit. Play with this variable to get better results, so the tracking resets are not much noticeable.</param>
264+
/// <param name="particleSettings"></param>
261265
protected void InitializeParticles(ParticlesSetting particleSettings)
262266
{
263267
if(particleSettings.particlesData.Any(x=>x.particleSystemMainObject == null||x.particleSystem==null))
264268
{
265-
Debug.LogError("Initialized particle system are missing data. Either Particle System or Particle System Enabler is not filled for some values");
269+
Debug.LogError("Initialized particle system are missing data. Either Particle System or Main Object is not filled for some values");
266270
}
267271
particleSystemsData = particleSettings.particlesData;
268272
particleTimeLimiter = particleSettings.particleTrackingLimit;
@@ -314,13 +318,14 @@ protected void TrackParticles()
314318
}
315319
catch
316320
{
317-
Debug.LogError("Particles Data not filled properly!!! Fill both the Particle System and Particle Main object fields for each element");
321+
Debug.LogError("Particles Data not filled properly!!! Fill both the Particle System and Particle Main Object fields for each element");
318322
}
319323

320324
}
321325
/// <summary>
322-
/// Call this method in GetSnapshotFromSavedValues() to Particles
326+
/// Call this method in Rewind() to restore Particles
323327
/// </summary>
328+
/// <param name="seconds">Use seconds parameter from Rewind() method</param>
324329
protected void RestoreParticles(float seconds)
325330
{
326331
for (int i = 0; i < particleSystemsData.Count; i++)
@@ -349,15 +354,15 @@ protected void RestoreParticles(float seconds)
349354

350355

351356
/// <summary>
352-
/// Main method where all tracking is filled, lets choose here what will be tracked for specific object
357+
/// Main method where all tracking is filled, choose what will be tracked for specific object
353358
/// </summary>
354359
public abstract void Track();
355360

356361

357362
/// <summary>
358-
/// Main method where all rewinding is filled, lets choose here what will be rewinded for specific object
363+
/// Main method where all rewinding is filled, choose what will be rewinded for specific object
359364
/// </summary>
360-
/// <param name="seconds">Parameter defining how many seconds we want to rewind back</param>
365+
/// <param name="seconds">Parameter defining how many seconds you want to rewind back</param>
361366
public abstract void Rewind(float seconds);
362367

363368
}

Assets/TimeRewinder/TimeRewinderImplementation/Scripts/RewindInputs/RewindBySlider.cs

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@
88
/// </summary>
99
public class RewindBySlider : MonoBehaviour,IPointerDownHandler, IPointerUpHandler
1010
{
11-
//Cause TimeManager timestep is set to Time.FixedDeltaTime, animator of the slider is also se to same timestep
12-
1311
[SerializeField] Slider slider;
1412
[SerializeField] AudioSource rewindSound;
1513

@@ -30,6 +28,7 @@ void Start()
3028
sliderAnimator = slider.GetComponent<Animator>();
3129
SetNormalSpeed();
3230
}
31+
#region Additional controls
3332
public void RestartTracking()
3433
{
3534
slider.value = slider.minValue;
@@ -84,7 +83,8 @@ public void ResumeRewind()
8483
rewindResume.interactable = false;
8584
rewindPause.interactable = true;
8685
}
87-
86+
#endregion
87+
8888
public void OnPointerDown(PointerEventData eventData)
8989
{
9090
howManyFingersTouching++;
@@ -121,7 +121,7 @@ public void OnSliderDown()
121121
if (slider.interactable)
122122
{
123123
if(!isRewindPaused)
124-
RewindManager.Instance.StartRewindTimeBySeconds(-slider.value*RewindManager.Instance.HowManySecondsToTrack); //Start rewind preview. (Note that slider have negative values, that is why it is passed with minus sign)
124+
RewindManager.Instance.StartRewindTimeBySeconds(-slider.value*RewindManager.Instance.HowManySecondsToTrack); //Start rewind preview (note that slider have negative values, that is why it is passed with minus sign)
125125

126126
SliderAnimationPause();
127127
rewindSound.Play();
@@ -133,24 +133,23 @@ private void SetNormalSpeed()
133133
}
134134
public void OnSliderUpdate(float value)
135135
{
136-
RewindManager.Instance.SetTimeSecondsInRewind(-value * RewindManager.Instance.HowManySecondsToTrack); //If slider value changes, change rewind preview state (Note that slider have negative values, that is why it is passed with minus sign)
136+
RewindManager.Instance.SetTimeSecondsInRewind(-value * RewindManager.Instance.HowManySecondsToTrack); //If slider value changes, change rewind preview state (note that slider have negative values, that is why it is passed with minus sign)
137137
}
138138
public void SliderAnimationPause() //When rewinding slider animator is paused
139139
{
140140
sliderAnimator.speed= 0;
141-
142141
}
143-
public void RestoreSliderAnimation() //Slider restoration so after uses releases it, it will snap back to correct value
142+
public void RestoreSliderAnimation() //Slider restoration after user releases it, it will snap back to correct value
144143
{
145144
float animationTimeStartFrom = slider.value - slider.minValue;
146145
sliderAnimator.Play("AutoResizeAnim", 0, animationTimeStartFrom);
147146
StartCoroutine(ResetSliderValue());
148147
}
148+
149149
//Cause slider animator is in fixed update
150150
IEnumerator ResetSliderValue()
151151
{
152152
yield return new WaitForFixedUpdate();
153153
slider.value = 0;
154-
}
155-
154+
}
156155
}

Assets/TimeRewinder/TimeRewinderImplementation/Scripts/RewindManager.cs

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,10 @@ public class RewindManager : MonoBehaviour
3737
List<RewindAbstract> _rewindedObjects;
3838

3939
/// <summary>
40-
/// Call this method to rewind time by specified seconds instantly without snapshot preview
40+
/// Call this method to rewind time by specified seconds instantly without snapshot preview. Usefull for one time instant rewinds.
4141
/// </summary>
4242
/// <param name="seconds">Parameter defining how many seconds should object rewind to from now (Parameter must be >=0).</param>
43-
public void RewindTimeBySeconds(float seconds)
43+
public void InstantRewindTimeBySeconds(float seconds)
4444
{
4545
if(seconds>HowManySecondsAvailableForRewind)
4646
{
@@ -52,17 +52,20 @@ public void RewindTimeBySeconds(float seconds)
5252
Debug.LogError("Parameter in RewindTimeBySeconds() must have positive value!!!");
5353
return;
5454
}
55-
5655
_rewindedObjects.ForEach(x => x.Rewind(seconds));
56+
HowManySecondsAvailableForRewind -= seconds;
5757
BuffersRestore?.Invoke(seconds);
5858
}
5959
/// <summary>
60-
/// Call this method if you want to start rewinding time with ability to preview snapshots. After done rewinding, StopRewindTimeBySeconds() must be called!!!. To update snapshot preview between, call method SetTimeSecondsInRewind()
60+
/// Call this method if you want to start rewinding time with ability to preview snapshots. After done rewinding, StopRewindTimeBySeconds() must be called!!!. To update snapshot preview between, call method SetTimeSecondsInRewind().
6161
/// </summary>
6262
/// <param name="seconds">Parameter defining how many seconds before should the rewind preview rewind to (Parameter must be >=0)</param>
6363
/// <returns></returns>
6464
public void StartRewindTimeBySeconds(float seconds)
6565
{
66+
if (IsBeingRewinded)
67+
Debug.LogError("The previous rewind must be stopped by calling StopRewindTimeBySeconds() before you start another rewind");
68+
6669
CheckReachingOutOfBounds(seconds);
6770

6871
rewindSeconds = seconds;
@@ -79,14 +82,28 @@ public void SetTimeSecondsInRewind(float seconds)
7982
rewindSeconds = seconds;
8083
}
8184
/// <summary>
82-
/// Call this method to stop previewing rewind state and effectively set current values to the rewind state
85+
/// Call this method to stop previewing rewind state and resume normal game flow
8386
/// </summary>
8487
public void StopRewindTimeBySeconds()
8588
{
89+
if (!IsBeingRewinded)
90+
Debug.LogError("Rewind must be started before you try to stop it. StartRewindTimeBySeconds() must be called first");
91+
8692
HowManySecondsAvailableForRewind -= rewindSeconds;
8793
BuffersRestore?.Invoke(rewindSeconds);
8894
IsBeingRewinded = false;
8995
}
96+
/// <summary>
97+
/// Call if you want to restart the whole tracking system
98+
/// </summary>
99+
public void RestartTracking()
100+
{
101+
if (IsBeingRewinded)
102+
StopRewindTimeBySeconds();
103+
104+
HowManySecondsAvailableForRewind = 0;
105+
TrackingEnabled = true;
106+
}
90107
private void CheckReachingOutOfBounds(float seconds)
91108
{
92109
if (Mathf.Round(seconds*100) > Mathf.Round(HowManySecondsAvailableForRewind*100))
@@ -100,15 +117,6 @@ private void CheckReachingOutOfBounds(float seconds)
100117
return;
101118
}
102119
}
103-
public void RestartTracking()
104-
{
105-
if(IsBeingRewinded)
106-
StopRewindTimeBySeconds();
107-
108-
HowManySecondsAvailableForRewind = 0;
109-
TrackingEnabled = true;
110-
}
111-
112120
private void Awake()
113121
{
114122
_rewindedObjects = FindObjectsOfType<RewindAbstract>().ToList();

0 commit comments

Comments
 (0)