Essence Showcase - Rewinding Time
Hi everyone! This is part three in a short series of posts I'm doing where I cover each of our time manipulation mechanics in Worldline. If you haven't seen the first two, they're right here:
Next up on the list is rewind essence. This is by far one of Worldline's more interesting mechanics, but it was also quite difficult to implement. When designing rewind, I knew I would need to store a lot of data about a lot of different things, and so I approached it from two different perspectives, which I dubbed a "top down" perspective, and a "bottom up" perspective.
With the top down perspective, the idea is that we would have one single entity which would be responsible for keeping track of all the different information that is needed to be stored each frame. Actually this is how Braid handled their rewind mechanic, which I learned from this talk.
For Worldline, it was a bit more unique in the sense that only some things will be rewinding at a time. In most cases, everything will rewind except for the player, but there are circumstances where you just have one or two objects rewinding, and nothing else.
In the above example, I'm showing off the unused "rewind aura." Things that enter the aura would start to go backwards in time. Due to the fact that we needed very specific control over the timeline of each object, we ended up going with the bottom up approach. This means that everything in the game world keeps track of its own past states.
The first way we did this was actually pretty cool, but could only be described as overkill, which made it way too expensive. Each object in the game would actually go through every single field and property associated with it, and record its values each frame. This worked well, but it had a few problems. If an object was updated, as in, what fields it has changed, we had to account for that dynamically, which would cause a performance drop during these situations, due to the sheer volume of data. This also meant that there was no accounting for things that didn't need to be recorded. For example, I would tell the game not to record constant data, like the size of the player's hitbox, but when you consider the massive volume of data associated with each object, it actually became more overwhelming to define what shouldn't be recorded, than what should be. So that's how I came up with the current solution. Using a hierarchical approach, for each template object, I define what should be recorded. For example, on something like a bullet, I say, "Record your position, rotation, and sprite," because that's all we really need. Then for all bullets, this type of recording will occur. Thanks to the way I structured the system, if there was a type of bullet, for example, one that got smaller as it traveled, all we need to do is also specify that for this type of bullet, its scale should be tracked as well. After getting over the hurdle of storing data, all that was left to do was assign the data backwards each frame to simulate a rewinding effect.
When it came to balancing the mechanic from a gameplay perspective, it wasn't too difficult. We were worried players wouldn't be able to find many uses for the mechanic outside of puzzles, but this actually didn't tend to be the case. Rewind serves as a nice fallback when the player doesn't have some other type of essence that can be used for "disengagement." For example, when players get attacked by a group of enemies, they can use rewind and the enemies will stop pursuing the player. On top of this, another side-effect of rewind was that players can "loot" enemies multiple times. Since rewind doesn't effect the player, we found players would kill an enemy, collect its essence, use rewind to bring the enemy back to life, and then kill it again to get more essence. Since the player doesn't rewind their own time, their essence reserves stay the same.
Leave a comment
Log in with itch.io to leave a comment.