Tuesday, November 22, 2016

software engineering - Time critical events based on framerate


Problem Description


Basically, I've made a "programming game" in which I've made my own scripting language. It is a completely standard Lunar Lander game, though instead of directly controlling the lander using keyboard input, it instead fires a sequence of commands you have provided through the scripting language I made. This all works, and I've hit a critical problem.


So essentially, using the scripting language, you specify something like After 5 seconds, activate thrust for 10 seconds, and then after 2 seconds, rotate the lander for 4 seconds. The goal is then to chain together a sequence of commands which will get you to land the lander safely.


Of course, this comes with one problem. If you repeat the sequence of commands, each command will have to be fired at exactly the same spot in the level, that is, after x amount of seconds, but also with the lander being in the exact same spot. If you did not use timer-based movement, sure you could indicate that a command should activate after 5 seconds, but the lander moving at 60 FPS would have moved way further than a lander moving at 30 FPS.


Why of course, I thought I would simple just make the lander use timer-based movement so it is independent of FPS (I am using the very standard approach of taking the amount of time passed last frame, and multiplying it to a constant move speed). Then I would count seconds using the system clock. So the after x amount of seconds, the lander would be in the same spot in the level when the command activates.


Unfortunately, this approach do not work. Every time I run a sequence of commands, they will be activated with, sometimes very slight, variations, making it impossible to actually get a consistent and reliable path for the lander.



My Question


So my question is, am I tackling this problem a completely wrong way? What exactly do you do when it is absolutely critical that timed events defined by the user will activate at exactly the same time and spot in a level? I seem to be quite stuck with this question.



Answer



The general solution to this problem is to have an update function with a completely fixed timestep. Unity calls this FixedUpdate, in physics engines you can run the simulation several times before updating the world, etc. but it's all the same concept.


While this fixed update function will always be slightly out of sync with everything else in your world, if you select a small enough timestep (1/60 or 1/30 or so), this will be unnoticable. Another thing to remember is that you only need to use this update function for things that need to be absolutely deterministic, so it doesn't hog your cpu even if you need to run it several times before updating the world. And if it's not completely obvious, this function should have absolutely nothing to do with your system clock - this runs on a "simulated" clock that you keep track of, and that never actually steps over the real system clock, but is otherwise independent.


Having said all this, in your case there may be simpler solutions. You can pre-calculate the path for your unit and interpolate on that path. The idea behind this solution is that you think of your unit's movement as a continous function instead of a physical simulation.


Alternatively you can try to "snap" your ship to the correct position after every movement, so the arithmetic error doesn't add up. However this may cause visual glitches if your fps is low or not constant.


No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...