Sponsored By

Braid Style Rewind System 04

Fourth post for the rewind system

Derek Dittmer, Blogger

March 21, 2013

6 Min Read
Game Developer logo in a gray background | Game Developer

Whew, it's been a long time since my last post, but that doesn't mean I have been slacking off. I have been adding new things, struggling with problems, and doing a lot of organizing. I am going to go over some of the high-level things that I did, because if I were to write everything down that I did, it would be quite lengthy and no one would read it.

One of the things that I did that I thought was pretty cool, was shrink down the size of my saved positions, by stuffing the positions (floats) into shorts. Right now, my map is pretty small, and since my positions never get too high or low, I am able to stuff them into the short by multiplying by 1000, and then dividing by 1000, when taking them out. This allows for precision to the 0.001, which is more than enough for positions. If I change the 1000 to 100, I can make my maps 10 times the size and will still have 0.01 precision, which isn't too bad. I'm sure it could be better: maybe check the size before shrinking it, and then multiply by a certain number to get the most precision possible. Oooo, I'm going to try that now. Alright, so now I'm saving 6 less bytes for my XPos, YPos, and Velocity (see below) floats combined. Might not seem like much, but when these things are getting saved 10 times a second, those bytes add up real quick.

Another cool thing that I got working was having the variable rewind speeds. Like in Braid, if you are rewinding and use the up/down arrow keys, you can speed up your rewind. What I did not know was that if you continue holding shift, you can actually rewind your rewind (crazy) to get to the point where you started your rewind. That threw a wrench in my code, and made everything quite a mess while I was trying to get it to work correctly, but now it's a bit cleaner and works pretty smooth. Of course, I had to modify my animation script to allow for that also.

Alright, one of the things that took up a lot of my time was trying to save off the velocity, so when you stop rewinding you keep on going as if you had just jumped there. This caused me so many problems. I spent a week and it was still not right. Then I changed how I was saving my time stamps from floats (delta times) to ints (frames), and that worked much better. It still isn't perfect, but it is much better than what I was getting with the floats. Me and floats aren't on good terms at the moment, for what they did to me that long week.

With that velocity problem came a whole ton of other problems. I was able to calculate my velocity by applying some gravity to it depending on the time stamp (how many frames), but that only worked for my player, because I was handling its gravity myself. My enemy had a rigidbody and I was unable to figure out the gravity applied to it at the time, because it did its gravity logic in the FixedUpdate(). This led me to make the player's physics its own class, and have the player and enemy inherit from that. With my enemy no longer having a rigidbody, most of its logic needed to change as well. Fun. At least the velocity problem is almost fixed.

I got the enemy rewinding also. It works just about the same, but it only records every couple of frames while it is in the air – while on the ground, it only saves when it hits a wall and changes direction. This makes the rewind still look good, and also saves some memory. I decided to give the enemy the Rewindable script, because I wanted him to be able to fall off a ledge, and have that rewind also, just like in Braid.

The moving platform also rewinds pretty easy. Because it is a looping animation, I don't even need to save its positions: just set the animation speed to -1 when rewinding. So much for "more complex movement" as I called it before – that was 100 times easier than the enemy!

I made a one-shot animation class, that is close to how my animation class works, but doesn't loop. Basically, you enable the script, and it runs through the animation and stops on the last frame. I slapped that script on my treasure chest, and now it opens and stays open without a problem.

All of this added stuff was to get my rewind system rewinding objects correctly. I found out that it is still not rewinding correctly just yet. Even though I am saving the frames (ints) instead of the elapsed time (floats), I still am using Time.deltaTime in my rewind lerp script. If the frame rate drops, there will be some strangeness to my rewind, as I was able to see with my enemy. I'm sure my game isn't going to be dropping anyone's frame rate, but something external to my game could be running that can drop the frame rate. Either way, I would like to do it right. So, now I need to save another variable for how long it has been since the last save position. That way, even if the Time.deltaTime changes, the lerp will still work correctly.

Other than that small issue, my rewind system is working quite well, so I have started putting some cool stuff in. The first is having players and enemies die, and being able to rewind that death. When the player dies, the game will stop also (kind of like in Braid, but without the cool animations). This is fully working. The other cool thing I have just started messing with is rewinding sounds. I was sure Unity had some way of doing this, and when I looked online, people said that setting the sounds pitch to a negative number would make it play in reverse. So, I added some sound effects to the game, and then spent a couple of hours messing with pitch and just about everything else trying to get it to play backwards. Then, because I had tried everything else, I converted my sounds to .wav and everything worked fine. I guess compression does not like being played in reverse; wish someone online would have mentioned that.

Sorry I wasn't able to dig deep into everything that I did. Don't worry though, when I am finished with this project, I will be posting the project on my site so you can download it and see exactly how I did everything. I've been using a lot of comments, not only so I know what the heck I am doing, but so someone else can hopefully understand what I am doing also.

Here's a short video of what I got so far. Things show off are in this order: | enemies and moving platform rewinding | velocities rewinding | player dying | enemy dying | rewind speeds | one shot animations | start of my reversed sounds |.

Thanks a lot; see you next time!

http://www.youtube.com/watch?feature=player_embedded&v=znDoM2gaG1o

(To see/play/download the project of final product, go to my website: http://derek.dittmer.com/please-be-kind.html

Read more about:

Blogs
Daily news, dev blogs, and stories from Game Developer straight to your inbox

You May Also Like