Simple Simulation: Fast Forward and Normal Timer - c#

A simple draw and move simulation uses the following:
A clock timer. Interval: 200ms.
A movement timer. Interval: 1ms.
Movement Constant. Value: 2.
Every time the movement timer ticks, a picture moves by addition by the movement constant. (i.e. picture.X = picture.X + movement constant)
The problem is fast forwarding. The user CAN fast-forward the simulation at any time.
How do I change theses three values (clock timer, movement timer, movement constant) to make the simulation speed faster without sacrificing integrity during a fast-forwarded run?

If integer multiples (1x, 2x, 3x, ...) for fast forwarding is enough, you could just run the simulation function several times during the timer handler function.
I'm not sure what you're doing with the clock timer though, but the same principle would apply to whatever it's doing.

You can have an "internal time" that's independant of the "real time". When the system runs at the base speed, these two increase in sync (every tick of the timer - that's set to 1 ms - adds 1ms to the internal time.
When you have a speedup multiplier of 2x, then add 2ms to the internal time for every timer tick.
Next you will have to calculate positions based on the internal time, with maybe a function like
newposition = startposition + speed * time

As Hans implied, there is a 'grain-size' in time and space in most simulations. Agents are then scheduled by skipping over time intervals ('ticks'). However, if you need more flexible and well-tested scheduling, you might want to borrow a scheduler from an ABM simulation package such as Mason (for Java) or Repast (Java or C++), or look at their open-source scheduler class codes and translate to another language.

Related

Approach to solve a not accurate replay system

Trying to make accurate replay system in unity and c#
Hi all,
Im working on a racing game and I decided to add a replay system to allow "ghost car" too, initially I was recordng data in some events like key pressed but only recording that data in all frames I manage a smooth replay, well its still ok as file is not huge and replay works, but the trouble is there is always a slight variation in time, only like 0.1 seconds or 0.2 at the most, I have a list of keyframes and in each position I record a time to be shown, the trouble I think is that because fps vary then not in all runs the same time marks are shown then the winning frame's time is not always being rendered so the winning frame happens in next update slightly after it should be shown. Im using c# and unity just in case, but I think its independent to this mainly. Thanks a lot about any clue, I have been around this issue for some time now
It sounds like you're doing frame-by-frame replay which, as you've discovered, requires your frames to play back with the same delay as the recording. In a game-render loop, that's not guaranteed to happen.
As you record the car states (position, heading, etc) per frame, you need to also record a timestamp (in this case, accumulating Time.deltaTime from race start should suffice).
When you play it back, find the current timestamp and interpolate (ie, Lerp) the car's state from the recorded bounding frames.
Hints for frame interpolation:
class Snapshot {
public float Timestamp;
public Matrix4x4 Transform; // As an example. Put more data here.
}
private int PrevIndex = 0;
private List<Snapshot> Snapshots = (new List<Snapshot>()).OrderBy(m => m.Timestamp).ToList();
private float GetLerpFactor(float currentTimestamp) {
if ( PrevIndex == Snapshots.Count - 1)
return 0; // Reached end of Snapshots
while (currentTimestamp >= Snapshots[PrevIndex + 1].Timestamp)
PrevIndex++; // move 'frame' forward
var currentDelta = Mathf.Max(0f, currentTimestamp - Snapshots[PrevIndex].Timestamp);
var fullDelta = Snapshots[PrevIndex + 1].Timestamp - Snapshots[PrevIndex].Timestamp;
var lerpFactor = currentDelta / fullDelta;
return lerpFactor;
}
Unless for some reason you need to interact with "ghost" car (like collisions) record final data on position/speed/direction at frequent enough original moments of time and interpolate that to new simulation. I would not record raw inputs but rather resulting changes (like gear shifts) unless you need to measure/show how fast user reacted to something.
If you really want to replay the same inputs you'd have to run two separate simulations at the same time so physics and timing of "real" version don't impact "ghost" one, most likely you'll have to again interpolate output of "ghost" simulation to align with real one (unless you have fixed time steps).

Is fixedUpdate time interval in Unity3d is really constant?

According to the Unity documentation, FixedUpdate get called in a fixed time step. This can be seen when we output the time.Deltatime in FixedUpdate call back.
However, when I tried to check the deltatime using .Net time system (i.e., TimeDate.now.millisecond) in FixedUpdate call back, the output of deltatime is not constant.
I suspected that the clock used by Unity3d is not the same from my PC's clock. But I am not sure if I am right or not. Does anyone know the reason about this?
Thanks
Note: the main question is about why capturing the interval time between consecutive FixedUpdate() using .NET DateTime.now produce the inconsistent time step while it shows consistent time step using Time.Deltatime.
Please check this.
FixedUpdate: FixedUpdate is often called more frequently than Update.
It can be called multiple times per frame, if the frame rate is low
and it may not be called between frames at all if the frame rate is
high. All physics calculations and updates occur immediately after
FixedUpdate. When applying movement calculations inside FixedUpdate,
you do not need to multiply your values by Time.deltaTime. This is
because FixedUpdate is called on a reliable timer, independent of the
frame rate.
And also in image you can read this near FixedUpdate State:
The physics cycle may happen more than once per frame if the fixed
time step is less then the actual frame update time.
If you need to check time in FixedUpdate you should use Time.fixedDeltaTime.

Using timer and game loop

I'm building a simple console game, there is the player who moves when key press down, and there are enemies which moves automatically, each type of enemy moves one time in X miliseconds.
As I understood I should using the timer, but I don't really know how to do that in the game loop (isn't built yet because I don't know how to do with the timer. but it should be while loop I think). the game ends when the enemy 'touch' the player (same x and y).
One important thing: I can't you in this exercise in Thread, but if you have other suggestions instead of using Timer you are welcome.
Thank you.
You normally don't use conventional timers in games. Games have a very different mechanism for handling their logic and the time that passed, they normally don't work with timers or not in the way you would expect:
Games normally have something called a game loop. Generally speaking it's three main functions that are called one after the other in a loop:
while(running)
{
HandleUserInput();
ChangeWorld();
Render();
}
You get user input, you change the game world accordingly and you draw it to the screen. Now, the faster your computer is, the faster this loop runs. That's good for the graphics (think FPS), but bad for the game. Imagine Tetris where every frame the blocks move. Now I would not want to buy a faster computer, the game would get more difficult that way.
So to keep the game speed constant independent of the power of the computer, the loop considers the time passed:
while(running)
{
var timePassedSinceLastLoop = CalculateTimeDelta();
HandleUserInput();
ChangeWorld(timePassedSinceLastLoop);
Render();
}
Now imagine a cooldown for something in game. The player pressed "a", some cool action happened and although he may press "a" again, nothing will happen for the next 5 seconds. But the game still runs and does all the other things that may happen ingame. This is not a conventional timer. It's a variable, lets call it ActionCooldown, and once the player triggers the action, it's set to 5 seconds. Every time the world changes, the timePassed is subtracted from that number until it's zero. All the time, the game is running and handling input and rendering. But only once ActionCooldown hits zero, another press of "a" will trigger that action again.
The ChangeWorld method includes all automatic changes to the world. Enemies, missiles, whatever moves without player interaction. And It moves based on time. If the enemy moves one square per second, You need to make his coordinate a float and add a fraction of a square every time the loop is run.
Lets say you have 30 fps so your loop runs 30 times a second. Your enemy now needs to move 1/30 of a square each loop. Then it will in the end have moved one full square per second.
The general premise behind the timer is to repeat some code every n.
To create the timer use this:
System.Timers.Timer aTimer = new System.Timers.Timer();
aTimer.Elapsed+=new ElapsedEventHandler(OnTimedEvent);
// Set the Interval to 1 millisecond. Note: Time is set in Milliseconds
aTimer.Interval=1;
aTimer.Enabled=true;
Then you implement this method:
private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
//Whatever you need repeated
}
The full example can be found here:
http://msdn.microsoft.com/en-us/library/system.timers.timer(v=vs.71).aspx

How to make timer keep runing while loop wait for another time result?

i have the following issue in my code,
i have this loop running on timer (this is just a small part of the loops that running on the big timer),
inside that big timer (he tick every 1 second) i have 1 method that need to wait 5 second then continue with the the rest of the loop code, but i want that it wont stuck the code and the timer will continue to run every 1sec and wont wait for those 5sec.
what i did i add a new timer (timer_deva) that tick every 5sec and did all the checks inside it, and then timer stops.
so my issue is that i need to wait 5sec to retrieve a value to complete my code, but i need that my main timer will keep running simultaneously, and when he get his result for the other time he will need to complete the code he left behind.
thanks in advance,
else if (mobID.Equals(Convert.ToInt32(txtDeva)))
{
//START CHECK WITH TIMER
timer_deva.Start();
//Methods inside timer_deva update the winnerNation
//END CHECK TIMER - GET RESULT
winner(zoneId, winnerNation, humansKills, orcKills);
}
tl;dr
Conventional Timers are not used in games. Games have a very different mechanism for handling their logic and the time that passed.
Long Version:
I know this may not answer your question directly, but it's way to much text to cramp into a comment. Your timers sound very complicated and hierarchical. From your variable names I will assume you are programming a game. Games normally don't work with timers or not in the way you would expect. This different game-like behaviour would help you a lot in your timers problem and may even help you more with your design in general.
Games normally have something called a game loop. Generally speaking it's three main functions that are called one after the other in a loop:
while(running)
{
HandleUserInput();
ChangeWorld();
Render();
}
You get user input, you change the game world accordingly and you draw it to the screen. Now, the faster your computer is, the faster this loop runs. That's good for the graphics (think FPS), but bad for the game. Imagine Tetris where every frame the blocks move. Now I would not want to buy a faster computer, the game would get more difficult that way.
So to keep the game speed constant independent of the power of the computer, the loop considers the time passed:
while(running)
{
var timePassedSinceLastLoop = CalculateTimeDelta();
HandleUserInput();
ChangeWorld(timePassedSinceLastLoop);
Render();
}
Now imagine a cooldown for something in game. The player pressed "a", some cool action happened and although he may press "a" again, nothing will happen for the next 5 seconds. But the game still runs and does all the other things that may happen ingame. This is not a conventional timer. It's a variable, lets call it ActionCooldown, and once the player triggers the action, it's set to 5 seconds. Every time the world changes, the timePassed is subtracted from that number until it's zero. All the time, the game is running and handling input and rendering. But only once ActionCooldown hits zero, another press of "a" will trigger that action again.

High precision sleep or How to yield CPU and maintain precise frame rate

I work on a 2D game engine that has a function called LimitFrameRate to ensure that the game does not run so fast that a user cannot play the game. In this game engine the speed of the game is tied to the frame rate. So generally one wants to limit the frame rate to about 60 fps. The code of this function is relatively simple: calculate the amount of time remaining before we should start work on the next frame, convert that to milliseconds, sleep for that number of milliseconds (which may be 0), repeat until it's exactly the right time, then exit. Here's the code:
public virtual void LimitFrameRate(int fps)
{
long freq;
long frame;
freq = System.Diagnostics.Stopwatch.Frequency;
frame = System.Diagnostics.Stopwatch.GetTimestamp();
while ((frame - previousFrame) * fps < freq)
{
int sleepTime = (int)((previousFrame * fps + freq - frame * fps) * 1000 / (freq * fps));
System.Threading.Thread.Sleep(sleepTime);
frame = System.Diagnostics.Stopwatch.GetTimestamp();
}
previousFrame = frame;
}
Of course I have found that due to the imprecise nature of the sleep function on some systems, the frame rate comes out quite differently than expected. The precision of the sleep function is only about 15 milliseconds, so you can't wait less than that. The strange thing is that some systems achieve a perfect frame rate with this code and can achieve a range of frame rates perfectly. But other systems don't. I can remove the sleep function and then the other systems will achieve the frame rate, but then they hog the CPU.
I have read other articles about the sleep function:
Sleep function in c in windows. Does a function with better precision exist?
Sleep Function Error In C
What's a coder to do? I'm not asking for a guaranteed frame rate (or guaranteed sleep time, in other words), just a general behavior. I would like to be able to sleep (for example) 7 milliseconds to yield some CPU to the OS and have it generally return control in 7 milliseconds or less (so long as it gets some of its CPU time back), and if it takes more sometimes, that's OK. So my questions are as follows:
Why does sleep work perfectly and precisely in some Windows environments and not in others? (Is there some way to get the same behavior in all environments?)
How to I achieve a generally precise frame rate without hogging the CPU from C# code?
You can use timeBeginPeriod to increase the timer/sleep accuracy. Note that this globally affects the system and might increase the power consumption.
You can call timeBeginPeriod(1) at the beginning of your program. On the systems where you observed the higher timer accuracy another running program probably did that.
And I wouldn't bother calculating the sleep time and just use sleep(1) in a loop.
But even with only 16ms precision you can write your code so that the error averages out over time. That's what I'd do. Isn't hard to code and should work with few adaptions to your current code.
Or you can switch to code that makes the movement proportional to the elapsed time. But even in this case you should implement a frame-rate limiter so you don't get uselessly high framerates and unnecessarily consume power.
Edit: Based on ideas and comments in this answer, the accepted answer was formulated.
Almost all game engines handle updates by passing the time since last frame and having movement etc... behave proportionally to time, any other implementation than this is faulty.
Although CodeInChaos suggestion is answers your question, and might work partially in some scenarios it's just a plain bad practice.
Limiting the framerate to your desired 60fps will work only when a computer is running faster. However the second that a background task eats up some processor power (for example the virusscanner starts) and your game drops below 60fps everything will go much slower. Even though your game could be perfectly playable on 35fps this will make it impossible to play the game because everything goes half as fast.
Things like sleep are not going to help because they halt your process in favor of another process, that process must first be halted, sleep(1ms) just means that after 1ms your process is returned to the queue waiting for permission to run, sleep(1ms) therefor can easily take 15ms depending on the other running processes and their priorities.
So my suggestions is that you as quickly as possible at some sort of "elapsedSeconds" variable that you use in all your update methods, the earlier you built it in, the less work it is, this will also ensure compatibility with MONO.
If you have 2 parts of your engine, say a physics and a render engine and you want to run these at different framerates, then just see how much time has passed since the last frame, and then decide to update the physics engine or not, as long as you incorporate the time since last update in your calculations you will be fine.
Also never draw more often than you're moving something. It's a waste to draw 2 times the exact same screen, so if the only way something can change on screen is by updating your physics engine, then keep render engine and physics engine updates in sync.
Based on ideas and comments on CodeInChaos' answer, this was the final code I arrived at. I originally edited that answer, but CodeInChaos suggested this be a separate answer.
public virtual void LimitFrameRate(int fps)
{
long freq;
long frame;
freq = System.Diagnostics.Stopwatch.Frequency;
frame = System.Diagnostics.Stopwatch.GetTimestamp();
while ((frame - fpsStartTime) * fps < freq * fpsFrameCount)
{
int sleepTime = (int)((fpsStartTime * fps + freq * fpsFrameCount - frame * fps) * 1000 / (freq * fps));
if (sleepTime > 0) System.Threading.Thread.Sleep(sleepTime);
frame = System.Diagnostics.Stopwatch.GetTimestamp();
}
if (++fpsFrameCount > fps)
{
fpsFrameCount = 0;
fpsStartTime = frame;
}
}

Categories