Gigi Labs

Please follow Gigi Labs for the latest articles. Programmer's Ranch no longer has its domain, so please update your bookmarks and links to programmersranch.blogspot.com.

Wednesday, May 29, 2013

Unity3D: Space Invaders (Part 2 - Linear Interpolation)

Hi all! :)

In the previous article ("Unity3D: Space Invaders (Part 1 - Navigation and Materials)"), we began working on a Space Invaders clone called Ranch Invaders. Today we're going to continue where we left off, and we're going to animate the alien moving around. If you didn't follow the previous article, don't worry! :) All you need to do is start a new Unity project and drag a cube onto the scene.

If you've read "Unity3D: Moving an Object with Keyboard Input", you might remember that in order to make an object behave in some way, we need to attach a script to it. So, right-click in the Assets panel, and in the context menu, select Create -> C# Script. You can call it Alien (or whatever you like). Then, drag the script onto the Alien object (cube). You'll know you've done it right when you select the Alien object and the Alien script appears in the Inspector:


Double-click the Alien script to open it in MonoDevelop. You are presented with a default (empty) behaviour script:


You will notice that these scripts all inherit from a MonoBehaviour class and have at least Start() and Update() methods. The Start() method allows us to set certain variables when the object is initialised, while the Update() method is called continuously while the game is running. A game is interactive because it shows (renders) a certain number of images (frames) per second. The Update() method is called every frame. So that is where you put most of your logic. Note: there are other, similar methods if you need more control, but we don't need to get into those right now.

In "Unity3D: Moving an Object with Keyboard Input", we saw that we could set an object's position by assigning a new Vector3 to its transform.position:

        this.transform.position = new Vector3(5, 5, 5);

However, what we'd like to do is have the Alien move gradually from one point to another. You can think of it like this:


So we want the Alien's x-position to start at -5, and move gradually to the right until it reaches x=5. With each frame, x is set to a different intermediate value t.

First, we need a variable to store the time when the animation began. Add this variable in the Alien class:

private float startTime;

The float data type is something we haven't covered in the C# articles so far, but it's simply a number that may have a decimal value (e.g. 5.48). When assigning float values, we need to add an 'f' suffix to the value (e.g. 5.48f).

Next, we set this startTime to the current time in the Start() method:

    void Start ()
    {
        this.startTime = Time.time;
    }

Unlike float, which is a standard data type, Unity uses its own classes to represent time. Instead of the DateTime type we're used to from C#, Unity has its own Time class. The equivalent of DateTime.Now is Time.time, and it gives us a float representing the current time.

We can now change the Update() method as follows to carry out the animation:

    void Update ()
    {
        float t = Time.time - startTime;
        float x = Mathf.Lerp(-5.0f, 5.0f, t);
        this.transform.position = new Vector3(x, 5, 5);
    }

Remember that Update() is called every frame. Thus, based on the current time, we calculate how far along the animation we have come, and store it in t. We can then use Lerp() to set x to the correct intermediate value between -5.0f and 5.0f.

Before I mess up your mind with an explanation on Lerp, press F8 to make sure the code compiles, and then press Play from within Unity. Watch the Alien (cube) move gradually from left to right. This will help you understand better what is happening.

Lerp is short for linear interpolation, which might sound like some scary monster. But to understand it, refer again to this diagram:


Let's say t starts at 0, and goes up to 100 as time goes by. It's not the same as the value of x; think of it as a percentage.

Now, let's say that at a particular point in time, t is 0.6 (60%). In order to find the corresponding value of x, we need the value that marks 60% of the way between -5 and 5. That's

t starts at zAs time goes by, t increases. To keep it simple, let's say it increases in whole numbers. So from -5, it becomes -4, -3, and so on until it finally reaches 5. The x value can be calculated from t as follows:


In Unity, you don't really need to worry about the mathematics. Just keep track of the time, and store the elapsed time in a variable (such as t). To use the Lerp() method, just pass the minimum, maximum, and t values as parameters, in that order. The result is the intermediate, or interpolated value you want.

When you press Play in Unity, you'll notice that the Alien (cube) moves across rather quickly. You can regulate this by multiplying a speed value:

        float t = (Time.time - startTime) * 0.4f;

The value (in this case 0.4f) is up to you to choose. Values less than 1 will make the cube move more slowly, and values greater than 1 will make it move faster.

Wonderful! :) In this article, we learned how to use linear interpolation (lerp) to animate the movement of a cube. As a matter of fact, interpolation is used in all sorts of animation, from video game credits scrolling vertically, to an object gradually changing colour when it is hit by a bullet. A lot of this functionality can be used easily using libraries such as iTween, but learning how it actually works gives you much more control.

Come back for the next article in the Ranch Invaders series, in which we will learn about prefabs and use them to shoot bullets! In the meantime, as an exercise, implement the code that allows the alien to move from left to right, down, right to left, down, etc (see this video to get an idea). :)

No comments:

Post a Comment