Gigi Labs

Please follow Gigi Labs for the latest articles.
Showing posts with label unity3d. Show all posts
Showing posts with label unity3d. Show all posts

Sunday, August 4, 2013

Unity3D: Changing game speed and pausing

Hi!

Today's article is a little break from the OOP tutorials. Instead, we revisit the Unity3D game development engine (at the time of writing, version 4.2 was recently released) and learn about controlling time. This allows us to easily pause the game, slow it down, or speed it up.

Create a new project and add a sphere to your scene via GameObject menu -> Create Other -> Sphere. Next, create a new C# script by right clicking in the Project panel, and selecting Create -> C# Script. Name it Ball, and drag it onto your Sphere in the Hierarchy panel. Double-click the script to open it in MonoDevelop.

We're going to make a very basic bouncing ball just to be able to see the effects of our change in speed. Start off with the following code for the Ball script:

public class Ball : MonoBehaviour
{
    private Vector3 velocity;
   
    // Use this for initialization
    void Start ()
    {
        this.velocity = new Vector3(1.0f, 1.0f, 0.0f);
    }
   
    // Update is called once per frame
    void Update ()
    {
        this.transform.position += this.velocity * Time.deltaTime;
       
        if (this.transform.position.x > 5.0f)
            velocity.x = -velocity.x;
        else if (this.transform.position.x < -5.0f)
            velocity.x = -velocity.x;
        else if (this.transform.position.y > 6.0f)
            velocity.y = -velocity.y;
        else if (this.transform.position.y < -5.0f)
            velocity.y = -velocity.y;
    }
}

This will make the ball bounce when it reaches the sides of the screen. This may vary depending on your monitor so use whichever values work best.

We've used Time.deltaTime before. Games look interactive because they generate a certain number of images (frames) per second, usually something between 30 and 60. Time.deltaTime is the time between one frame and the next; multiplying this by the velocity makes the ball move pretty uniformly.

Another important property of the Time class is Time.timeScale. This is a measure of how quickly scripts and animations run, and is set to 1.0f by default. We can change this to make the game run at different speeds. To try it out, add the following code to the Ball script's Update() method:

        if (Input.GetKeyDown(KeyCode.P))
            Time.timeScale = 0.0f;
        else if (Input.GetKeyDown(KeyCode.N))
            Time.timeScale = 1.0f;
        else if (Input.GetKeyDown(KeyCode.F))
            Time.timeScale = 2.0f;
        else if (Input.GetKeyDown(KeyCode.S))
            Time.timeScale = 0.5f;

What we're doing here is:

  • If the player presses 'P' (pause), we set the time scale to zero, effectively stopping any movement in the game.
  • If the player presses 'N' (normal speed), we set the time scale to the default of 1.0f.
  • If the player presses 'F' (fast), we set the time scale to double the normal speed.
  • If the player presses 'S' (slow), we set the time scale to half the normal speed.
This simple property allows you to not only pause the game, but also to play the game at different speeds. Several games including Starcraft and Warcraft 2 have settings that allow you to tweak the game speed in order to make it more challenging or less frenetic.


This article showed how a single line of code in Unity3D is enough to change the speed of a game or pause it. Although this was a very easy tutorial, I hope you will also find it very useful in any games you make!

Monday, June 10, 2013

Unity3D: Arkanoid

Hullo! :)

One of the subscribers of the Programmer's Ranch Facebook page requested an article on creating Arkanoid with Unity. So... here you go. :)

Create a new Unity project and save your scene. Set up your scene using scaled up cubes for the scene boundaries (except for the bottom), and put in another cube for the paddle and a sphere for the ball:



Make sure that all objects have the same z-coordinate for position, and that they are visible to the camera.

The game mechanics for Arkanoid are very similar to those of Pong, so we will be following very similar steps. As a matter of fact, we can use the same Ball script we used in Pong. Create a new C# script, attach it to the sphere, and after opening it in MonoDevelop, paste the code we used in Pong:

public class Ball : MonoBehaviour
{
    private Vector3 direction;
    private float speed;
 
    // Use this for initialization
    void Start ()
    {
        this.direction = new Vector3(1.0f, 1.0f).normalized;
        this.speed = 0.1f;
    }
 
    // Update is called once per frame
    void Update ()
    {
        this.transform.position += direction * speed;
    }
}

Attach a Rigidbody to the sphere via Component menu -> Physics -> Rigidbody, which will allow the ball to bounce off surfaces. Remember to turn off "Use Gravity".

Next, select the Main Camera and change Projection from Perspective to Orthographic to remove perspective and end up with a more suitable 2D view. Change the Size property until the scene fits the camera's view properly:


Create a new C# script and name it Paddle. Attach it to the cube to be used as a paddle. Paste the following code to enable left and right movement via arrow keys:

public class Paddle : MonoBehaviour
{
    private float speed = 0.1f;
 
    // Use this for initialization
    void Start ()
    {
 
    }
 
    // Update is called once per frame
    void Update ()
    {
        if (Input.GetKey(KeyCode.LeftArrow))
            this.transform.position += Vector3.left * speed;
        if (Input.GetKey(KeyCode.RightArrow))
            this.transform.position += Vector3.right * speed;
    }
}

This is quite similar to what we did in the Pong article, except we're moving left and right instead of up and down. We are using the static vectors Vector3.left and Vector3.right, which are really just shortcuts for unit vectors along the particular directional axis (in this case (-1, 0, 0) and (1, 0, 0), respectively). We similarly used Vector3.up ((0, 1, 0)) and Vector3.down ((0, -1, 0)) in Pong.

We can now take care of the bricks. Since we will have a lot of them, it's best to create a prefab. From the GameObject menu, select Create Other -> Cube, and drag it into the Project panel in Unity to make a prefab out of it. Rename it to Brick. Create a new tag called Brick and tag your brick as such. Remember to click the Apply button in the inspector to make the tag apply to all instances of the prefab.

Proceed to duplicate (Ctrl+D) the brick so that there are many bricks in the top part of the screen:


To make the ball destroy bricks as it hits them, add the following code at the end of the OnCollisionEnter() method in the Ball script:

        if (collision.gameObject.tag == "Brick")
            GameObject.Destroy(collision.gameObject);

You can now play happily as the ball destroys bricks but not the paddle or the edges:


That wraps up the basic game mechanics for Arkanoid. As an exercise, add victory (for when you clear all the bricks) and defeat (for when the ball escapes below the paddle) conditions.

In these recent tutorials about classic arcade games, I have purposely focused exclusively on game mechanics (e.g. bouncing, shooting, etc). This was intentional. When making a game, you should first concentrate on making solid game mechanics that work perfectly. Then, you can focus on building the rest of the game (levels, menus, screens between levels, etc) and polishing (colours, animation, etc).

In fact, this Arkanoid game looks like shit. The first thing I'd do after finishing the game mechanics is give it a touch of colour (via materials, and put in a point light to brighten the colours):


...and here's what it looks like in-game:


This colouring took a couple of minutes to do, and I think you'll agree with me when I say that the game looks much more alive. Making the game vibrant and fun is just as important as programming the game mechanics, so don't overlook it!

Thanks for reading, and I hope you found this useful! :)

Friday, June 7, 2013

Unity3D: Pong

Hi folks! :)

Today we're going to see how to create a game like Pong, one of the earliest classic arcade video games, using Unity3D. The approach for movement is very similar to the one we used in "C# Threading: Bouncing Ball", although we don't have to worry about threads in this case.

After creating a new project, use the GameObject -> Create Other menu to set up the scene using four cubes and a sphere. After scaling the cubes to be elongated, put one on each side: at the left and right as paddles, and at the top and bottom as walls that the ball can then bounce on:


One thing you'll notice is that the paddles don't look like straight lines - they are seen as if from the side. That's because we're using a perspective camera. For a game like Pong, where we don't care about perspective, an orthographic camera is probably better.

Select the Main Camera from the Hierarchy panel, and change the Projection property from Perspective to Orthographic. Change the Size property until the game objects fit the camera's view comfortably (check this by pressing Play in Unity, not from the camera preview, since the resolution is different):


Now, let's make the ball move. Right click in the Project panel and select Create -> C# Script. Name it Ball and drag it onto the Sphere. Double-click the script to open it in MonoDevelop.

Just like in "C# Threading: Bouncing Ball", we now give the ball a direction and a speed with which to move (Physics people will know they are together called velocity):

public class Ball : MonoBehaviour
{
    private Vector3 direction;
    private float speed;
 
    // Use this for initialization
    void Start ()
    {
        this.direction = new Vector3(1.0f, 1.0f).normalized;
        this.speed = 0.1f;
    }
 
    // Update is called once per frame
    void Update ()
    {
        this.transform.position += direction * speed;
    }
}

The normalized part is something we do for convenience. A normalised vector has a magnitude of 1, making it easy to work consistently with it. We then modify the speed using the speed variable.

In order to implement the bounce effect, we have the ball detect collisions, and change trajectory when a collision occurs:

    void OnCollisionEnter(Collision collision)
    {
        Vector3 normal = collision.contacts[0].normal;
        direction = Vector3.Reflect(direction, normal);
    }

Take a look at this diagram to understand what's happening here:


In order to make the ball bounce, we need to find where it hits a wall or paddle, and change its direction. We reflect the direction in the surface normal, which is at 90 degrees to the surface itself. In Unity, we get that surface normal from the point of contact with the surface, which is available from collision.contacts.

Although it is good to know the vector mathematics behind vector reflection, in Unity3D this is as easy as using Vector3.Reflect() and passing in the incident direction and the surface normal.

In order for this to work. You will need to add a rigidbody to the Sphere, via Component menu -> Physics -> Rigidbody.

Now, just add another script for the paddle movement, and attach it to the paddles:

public class Paddle : MonoBehaviour
{
    private float speed = 0.1f;
 
    // Use this for initialization
    void Start ()
    {
 
    }
 
    // Update is called once per frame
    void Update ()
    {
        if (Input.GetKey(KeyCode.UpArrow))
            this.transform.position += Vector3.up * speed;
        if (Input.GetKey(KeyCode.DownArrow))
            this.transform.position += Vector3.down * speed;
    }
}

Enjoy the game!


In this article, we created a simple Pong game and learned about orthographic vs perspective cameras as well as vector reflection (used to bounce an object off a wall).

This simple game mechanic can be used for various classic games including Pong and Arkanoid.

The only thing we didn't do is handle when the ball leaves the area, in which case the player should lose the game. I'll leave that as an exercise since it's quite trivial (you can do something like how we handle bullets in "Unity3D: Space Invaders (Part 4 - Collisions)", and when the ball leaves the area, you change to a different scene showing a loser's screen - see "Unity3D: Scenes and Building").

In the next article, we will revisit the bouncing ball theme and make an Arkanoid clone. So check back! :)

Tuesday, June 4, 2013

Unity3D: Scenes and Building

Hi people! :)

Today we're going to learn about scenes in Unity. Scenes allow us to have different levels, both for gameplay as well as to incorporate things like the game menu, credits screen, etc.
  • Create a new project in Unity, and press Ctrl+S to save your first scene. Call it "Level1".
  • Bring a cube into the scene via GameObject menu -> Create Other -> Cube.
  • Then, right click in the Assets panel and select Create -> C# Script. Call it "NextLevel".
  • Drag the "NextLevel" script onto the cube.
  • Double-click the "NextLevel script to open it in MonoDevelop.
In the Update() method, put this:

        if (Input.GetMouseButtonDown(0))
        {
            int levelCount = Application.levelCount;
            int currentLevel = Application.loadedLevel;
            
            if (currentLevel < levelCount - 1)
                Application.LoadLevel(currentLevel + 1);
        }

This will allow you to move to the next level (if there is one) when the user clicks the left mouse button. I'll explain this in a minute.

First, let's create another two scenes (levels). You can do this either via the File menu -> New Scene, or else by selecting a scene in your Assets panel, and pressing Ctrl+D to duplicate it. When you double-click another scene in the Assets panel, Unity will open that scene instead of your old one, so make sure you always save before changing scene.

Create another two scenes using whichever method you prefer. Put a sphere in level 2, and a cylinder in level 3. Drag the "NextLevel" script onto each of these objects. In each scene, adjust the position of the objects so that they are visible to the camera.

Once you are ready, it's time to set up the order of the scenes in the game. Go to File -> Build Settings...:


From the Assets panel, drag the scenes into the "Scenes in Build" area of the Build Settings window:


The scenes are automatically ordered, as you can see from the corresponding number on the right. This means that Level1 is the first scene to be loaded, and the next one is Level2. You can reorder the scenes by dragging them up or down, and you can remove them by selecting them and pressing Delete.

Now, you can test this by opening Level1 in Unity and pressing Play. Level1 (the one with the cube) is loaded first. By clicking the left mouse button, you can transition to the two other scenes.

Back to the code above, Application.levelCount gives you the total number of scenes in your game, in this case 3 (note that they must be listed in the Scenes in Build for them to be considered). Application.loadedLevel gives you the index of the currently loaded level (the ones on the right hand side of Scenes in Build, starting from zero). Application.LoadLevel allows you to transition to any scene you want, by specifying its index.

For the record, it is also very easy to reload the current scene in cases where the player wants to restart the current level.

Finally, the Build Settings screen is also the place to go if you want to distribute your game. From here, you can create executable versions of the game. There are many supported platforms, and recently Unity is also allowing developers to build on iOS and Android for free - something that until recently would have cost several hundred dollars.

In summary, scenes are a great way to split up your game into several different levels that don't depend on each other. You can use them for different game levels, a main menu, credits/help screens, etc. The Application class provides methods and properties allowing you to work with scenes.

Thanks for reading, and stay tuned for more! :)

Saturday, June 1, 2013

Unity3D: Space Invaders (Part 5 - Behaviour)

Hi all! :)

In yesterday's article - Unity3D: Space Invaders (Part 4 - Collisions) - we learned how to handle collisions in Unity. At the end of the article, we listed several items that are still missing from Ranch Invaders.

Today's article deals with some of those issues, mainly relating to Player and Alien behaviour.

Player Movement

In Space Invaders, the Player's ship moves only left and right. If you've read "Unity3D: Moving an Object with Keyboard Input", you'll know that this is really easy to do. Open the Player script with MonoDevelop. You should currently have the code for shooting:

    void Update ()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            Instantiate(bullet, this.transform.position, Quaternion.identity);
        }
    }

Change it as follows to allow the Player to move using the left and right arrows:

    void Update ()
    {
        Vector3 pos = this.transform.position;
       
        if (Input.GetKeyDown(KeyCode.Space))
            Instantiate(bullet, this.transform.position, Quaternion.identity);
        if (Input.GetKeyDown(KeyCode.LeftArrow))
            this.transform.position = new Vector3(pos.x - 0.1f, pos.y, pos.z);
        if (Input.GetKeyDown(KeyCode.RightArrow))
            this.transform.position = new Vector3(pos.x + 0.1f, pos.y, pos.z);
    }

Great, you can now move the Player's ship left and right. There's a problem, however. If you hold down an arrow key, the Player's ship does not continue moving. We can fix this by using Input.GetKey() instead. Also, we need to set constraints to prevent the Player's ship from leaving the screen:

    void Update ()
    {
        Vector3 pos = this.transform.position;
       
        if (Input.GetKey(KeyCode.Space))
            Instantiate(bullet, this.transform.position, Quaternion.identity);
        if (Input.GetKey(KeyCode.LeftArrow) && pos.x > -2.5f)
            this.transform.position = new Vector3(pos.x - 0.1f, pos.y, pos.z);
        if (Input.GetKey(KeyCode.RightArrow) && pos.x < 2.5f)
            this.transform.position = new Vector3(pos.x + 0.1f, pos.y, pos.z);
    }

Cooldown

As it is, the Player can fire as many bullets as it likes, with no gap between one and another. In order to implement a cooldown, we use an approach similar to this. When a bullet is fired, the time is recorded and no bullet may be fired before the cooldown period has passed. To do this, declare the following variables in the Player class:

    public float cooldown = 1.0f; // minimum time between bullets
    private float nextFire = 1.0f; // next time when a bullet can be fired

Then, adjust the firing code as follows:

        if (Input.GetKey(KeyCode.Space) && Time.time >= nextFire)
        {
            nextFire += cooldown;
            Instantiate(bullet, this.transform.position, Quaternion.identity);
        }

Then, try it out, and adjust cooldown as you like:


Then, rejoice.


Alien Movement

In Space Invaders, aliens move right, down, left, down, etc. Making this work properly takes a bit of work, so I'll just give you the code:

public class Alien : MonoBehaviour
{
    public float horDistance = 1.0f;
    public float verDistance = 0.5f;
    public float speed = 0.4f;
    private float startTime;
    private Vector3 startingPosition;
    private Vector3 target;
   
    // Use this for initialization
    void Start ()
    {
        this.startTime = Time.time;
        this.startingPosition = this.transform.position;
        this.target = this.startingPosition + new Vector3(this.horDistance, 0, 0);
    }
   
    // Update is called once per frame
    void Update ()
    {
        Vector3 currentPosition = this.transform.position;
        Vector3 newPosition = Vector3.MoveTowards(currentPosition, this.target, speed * Time.deltaTime);
        this.transform.position = newPosition;
       
        //print (this.target);
       
        if (newPosition == target)
        {
            if (newPosition.x == startingPosition.x)
            {
                if (((newPosition.y - startingPosition.y) / verDistance) % 2 == 0)
                    this.target = newPosition + new Vector3(this.horDistance, 0, 0);
                else
                    this.target = newPosition - new Vector3(0, this.verDistance, 0);
            }
            else
            {
                if (((newPosition.y - startingPosition.y) / verDistance) % 2 != 0)
                    this.target = newPosition - new Vector3(this.horDistance, 0, 0);
                else
                    this.target = newPosition - new Vector3(0, this.verDistance, 0);              
            }
        }
    }
}

Don't fret about what the code is doing... just use it. Tweak the public variables as you like.

More Aliens

Since we need a lot of aliens, it's a good idea to make the Alien object a prefab. To do this, drag it from the Hierarchy panel to the Assets panel. If you did it right, its listing in the Hierarchy panel should turn blue. This way, if you make any changes, you can apply them across all Aliens.

To make multiple Aliens, you can either press Ctrl+D (duplicate) to create additional objects, or else instantiate all the aliens in code using for loops. In my case, I just duplicated a handful of Aliens, just for testing:


Don't get too fussy about the Alien placement and all that. The reason we're still working with cubes and spheres is that you should first concentrate on making sure that your game mechanics work correctly. Only once that is done should you spend some time (a lot of time, actually) making it look good.

Aliens Shooting

Allowing Aliens to shoot the Player is no different from allowing the Player to shoot the Aliens. However, you now need a different bullet that moves downwards and that can destroy the player.

Once you attach a rigidbody to the Player (Component -> Physics -> Rigidbody, and remember to turn off "Use Gravity"), you will find some unexpected behaviour: at times, when the Player shoots a bullet, the Player itself is destroyed! That's because we don't yet have any code in the Bullet script that distinguishes between objects it can destroy. So far it worked correctly only because the Player didn't have a rigidbody, in which case the collision doesn't happen.

An easy way to solve this is to tag the object. Select the Player. At the top of the Inspector is a section where you can select a tag to assign to the object. For the Player, you can choose the predefined Player tag:


For the Aliens, you will need to add a new tag. From the drop-down list containing tags (shown above), select "Add Tag...".


In the resulting interface (shown above), expand the "Tags" node. Next to "Element 0", type "Alien". This creates the "Alien" tag, but does not assign it to the object.


To tag the Alien as such, select an Alien object, and select the newly available "Alien" tag from the drop-down list. Remember to click "Apply" to make this work for all Alien objects (since it's a prefab).

The Bullet script's collision code now becomes:

    void OnCollisionEnter(Collision collision)
    {
        if (collision.gameObject.tag == "Alien")
        {
            GameObject.Destroy(collision.gameObject);
            GameObject.Destroy(this.gameObject);
        }
    }

The Player's bullets should now destroy only Aliens.

For the aliens to shoot at the player, you will first need to create another bullet prefab (e.g. "AlienBullet") with the same script as the Bullet, except for two key differences. First, the bullet needs to go downwards instead of upwards. So:

    void Start ()
    {
        this.target = this.transform.position - new Vector3(0, 20, 0);
    }

Secondly, it needs to collide with the Player instead of the Alien:

void OnCollisionEnter(Collision collision)
{
if (collision.gameObject.tag == "Player")
{
GameObject.Destroy(collision.gameObject);
GameObject.Destroy(this.gameObject);
}
}


Finally, the code for shooting (in the Alien script) will be a little different from that of the Player. Instead of shooting when the user presses a key, the Alien will shoot with a random delay. First, declare the following variables in the Alien class:

    public GameObject bullet;
    public float minShootDelay = 1.0f;
    public float maxShootDelay = 7.0f;
    private float nextShootTime = 0.0f;

In the Unity editor, set the AlienBullet prefab in the Alien script's bullet slot.

In the Start() method, add code to initialise nextShootTime:

        this.nextShootTime = Random.Range(minShootDelay, maxShootDelay);

Unity's Random.Range() method is similar to .NET's Random.Next() method, but not quite the same.

Change the code that handles when bullets leave the game area, since these bullets are going down instead of up:

        if (this.transform.position.y < -3.0f)
            GameObject.Destroy(this.gameObject);

Finally, in the Update() method, we add code for actual shooting:

        if (Time.time > nextShootTime)
        {
            Instantiate(bullet, this.transform.position, Quaternion.identity);
            nextShootTime = Time.time + Random.Range(minShootDelay, maxShootDelay);
        }

If you try it now, things will get a little bit messy as the Aliens' bullets will collide with themselves:


Explaining how to solve this requires an article in itself. Notwithstanding this, in this (long) article we have taken care of several behaviour issues with both the Player and the Aliens, and brought the game much closer to a working Space Invaders clone.

This is the last article in the Ranch Invaders series. I hope you'll return to the Ranch to read about other interesting topics! :)

Friday, May 31, 2013

Unity3D: Space Invaders (Part 4 - Collisions)

Hello again! :)

In the previous article - "Unity3D: Space Invaders (Part 3 - Prefabs)" - we implemented bullet-shooting in our Space Invaders clone. We developed a bullet prefab that we could then create during gameplay when the player shoots at an alien. However, bullets aren't much use if they don't hit something.

In this article, we'll deal with that problem, and allow bullets to destroy aliens upon impact.

First, we need to set up the scene so that the player can actually target an alien when firing. Creating a 2D game in Unity - which uses 3D coordinates - may sometimes be a little bit confusing. To help us get our bearings, let's put create background. From the GameObject menu, select Create Other -> Cube. Rename it to "Background". Resize and move it so that it is very thin, but covers the entire camera view:


Note: we could have used a Plane object here instead of a Cube, but when your game starts to get a little complex, you'll find that a Plane has a number of limitations that a Cube doesn't.

The Alien needs to be directly above the Player, if bullets are to hit it. In the Inspector, set the position of the Player and the Alien so that they have the exact same z-coordinate. Move things around and resize them so that they fit nicely into the camera's view. Give the Background, Player and Alien different coloured materials so that they can be clearly seen from the camera.


Since this looks a bit dull, go to the GameObject menu and select Create Other -> Point Light. Mess with the light's position and intensity (the intensity is in the Inspector when you select the light) until you are happy. In the image below, I also changed the alien's material, since the previous one didn't have very good contrast with the background:


Now, in the Assets panel, double-click the Alien script to open it in MonoDevelop. This is what we had from the article on linear interpolation:

public class Alien : MonoBehaviour
{
    private float startTime;
    
    // Use this for initialization
    void Start ()
    {
        this.startTime = Time.time;
    }
    
    // Update is called once per frame
    void Update ()
    {
        float t = (Time.time - startTime) * 0.4f;
        float x = Mathf.Lerp(-5.0f, 5.0f, t);
        this.transform.position = new Vector3(x, 5, 5);
    }
}

First of all, if you changed position of the Alien, you may need to adjust the code in the Update() method. You can find out the minimum and maximum x coordinates by placing an object at the left and right edges of the Background and taking note of its x-coordinate. A bit of trial and error may also help. For me, this works:

    void Update ()
    {
        float t = (Time.time - startTime) * 0.4f;
        float x = Mathf.Lerp(-2.5f, 2.5f, t);
        this.transform.position = new Vector3(x, this.transform.position.y, this.transform.position.z);
    }

If you didn't do the exercise at the end of the linear interpolation article to make the Alien behave in a proper Space Invaders manner, let's at least make it move back and forth so that the player can hit it at some point. Add this variable to the Alien class:

    private bool movingRight = true;

The Update() method thus becomes:

    void Update ()
    {
        float t = (Time.time - startTime) * 0.4f;
        float x = 0.0f;
        
        if (movingRight)
            x = Mathf.Lerp(-2.5f, 2.5f, t);
        else
            x = Mathf.Lerp(2.5f, -2.5f, t);
        
        if (x >= 2.5f)
        {
            movingRight = false;
            this.startTime = Time.time;
        }
        else if (x <= -2.5f)
        {
            movingRight = true;
            this.startTime = Time.time;
        }
        
        this.transform.position = new Vector3(x, this.transform.position.y, this.transform.position.z);
    }

All this means is that the Alien starts moving right. When it hits the right edge, it starts moving left instead. It keeps moving back and forth between the left and right edges. Try it out in Unity and adjust coordinates if it doesn't feel right:


We are now ready to deal with bullets hitting aliens. Select the Alien, and from the Component menu, select Physics -> Rigidbody, and be sure to turn off "Use Gravity":


This is necessary for the collision to work, as are the box collider on the Alien and the capsule collider on the Bullet. Colliders are just things that help check when an object hits another, and when you create a standard object (such as a cube), colliders are normally added by default.

So now, go double-click the Bullet script to open it in MonoDevelop. Add the following method:

    void OnCollisionEnter(Collision collision)
    {
        GameObject.Destroy(collision.gameObject);
        GameObject.Destroy(this.gameObject);
    }

The OnCollisionEnter() method is called when one collider hits another. The collision parameter gives us information about the collision, including the object was hit (in collision.gameObject). As you can read in the documentation, a rigidbody is required for it to work.

What we are doing here is that when a bullet hits an alien, we use GameObject.Destroy() to remove both the bullet and the alien from the scene. Since the script is running on the bullet, this.gameObject refers to the bullet, and collision.gameObject refers to the alien.

You can now press Play to test this in Unity. Press Space to fire, and when a bullet hits an alien, both should disappear.

There's just one thing that we haven't handled, however: what happens to bullets if they don't hit the alien? As it is, they just keep on accumulating:


Notice the long list of Bullet(Clone)s in the Hierarchy panel. To get rid of bullets that have gone out of view, the easiest way is to just destroy them when they go beyond a certain distance. In the Update() method of the Bullet script, you can add something like this:

        if (this.transform.position.y > 4.8f)
            GameObject.Destroy(this.gameObject);

Awesome! :D In this article, we have handled collisions so that bullets are able to destroy aliens. The game is taking shape.

However, there are still a lot of things we need to do:
  1. Allow the player to move sideways
  2. More aliens
  3. Aliens should move downwards when reaching a side of the game area
  4. Aliens should shoot at the player
  5. There should be a cooldown for firing bullets (e.g. you can only fire one bullet every second)
  6. We need a welcome screen before the game begins
  7. We need a main menu
  8. We need to transition to other levels when all enemies are cleared
  9. We need to show some kind of score
As you can see, creating a game can involve a lot of work, and much of game design is tweaking things until the game feels right and is fun! :)

In tomorrow's last article in the Ranch Invaders series, we will cover the first few points in order to have a single playable level. We will be covering the remaining points as well, but not as part of the Ranch Invaders series!

Thursday, May 30, 2013

Unity3D: Space Invaders (Part 3 - Prefabs)

Hello, and welcome back to the Ranch! :)

This article continues with the Ranch Invaders series. However, like with yesterday's article, if you haven't read the previous articles, you can simply follow along by creating a new Unity project.

In today's article, we're going to add the player's ship into the game, and allow it to shoot bullets. In doing this, we will learn what prefabs are, and how to create objects while the game is running.

From the GameObject menu, go to Create Other -> Sphere. In the Hierarchy section, select the Sphere, press F2, and rename it to "Player". Move it so that it appears in the bottom of the camera's view (you might want to select the Main Camera to see its preview while you do this).

Next, from the GameObject menu, go to Create Other -> Capsule. Rename it to "Bullet". After pressing the 'R' key to go into scaling mode, resize the bullet (capsule) so that it is much smaller than the player (sphere).

Your work so far might look something like this:



Now, from the Hierarchy panel, drag the Bullet into the Assets panel:


The result is that the Bullet is added to the Assets panel, and in the Hierarchy panel, its entry turns blue. This means that the Bullet is now a prefab.

The Player and the Alien objects are simply objects in the scene. Since the Bullet is a prefab, we can refer to it in scripts and create as many Bullets as we like through code. A great thing about prefabs is that you can customise the prefab once (e.g. make a bullet with a yellow material), and all instances of that prefab will have the same features. Let's see how this works in practice.

In the Assets panel, right click somewhere, and in the context menu, select Create -> Material. Name it "Bullet". In the Main Color property, select whichever colour you think is best for a bullet (e.g. yellow). Drag the material onto the Bullet object either in the Hierarchy panel or in the world view:

Right click the Assets panel and Create -> C# Script. Name it "Bullet". Drag the script onto the Bullet object. Double-click the script to launch MonoDevelop.

In the Bullet class, add a public variable to represent the speed:

    public float speed = 1.0f;

When you expose a public variable like this, it appears in the Inspector in the section where the script is:


You can now change this variable as you like through the Inspector, and when you Play the game in Unity, that value will be used. Note, however, that if you change such variables while Playing, changes will be reverted once you stop playing.

Now, we need to write a script that will take care of the bullet's movement. Since we're doing Sp-- sorry, Ranch Invaders, we're looking to do something like this:


The bullet starts at the player's position, and is shot upwards where the Aliens will be. In code, we can do this as follows:

public class Bullet : MonoBehaviour
{
    public float speed = 1.0f;
    private Vector3 target;
   
    // Use this for initialization
    void Start ()
    {
        this.target = this.transform.position + new Vector3(0, 20, 0);
    }
   
    // Update is called once per frame
    void Update ()
    {
        Vector3 currentPosition = this.transform.position;
        Vector3 newPosition = Vector3.MoveTowards(currentPosition, this.target, speed * Time.deltaTime);
        this.transform.position = newPosition;
    }
}

Remember that we're going to have the Player create (shoot) bullets. When the bullets are created, they will be at the Player's position. We want the bullets to go upwards, so we define a target that is a certain distance away (e.g. 20 units). By adding a Vector3(0, 20, 0) that simply points directly upwards, to the initial bullet position, we can set a destination for the bullet that is directly above its starting position.

In the Update() method, we use Vector3.MoveTowards() which works pretty much like Lerp (see yesterday's article). Except that instead, we are moving the Bullet from its current position towards the target in steps of speed * Time.deltaTimeTime.deltaTime is a measure of frame time, so the bullet will move a short length upwards with every frame. We multiply speed to be able to control the speed.

From the Unity editor, press the Play button and watch the bullet move upwards. If you think it's too fast or too slow, tweak the speed by selecting the Bullet and changing the speed value in the Inspector.

You can now delete the Bullet from the scene. Since it's among our Assets, we can create it at runtime. Create a new C# script called "Player" and drag it onto the Player object. Double-click the Player script to open it in MonoDevelop.

In the Player class, add the following public variable:

    public GameObject bullet;

Save the script. Back in Unity, select the Player object, and in the Inspector, under the Player Script, notice that there is now a slot for the bullet game object:


From the Assets panel, drag the Bullet prefab into the appropriate slot in the Inspector, where it currently says "None (Game Object)".

Now, from the Player script, we can make instances of this prefab. In the Update() method of the Player script, just add the following:

        if (Input.GetKeyDown(KeyCode.Space))
        {
            Instantiate(bullet, this.transform.position, Quaternion.identity);
        }

So all we're doing here is that when the player presses the Space key, we use the Instantiate() method to create a bullet. We give it the object we want to instantiate (in this case the bullet prefab), and its starting position and orientation (rotation). I'm not going to go into quaternions here, but Quaternion.identity simply means that the bullet isn't rotated.

You can now press Play to try out the game. Press Space to watch bullets move like sausages in the sunset:


If it doesn't work, don't worry! :) Depending on how you carried out the steps above, it is possible that the bullet prefab wasn't saved correctly. In my case, for example, I found that the Bullet script was missing. Since a prefab is really just a template for an object, you need to make sure that any changes to it apply to all the objects that use that template. So in the case of the missing script, once you drag the Bullet script onto a Bullet object in the scene, you need to click "Apply" at the top of the Inspector in order to apply the changes to all affected objects.

Great! We can now shoot sausage-like bullets to our heart's content. We still have some work left to do, though: we need more aliens, the player's ship needs to move sideways, bullets need to destroy aliens, etc. We'll handle some of these things in the next article. Until then, au revoir! :)

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). :)

Monday, May 27, 2013

Unity3D: Space Invaders (Part 1 - Navigation and Materials)

Hello, fellow game developers! :)

In today's article we're going to start working on a clone of the arcade classic, Space Invaders. To prevent Tomohiro Nishikado from suing my ass off, we'll instead call this Ranch Invaders. Through this game we'll learn a number of important concepts including prefabs, linear interpolation, materials, and more. Since we can't learn all this in a single article, this will be spread out over several articles.

If you've been following my previous Unity3D articles, the last project you used will automatically open when you launch Unity. Create a new project from File menu -> New Project... and find a place to put it:


You don't need to import any packages. Once Unity relaunches with your new project, press Ctrl+S to save your .unity (scene file) somewhere.

Great. Now, we'll begin working on the alien, and we'll use it to learn some basics about working with Unity. For the time being, we'll use a simple cube as the alien, so go to GameObject menu -> Create Other -> Cube, just the same as we did in the previous two articles. You should now have a cube sitting in your game world (left portion of the screen):


You can see from the Inspector that the cube is at (0, 0, 0). You will also notice three arrows (red, green and blue) shown on the cube in the game world. You can click and drag one of the arrows to move the cube, and you will see the Position values in the Inspector change. You can also drag one of the squares between the arrows in order to move the cube in two directions (e.g. X and Y) at once.

In the Hierarchy section, there's also an object called Main Camera apart from the Cube you placed. If you select it, you'll see a little preview window:


If you press the Play button at the top of the Unity interface, you'll see the same thing. The main camera represents what the player is seeing.

Select the Cube again. Using the mouse, you can navigate the scene in order to work with the objects in it. If you press Alt and click and drag the left mouse button, you can rotate the view around the currently selected object (the Cube in our case). A middle-click (click the mouse's scroll wheel) and drag pans (moves sideways) the view relative to the selected object. By scrolling the mouse wheel, you can zoom the view towards or away from the camera. Finally, you can use the gizmo at the top-right of the world view to view the scene from particular directions (e.g. from the top).

You can manipulate the object itself by moving, rotating, or scaling it. We have already seen how to move an object (by using the arrows). You can use the W, E and R keys (or the buttons at the top-left of the Unity interface, just below the File menu) to switch between movement, rotation and scaling mode. When you do this, the arrows will change:


The screenshot above shows how the arrows change when you are scaling. You can drag one of the coloured boxes to scale in one direction, or the small box at the centre in order to scale uniformly (in all directions). Rotation has yet another thingy you can drag in order to rotate in different directions.

Once you're comfortable with navigating the scene using these controls, it's time to customise our Alien (Cube) a little bit.

With the Cube selected in the Hierarchy panel, press F2 and rename it to Alien.

Next, right click on the Assets panel and select Create -> Material. Name it Alien as well. Click on the white box next to "Main Color" and select whatever colour you want your alien to be:


Drag the material from the Assets panel onto the cube in the world view:


Other than using a solid colour, you can also select an image that you think would make it look more like an alien. To do this, right click in the Assets panel, select Import New Asset... and find the image you want on your filesystem. Once the image appears in your Assets panel, you just need to select the Alien's material and drag the image into the area that says "None (Texture)":


That's about as alien-like as it can get. This technique of wrapping an image around a 3D object is called texturing, and the image is called a texture.

Great! :) We covered some basic navigation controls in this article, as well as how to apply a material to a 3D object. The material may be either a solid colour or an image (texture).

In the next article, we will learn about linear interpolation, and use it to script the alien's sideways-moving behaviour. Until next time! :)

Sunday, May 26, 2013

Unity3D: Setting up Source Control with SVN

Hi all! :)

Any experienced developer will tell you that source control using something like SVN is important for anything but the simplest projects. Source control allows you to keep a complete history of any changes you made, download them to different machines (great when working with other people on the same project), compare different versions of source files, and even revert to a specific version when necessary.

This article assumes you are already familiar with SVN, and are using a client such as TortoiseSVN. If you have no clue at this point, you can safely skip this article - future articles will not depend on it.

Start a new project and insert a cube into the game world via GameObject menu -> Create Other -> Cube, just so we have something in the game world.

Press Ctrl+S to save a .unity file into your project's Assets folder. This .unity file is called a Scene file - you can have several different scene files for different views such as the main menu, credits screen, and actual gameplay.

Now that you have something small in your project, you might want to commit it into SVN. The problem is that in your project's Library folder, there is this metadata folder with loads of weird subfolders:


...and each of those subfolders has a bunch of weird files:


Given that there are loads of such files and folders, and that they change very frequently, maintaining these in SVN will be a nightmare.

Fortunately, however, there is another way to use SVN with Unity.


From the Edit menu, go to Project Settings -> Editor. The Editor Settings will appear in the Inspector, on the right. From here, change the Version Control Mode from Disabled to Meta Files.

In Windows Explorer, navigate to your project folder:


Close Unity. The Temp folder will disappear.

Next, delete the Library folder. Don't worry - this will be created with the new meta files format (instead of all those weird files and folders) next time we open Unity.

You can now commit the project folder into SVN. If you're using TortoiseSVN, right click on the project folder, and select TortoiseSVN -> Add... and select all files and folders in the project. Then, right click the project folder and select SVN Commit... to commit the project into SVN:


Now, re-open the project in Unity by double-clicking the .unity file in your project's Assets folder. In the status bar at the bottom-left, you will see a message saying "Rebuilding Library because the asset database could not be found!":


Finally, to prevent you from accidentally committing the Library or Temp folders while you work, add both folders to the SVN ignore list by right-clicking on each folder and selecting TortoiseSVN -> Add to ignore list -> [Library/Temp]:


Once you have done this, the Temp and Library folders should carry an appropriate icon showing that they are excluded:


You can now continue making changes in Unity and committing them to your heart's content.

I hope that this was useful, and that you'll check back for other articles on Unity3D and on programming in general! :)