Managing time in a turn-based game

Hey folks…I have a game that I’m working on that is turn-based. On each turn the player will plan a series of moves. I allow the moves to play out and timestamp certain “events.” So for example, let’s say I plan to march a soldier to a certain position and he takes damage along the way. I would mark the beginning of his movement at [start time = 0] and then let’s say he dies after 16 seconds of movement, I would mark his death at [death time = 16]. If 7 seconds along his route, he killed an enemy tank, then I would tag that tank’s death at [death time = 7]. I’m using round numbers here…but these would all be floating point values.

I record all these events with their timestamps on the server. When the opponent logs into the game, the event data is download, and then the event is “reenacted” on the opponent’s machine. So I’m not recording the player’s turn as a “video,” but I’m recording the events in such a way that I can replay them when the opponent logs in to the game. After the opponent views the previous player’s turn, then they will go into the planning phase of their own turn. They would record a series of moves, and the game would record the event timestamps and submit them to the server. This is the basic mechanic I’m using to allow players to view each others moves. It’s cheaper than recording actual video and beaming it down to the mobile device on which the game is played.

Now, knowing that gamers (and game developers) are an impatient lot, I wanted to add a “fast forward” feature to the game that would allow you to advance the playback speed of all these events. I thought maybe a 2x speed or a 3x speed would be appropriate. But I’m noticing the higher I advance the time scale (using TimeManager.TimeScale) the farther out of sync my playback becomes.

So in the previous scenario…my tank might die well before the soldier arrives at a position wherein he can attack the tank.

I’m not sure why this is the case. My timestamps are recorded using a ticker component that updates the “event clock” in the Update() method. At the beginning of the turn, I set the clock to 0.0, then on each call to Update() I advance the ticker by Time.deltaTime. I realized this might be a bad idea since Update() is framerate dependent, so I tried moving the event clock logic to FixedUpdate(), still using Time.deltaTime, but to no avail. It still seemed that the higher I set the time scale…the further apart things drifted.

The other major component to this is that I’m using Unity’s Navigation Mesh and pathfinding systems. When I boost the time scale…the characters DO move faster…but they also seem to have a harder time navigating. They seem to be more jerky and they seem to snag on corners a little moreso than they do at time scale = 1.0. It could just be my imagination…but it seems like maybe this “degradation” in path finding could be delaying the soldier’s arrival at the appropriate locations.

So a couple of questions.

  1. Should I be running my event clock from Update() or from FixedUpdate()? Or maybe there’s a place that is more appropriate than either of these 2 methods.

  2. Should I be using Time.deltaTime or is there a better value to use to indicate the timestamps of the various events that I am keeping track of?

  3. Are there any settings in Unity’s navigation system that I should be checking or setting to correlate with a change in the time scale?

Any help will be greatly appreciated. I thought this mechanism would work fairly well because it’s something like “key frame animation.” I don’t need to know everything that happened on every frame…I just need to capture a few key events. I should probably also note that playback doesn’t drift at all at a time scale of 1.0. So the game’s mechanics are working quite well. The only problem is that nobody will want to wait to watch the entire playback at normal speed…they will all want to advance the speed or skip the playback altogether to play their turn.

Thanks for your brain cycles!

Doing a bit more digging, I’ve found this page from the reference manual which…in truth…just confuses me.

http://docs.unity3d.com/Documentation/ScriptReference/Time-timeScale.html

This article suggests that if you lower the time scale that you proportionally lower the Time.fixedDeltaTime value. But then it gives an example that does NOT lower fixedDeltaTime when the time scale is lowered, but it DOES RAISE the fixedDeltaTime when the time scale is returned to its normal value of 1.0.

Couple that article with this one:

http://docs.unity3d.com/Documentation/ScriptReference/Time-fixedDeltaTime.html

Which outright says not to use Time.fixedDeltaTime because the appropriate value would be stored in Time.deltaTime.

So … yeah I’m a bit confused. I think maybe what I need to do is experiment with a few of these combinations…using Update(), using FixedUpdate, using Time.deltaTime, using Time.fixedDeltaTime, syncing Time.fixedDeltaTime as I modify Time.timeScale, and NOT syncing Time.fixedDeltaTime as I modify Time.timeScale.

I’d suspect somewhere in all of permutations of those variables to the approach…I will find my answer. :-/

I would do all this in normal time, no time advancing. Just keep a single “currentTime” variable. Each update advance it by Time.deltaTime * speed. Then do the events that occurred in that delta time. You treat it much like a database. Just get all events that occurred within the deltaTime and start their animations. So if 5 people died at 7, then all simply die at the same delta time tick.

It will be closer, but not exact. It will however not have a choice to work right.

@bigmisterb…thanks for the suggestion. That might work. If I understand you correctly, you’re saying that I just keep time. Create a component of some kind that is effectively a time manager of my own creation. Then just track against that. Instead of using Time.timeScale to change the flow of time, I just edit some value in my custom made time manager component.

If I understand you correctly, the only issue that I can see with this approach is that the physics would be off as well as the AI navigation speeds. So I’d have to compensate for that somehow.

Let’s say my soldier moves within attack range of the tank and lobs a grenade. If I’m keeping my own time, then I’d have to adjust his movement speed an animation speed to get him to the attack position at the appropriate time…then when he lobs the grenade…I’d have to adjust the grenade’s position along the arc to compensate for the increased speed in the passage of time (as opposed to just using PhysX which is what happens now). This could prove tricky.

Or maybe I’m not fully understanding your suggestion. Nonetheless…thanks for the response. It’s all good to brain food for ways to approach the solution.

hmmm… usually turn based games don’t have physics. I would do all of this in animations. Grenade lobbing and such should be done mathematically, so yeah, much easier that way.