Top Banner
Game Development - Unity Lab 2 Making Your Tank Move As always, make sure to double-click the “Tank” scene under the Project Asset’s folder to get the current working version. This tutorial will cover the following: Adding movement to our 2D tank sprite Adding a Terrain background layer Adding a GroundDetector to our tank Basic scripting Some Basic Scripting Scripts allow us to add behavior to our GameObjects. Let’s start by creating a simple C# tank controller script to move the tank around. Click the “Create” drop down under the Project panel like so: This will generate an empty script for us, please select the script and rename it to “TankController.” You should see the following code: using UnityEngine; using System.Collections; public class TankController : MonoBehaviour { // Use this for initialization void Start () { }
20
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
  • Game Development - Unity Lab 2

    Making Your Tank Move As always, make sure to double-click the Tank scene under the Project Assets folder to get

    the current working version.

    This tutorial will cover the following:

    Adding movement to our 2D tank sprite

    Adding a Terrain background layer

    Adding a GroundDetector to our tank

    Basic scripting

    Some Basic Scripting Scripts allow us to add behavior to our GameObjects. Lets start by creating a simple C# tank

    controller script to move the tank around. Click the Create drop down under the Project panel

    like so:

    This will generate an empty script for us, please select the script and rename it to

    TankController. You should see the following code:

    using UnityEngine;

    using System.Collections;

    public class TankController : MonoBehaviour {

    // Use this for initialization

    void Start () {

    }

  • // Update is called once per frame

    void Update () {

    }

    }

    This will not be very helpful for making our tank move around so lets update it a bit with some

    moving and jumping logic.

    using UnityEngine;

    using System.Collections;

    public class TankController : MonoBehaviour {

    [HideInInspector]

    public bool jump = false;

    public float moveForce = 365f;

    public float maxSpeed = 5f;

    public float jumpForce = 1000f;

    private Transform groundDetector;

    private bool grounded = false;

    void Awake()

    {

    // Setting up references.

    groundDetector = transform.Find("GroundDetector");

    }

    void Update()

    {

    // The player is grounded if a linecast to the groundcheck position hits

    anything on the ground layer.

    grounded =Physics2D.Linecast(transform.position, groundDetector.position,

    1

  • // If the jump button is pressed and the player is grounded then the player

    should jump.

    if(Input.GetButtonDown("Jump") && grounded)

    jump = true;

    }

    void FixedUpdate ()

    {

    // Cache the horizontal input.

    float h = Input.GetAxis("Horizontal");

    if(h * rigidbody2D.velocity.x < maxSpeed)

    rigidbody2D.AddForce(Vector2.right * h * moveForce);

    if(Mathf.Abs(rigidbody2D.velocity.x) > maxSpeed)

    rigidbody2D.velocity = new

    Vector2(Mathf.Sign(rigidbody2D.velocity.x) * maxSpeed, rigidbody2D.velocity.y);

    // If the player should jump...

    if(jump)

    {

    rigidbody2D.AddForce(new Vector2(0f, jumpForce));

    jump = false;

    }

    }

    }

    Ok, now that we have our new motion script, we must make a couple of modifications to our

    Unity game scene.

    Adding a GroundDetector

    We will now need to add a GroundDetector we can use to determine whether or not our tank

    is touching the ground.

  • This ground detector will be an empty GameObject (consisting of nothing more than a

    transform component and a red oval placeholder shape). The end user will not be able to see

    this object, but it will be useful in code.

    Create an empty GameObject (GameObject -> Create Empty). Now select your new empty

    GameObject, rename it to GroundDetector in the Inspector window and choose a red pill

    outline for it (this makes it easy to see in the game scene).

    Now, move the GroundDetector into our Tank GameObject at the bottom of our tank, it should

    look like this when you have finished.

    Ok, before we finish we have one more minor task, which is to add our Terrain to the Terrain

    Layer. Start by selecting Layers -> Edit Layers in the upper right hand corner of the main

    Unity window.

  • In Unity, layers help us to sort GameObjects into categories for determining how collisions are

    to be resolved. If we have a number of background game objects which never interact with

    anything on the screen (such as clouds or other scenic elements), we can simply move those

    objects into a Scenery layer to get them out of the way.

    On the Edit Layers menu, add a Terrain layer as below.

    Next, click our Terrain object and set its layer to Terrain.

    This isnt exactly ideal, we will need to make some changes to our tanks physics behavior to

    make it behave less spastically.

    Change your tanks mass to 20

    Change Max Speed to 5

    Change Jump Force to 5000

    Modify your Tanks Box Collider 2Ds center Y value to -0.4

    Modify your Tanks Box Collider 2Ds size Y value to 0.2

  • Get to the Chopper

    Right now our tank is a single unified sprite. However, we need to chop it up a bit so we can

    allow fun behaviors like aiming the tanks turret, allow individual wheel movements and (later)

    allow us to blow up our tank if we lose the game.

    As before, click the tanks sprite in the project panel at the very bottom of the Unity

    screen. Select Sprite mode -> Multiple to indicate that our Tank sprite actually contains

    many small sprites.

    Now click Sprite Editor, you should see this.

    Now click + drag inside the slice window to add slice boxes around the following

    components: Slice each tank wheel, slice the turret barrel and slice the body of the tank.

    When you slice each section, a blue box will appear indicating the size of the current slice.

    When you are done with a section, simply release the mouse and then click + drag again

    somewhere else to initiate a new slice.

  • When you are done slicing, click Apply to perform the slice and then close the window.

    You should now see the following sub slices on your tank sprite (click the arrow to make the

    sprite drawer slide out).

    Before we get too excited, go back into the sprite editor, click each sprite slice and name them

    like so: turrent, shell, wheel_1, wheel_2, wheel_3. Click apply to update the sprite names.

    Adding Our New Parts

    Well that was fun, but now we have a new problem: We must add all these sprites back into

    our scene under our Tank GameObject. As you can see, our Tank Body Sprite now consists

    of just our turret.

  • Next, systematically create new sprite renderers, nest them inside the tank GameObject and

    select the appropriate sprites from the sprite sheet we just carved up and put all the pieces back

    where they were before. The result (in wireframe mode) should look something like this:

    Note: You get to wire-frame mode by selecting the drop down in the upper left hand menu in

    the scene viewer.

  • Adding a Cannon

    We have our new and improved cannon, what do we do with it? Drag and drop it into the

    project and open up the Sprite Editor as in prior tutorials. Make sure to click Sprite Mode:

    Multiple to get the Sprite Editor to show up.

    This time, we will need to modify the pivot point so that our cannon will pivot at the base

    instead of the center (default). It will look like this initially. Notice that the blue pivot point is

    dead center. Thats not good.

    Move the pivot to the bottom center by clicking the Pivot drop down and selecting Bottom.

  • Now the pivot should appear in the center, bottom of the cannon.

    Ok, now go ahead and delete the old, lame cannon from our tank, create a new Sprite Renderer,

    place that inside the Tank and then set our new cannon graphic as the sprite. Name this sprite

    renderer Turret.

    Make it look like this:

    Now we need to make the cannon point at the mouse, this will require a new script. Create a new script called TurretController and drop it onto the Turret Sprite Renderer you just created.

    Here is the script for it:

    using UnityEngine;

    using System.Collections;

    public class TurretController : MonoBehaviour {

    private Vector3 mouse_pos;

    private Vector3 object_pos;

    private float angle;

    // Use this for initialization

    void Start () {

    }

    void Update(){

    }

    void FixedUpdate () {

    //

    mouse_pos = Input.mousePosition;

    mouse_pos.z = 0.0f;

    object_pos =

    Camera.main.WorldToScreenPoint(transform.position);

  • mouse_pos.x = mouse_pos.x - object_pos.x;

    mouse_pos.y = mouse_pos.y - object_pos.y;

    angle = Mathf.Atan2(mouse_pos.y, mouse_pos.x) *

    Mathf.Rad2Deg - 90;

    Vector3 rotationVector = new Vector3 (0, 0, angle);

    transform.rotation = Quaternion.Euler(rotationVector);

    }

    }

    Now click play

  • Game Development - Unity Lab 3

    Prefabs are pre-fabulous

    Unity prefabs are reusable GameObjects which can be placed or spawned in scenes over and

    over again (and transferred easily between projects and scenes). Prefabs offer the benefit of

    portability to our GameObjects. We are going to start by simply dragging our Tank into the

    Project view at the bottom. This will turn its title blue and automatically convert it into a

    Prefab. Also create a Prefabs folder just to stay organized and drop our tank into it.

    Now that we have a prefab tank, lets create a prefab enemy to go with it.

    A Simple Enemy

    So for the sake of the tutorial we will be pretending that this looks like an evil, threatening

    space alien bent on the destruction of earth. Download it and drag + drop it into the Unity

    Assets folder, set its type to Sprite, create a new Sprite Renderer GameObject, use this as

    the sprite and then name it to Alien. Drag and drop it into the Assets folder to convert it

    into a Prefab.

    &

  • Once you have the Alien prefab, also add a Circle Collider to it so it looks like this. Note,

    you may want to tighten up the circle collider to more closely fit the alien sprite than the

    below.

    A Basic Alien Movement Script

    Before moving our alien, we need to introduce the concept of tags. Open your Tank and click

    the Tag drop down in the Inspector window. Choose Player.

    Do the same with Alien and Terrain, respectively adding the Terrain and Alien tags by

    clicking the Add Tag button. Tags are words we can apply to items in the scene to help

    categorize them for scripting purposes. Tags may also be used to search for GameObjects in

    the scene.

  • We will use these for some collision detection later on.

    Now add this movement script to the Alien prefab. Make sure to also add a RigidBody2D

    (required for collisions) and click the isKinematic to disable physics on it.

    using UnityEngine;

    using System.Collections;

    public class AlienController : MonoBehaviour {

    public float alienSpeed = .02f;

    // Use this for initialization

    void Start () {

    }

    // Update is called once per frame

    void Update () {

    transform.position += new Vector3(0, -alienSpeed, 0);

    }

    void OnCollisionEnter(Collision collision) {

    }

    }

    Handling Collisions

    Collisions in 2D can be extremely fiddly and there are a number of things which can go

    wrong to screw them up so proceed with caution.

  • Trigger Happy

    For this next part you need to refactor our scene to remove our old jagged terrain and replace

    it with a flat terrain. This terrain is just a grey sprite with a box collider.

    To check for collisions we will need to make use of the tags which we added in the last scene.

    Converting a collider to a trigger causes it to be ignored by the physics engine and also

    enables us to intercept trigger events from colliding with other objects. Please make sure that

    our Aliens Circle Collider 2D has been set to a trigger as below.

    Note that we also added a Rigidbody 2D (this is required for collisions to work properly with

    triggers) and set its gravity scale to 0 to prevent it from interfering with the alien motion

    logic.

  • Next, update the script for the AlienController to make it look like this:

    using UnityEngine; using System.Collections; public class AlienController : MonoBehaviour { public float alienSpeed = .02f; // Use this for initialization void Start () { } // Update is called once per frame void Update () { transform.position += new Vector3(0, -alienSpeed, 0); } void OnTriggerEnter2D(Collider2D col) { // If the alien hits the trigger... if (col.gameObject.tag == "Player") { Destroy (gameObject); } else if (col.gameObject.tag == "Terrain") { Destroy (gameObject); } } }

    By adding the OnTriggerEnter2D function, we can now intercept any and all colliders which

    pass into the space occupied by our alien spaceship. We then check their tags and can destroy

    the space ship on command.

    NOTE: We will have to face many problems with triggers and collisions until realize that

    some of the Z-values on a few of our prefabs were off. Because we are working in 2D, all Z-

    values must be the same if you expect collisions to get triggered. If your objects dont seem

    to be colliding double check that they are all on the same plane.

  • Basic UI with GUI Text

    This guide covers some very basic UI text to track your score whenever an alien happens to die.

    A Basic Scoreboard

    Start by clicking GameObject -> Create Other -> GUIText

    Next, name this object Score and create the following script then name it

    ScoreController.

    using UnityEngine;

    using System.Collections;

    public class ScoreController : MonoBehaviour {

    public int score = 0; // The player's score.

    private int previousScore = 0; // The score in the previous frame.

    void Awake ()

    {

  • }

    void Update ()

    {

    // Set the score text.

    guiText.text = "Score: " + score;

    // Set the previous score to this frame's score.

    previousScore = score;

    }

    }

    Your score game object should look like this now:

    Note: GUI elements behave in a different manner than other game objects, the coordinates for

    the transform are not in world coordinates but in screen coordinates. Therefore, you must

    make sure to constrain them between 0 and 1 if you want the GUI elements to appear in the

    screen. Otherwise, you wont see your text. Please verify the Score is within 0 1 for both

    its X and Y coordinates.

  • Now, open up the AlienController script and add the following script update:

    using UnityEngine;

    using System.Collections;

    using UnityEngine;

    using System.Collections;

    public class AlienController : MonoBehaviour {

    public float alienSpeed = .02f;

    private ScoreController score;

    // Use this for initialization

    void Start () {

    score = GameObject.Find("Score").GetComponent();

    }

    // Update is called once per frame

    void Update () {

    transform.position += new Vector3(0, -alienSpeed, 0);

    }

    void OnTriggerEnter2D(Collider2D col)

    {

    // If the alien hits the trigger...

    if (col.gameObject.tag == "Player") {

    Destroy (gameObject);

    if(score.score >= 100)

    score.score -= 100;

    else if(score.score > 0)

    score.score = 0;

    } else if (col.gameObject.tag == "Terrain") {

  • score.score += 100;

    Destroy (gameObject);

    }

    }

    }

    Now, when the alien dies by crashing into the ground, the score will update. The result will

    look like this: