- Home /
How to store a variable's values for a specific time window (say 500ms) for further reuse in void update?
Hello friends
I want to make a buffer window of say 0.5 Sec storing some changing values of variables. And as the game progresses old values get deleted from the top and new values added at the bottom. i.e. buffer window moves downward (may be imagined) :)
void Update ()
{
float buffer = 0.5f;
float dt = Time.deltaTime; // time it took to complete the last frame
float R = Random.Range(-10.0f, 10.0f); // any value just for the sake of this example
float TimeElapsed = Time.time; // any value just for the sake of this example
// above three values I want to store for 0.5 sec
// when the game starts buffer size is zero
// first values will be stored in the first row, second in second row and so on..
// as the game progresses buffer size increses till sum of 'dt's in the buffer < 0.5sec
// as the game further progresses buffer window moves downwards
// i.e. 1st row's values get deleted and 2nd row's value will move to 1st row and so on..
// as 'dt' is not constant buffer size may change. (Say ~30 for 60FPS)
// if 'n' is the buffer size then I need the following loopto run
for (int m = 1; m <= n; m = m++)
{
totaltime += dt_buffer[m];
num += R_buffer[m];
CumTime += TimeElapsed_buffer[m];
}
Debug.Log " Total Time " + totaltime);
Debug.Log " Some Number " + num);
Debug.Log " Cumulative Time " + CumTime);
}
I hope my question is expressive enough. :D
Thank you very much.
Answer by JeyP4 · Apr 19, 2018 at 09:58 PM
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityStandardAssets.Vehicles.Car;
using UnityStandardAssets.CrossPlatformInput;
public class PredictedPosition : MonoBehaviour
{
public class parameters
{
public float dt;
public float R;
public float TimeElapsed;
public parameters(float newdt, float newR, float newTimeElapsed)
{
dt = newdt;
R = newR;
TimeElapsed = newTimeElapsed;
}
}
List<parameters> list = new List<parameters> ();
void Update()
{
float delay = 0.5f;
list.Add (new parameters(Time.deltaTime, Random.Range(-10.0f,10.0f), Time.time));
for (int i = 0; i < 100; i++)
{
if (list.Sum (pkg => pkg.dt) > delay)
list.RemoveAt (0);
else
break;
}
float totaltime = 0, num = 0, CumTime = 0;
for (int m = 0; m <= list.Count (); m = m++)
{
totaltime += list.ElementAt (m).dt;
num += list.ElementAt (m).R;
CumTime += list.ElementAt (m).TimeElapsed;
}
Debug.Log (" Total Time " + totaltime);
Debug.Log (" Some Number " + num);
Debug.Log (" Cumulative Time " + CumTime);
}
Answer by IJM · Apr 19, 2018 at 10:41 AM
Here is an example from the top of my head:
//Buffer data
private struct BufferData
{
public int ValueA;
public float ValueB;
public float DeltaT;
}
//Buffer
private List<BufferData> _buffer = new List<BufferData>();
private float _bufferTime;
void Update()
{
var deltaT = Time.deltaTime;
_buffer.Insert(0, new BufferData() { ValueA = ..., ValueB = ..., DeltaT = deltaT });
_bufferTime += deltaT;
while(_bufferTime > 0.5f)
{
var lastIndex =_buffer.Count-1;
_bufferTime -= _buffer[lastIndex].DeltaT;
_buffer.RemoveAt(lastIndex);
}
//At this point, _buffer contains minimum of one item, and maximum of 500 miliseconds of data
...
Have in mind that if you are using fixed framerate, let's say 60PFS. You can just make a buffer that has 30 items, and that will be ~0.5 seconds of data.
Hey thank you for so quick reply
can u tell me how to add elements in this list. (if possible in C#, because i dont know java). Thank u again.. :)
I gave you an example in C#. Just replace BufferData properties, except DeltaT, and do whatever you want. You can add a element to a list with Add, or you can use Insert, like i did, with specific index. (In my case 0, so that new elements go to the first place)
Ins$$anonymous$$d of a List you may want to use a ring buffer to avoid constant moving around your whole buffer since inserting at the front will shift all elements down by one. Also if you want a "running total" it's much more efficient to keep the total and each frame just add the new value and subtract the oldest ones that you're going to remove from the buffer. For large buffers this is much more efficient since you only need to add one and remove one or two values each frame. When using a ring buffer you don't even need to move the values around. I've created a simple RingBuffer if you need one.
Ya I know your RingBufffer.cs I tried but but didnt succeed to implement that in this task.
Any help from you will be really appreciated. Thank you :)
Circular buffer is fixed size, this supports variable frame rate. I've optimized the code :)
Actually a List also uses a fixed size buffer. It just automatically creates a new larger buffer when it runs out of space and copies the old elements over. You just need to choose a large enough buffer or increase it's size when you run out of space Though in this case you get exact the behaviour of System.Collections.Queue<T>
. It's also a circular buffer but it grows rather than overwriting the oldest values when running out of space. The point why using a circular buffer in the first place it to avoid moving all elements around each time you add / remove a value. So an add / remove operation becomes O(1) ins$$anonymous$$d of O(n).
Your answer
Follow this Question
Related Questions
A node in a childnode? 1 Answer
future updates 0 Answers
Update List Item 0 Answers
What do you think of this? List, Vector 3 and Update 1 Answer
List is empty in Update 0 Answers