Mar 302012
 

Manipulating time in Unity3d is quite a bit of fun.  When I first created the project you can see below, I wanted to see how difficult it would be it institute something similar to what we see in Braid – basically a button that can turn back time.  For my purposes, I wanted to start out fairly small and be able to attach a script to any game object in the scene that would be affected by this time-shift.  I’ll paste the code here, but be sure to check it out in action at the link below:

Time-manipulation Demo

This was also my first real experience with the new Shiruken particle system, and I have to say I’m rather impressed.  It’s clearly very different, but you can’t argue with the results.  Anyway, I decided to use a simple array to hold the data for time reversal.  The main control key, “R”, simply triggers a boolean variable when held down.  This is located in the regular character movement controls, like this:

//Reversal key
 if (Input.GetKey("r")) {
 isRevving = true;
 } else {
 isRevving = false;
 }

By doing that, I don’t have every instance of the script listening for the R key.  The actual time script looks like this:

var thisHistory = new Array();
function Update () {
 var revControl : boolean = GameObject.FindGameObjectWithTag("Player").GetComponent(charMover).isRevving;

 if (revControl == false) {
 thisHistory.Push(transform.position);
 if (thisHistory.length > 1000) {
 thisHistory.RemoveAt(0);
 }
 }

 if (revControl == true && thisHistory.length > 0) {
 RevOne();
 }
}
function RevOne() {
 var onNum = thisHistory.length;
 transform.position = thisHistory[(onNum - 1)];
 thisHistory.Pop();
}

As you can see, it simply hold the last 1000 frames of position data in memory and begins to delete the old data as time goes on.  If the reverse key is pressed, it stops recording and starts moving backward, deleting each frame as it goes along.  I was quite happy with the results for character movement, and this same thing could be applied to many variables aside from position if the script was extended.  Some ideas that are fairly obvious would be character health, rotation, or any other piece of numerical data that would be important to your game environment.

I didn’t apply the script to the in-game “bullets”, because the script doesn’t support the deletion of the bullet once it rewinds to the point of its origin.  however, something tag-based could be quite easily added into the script if that was a desired feature.

The other fun thing I wanted to do with time in this demo is something similar to bullet-time.  When a target is hit, I thought it would be fun to slow the overall game time down and gradually increase it back to regular speed.  Through the Time.timescale function, unity made this little diddy a snap.  It works something like this:

//time fixer (currently located in the character movement script)
 if (Time.timeScale > 0 && Time.timeScale < 1) {
 Time.timeScale += 0.005;
 }

Make note of the specification that the timescale needs to be above 0. This was added so that a game could still be paused without gradually unpausing itself.  With this if condition added into the Update section of a running script, all we have to do is trigger a drop in timescale based on a condition.  In this case, I used the collision of a bulled with one of the white target blocks:

//This snippet is attached to the white target blocks
var exp : Transform;
function OnCollisionEnter(other : Collision) {
 if (other.transform.tag == "bullet") {
 var splode : Transform = Instantiate(exp, transform.position, Quaternion.identity);
 splode.particleSystem.Play();
 GameObject.FindGameObjectWithTag("Player").SendMessage("Timing");
 Destroy(gameObject);
 }
}
------
//This function was added to the character movement script
function Timing() {
 Time.timeScale = 0.1;
}

With these few pieces of code added to my dull demo platformer, I was able to quickly pull off some quality features with very little programming.  Hopefully readers will find this demo useful as well, and if you have any questions, please feel free to drop them in the comments below :)

 Leave a Reply

Connect with Facebook