Badblog

welcome to our blog

We are Learncodz.


Posts

Comments

The Team

Blog Codz Author

Connect With Us

Join To Connect With Us

Portfolio

    Posted by: Unknown Posted date: 19:59 / comment : 0

    Our mini game is going to have several different types of pickups for the user to collect. Type 1 will simply increment the score, type 2 will add or subtract a random score and type 3 will either speed up or slow down the player. To make it more interesting the pickups will randomly change while the player is playing.
    The first step is to create a new script that will define what type of pickup each instance is.
    Open your project from last time or download the source from above; then within the Project Window right-click on the Scripts folder and select Create -> JavaScript; rename it Pickup.
    unity tutorial: gui, timers, particles
    We'll now add this new script as a Component of our pickup prefab, so select the 'pickup-prefab' from within the Prefabs folder and drag the Pickup script onto the Inspector Window (or onto the 'pickup-prefab' itself).
    unity tutorial: gui, timers, particles
    Every instance of the pickup that's now spawned will feature this new script which will determine the type of pickup it is and various other properties. Let's now define these types.
    When the pickup is spawned we're going to decide randomly what type it is, so add the following code to the Pickup script:
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    // variable to hold the type
    public var type:int;
     
     
    function Awake()
    {
        // set a random type to begin
        SwapType();
    }
     
    function SwapType()
    {
        // generate a random number between 1 and 10
        var random:float = Random.Range(1,10);
         
        // set the type
        if (random <= 5) // 50% for type 1
        {
            type = 1;
        }
        else if (random <= 8) // 30% for type 2
        {
            type = 2;
        }
        else // 20% for type 3
        {
            type = 3;
        }
    }
    The above block of code defines a variable 'type' which, when the script initialises, is randomly set to a value of 1 (standard point pickup), 2 (point gamble pickup) or 3 (speed powerup) to define the type of the pickup.
    We generate the random number using Random.Range(...) and then use a series of if statements to increase the probability of it being a standard point pickup (type = 1) and therefore make the speed powerups more rare to come across.
    Once instantiated the pickup will currently remain the same type for the duration of its lifetime. Let's make it a little more interesting by making it change type after a random number of seconds.
    Add the following variables and Start() function to the script:
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    // min and max times for type change
    public var minTypeChange:int = 10;
    public var maxTypeChange:int = 30;
     
    function Start()
    {
        while (true)
        {
            // wait for X seconds
            yield WaitForSeconds(Random.Range(minTypeChange, maxTypeChange));
             
            // set a random type
            SwapType();
        }
    }
    This essentially starts a while loop which will run forever since the condition being tested is always true. The first part of the statement uses a yield WaitForSeconds(...)statement to create a delay for a random number of seconds, between the min and max values specified, before then swapping the type of the pickup by calling the SwapType function we defined earlier on.
    So the game should currently work as we expect - but the player has no idea what type of pickup they are collecting! So now let's brighten up our pickup a little to distinguish between the different types. We'll use everyone's favourite feature...
    So that the player can tell the difference between the pickups, we're going to add different coloured particle systems in the centre of the pickups.
    Drag an instance of the pickup-prefab into the scene and focus on it by either using the F key or double-clicking on it within the Hierarchy. Add a Particle System using the top menu: GameObject -> Create Other -> Particle System. Make it a child of the pickup-prefab by dragging it onto the pickup-prefab within the Hierarchy; click Continue when the below dialog warns you about losing the prefab connection.
    unity tutorial: gui, timers, particles
    Use the Inspector to position the Particle System at (0, 0, 0) so that it's in the centre of the pickup model as illustrated below.
    Note: if you have the particle system or one of its parents selected then the particle system will emit particles within the Scene Window; it will otherwise cease emitting the particles until reselected.
    unity tutorial: gui, timers, particles
    So you should now have your first particle system positioned in the centre of the pickup.
    Particle Systems within Unity are made up of three Components: an Emitter, anAnimator and a Renderer. Their names are quite self explanatory and each features a handful of public variables for you to customise, allowing all kinds of awesome visual effects to be produced.
    You can read more about each on their Component Reference pages that are linked above. You can also find their Script Reference pages here: EmitterAnimator andRenderer.
    Currently our particle system is quite boring, right? Select the particle system and within the Inspector adjust the Emitter Component to match the values below:
    unity tutorial: gui, timers, particles
    All we've done is alter the energy that the particles have, affecting how long they 'live' for, and shrunk the Ellipsoid where they are emitted from so you should now notice that the particles are now all emitted much more closely together in the centre of the pickup.
    unity tutorial: gui, timers, particles
    Now match your particle's Animator Component to the values shown below:
    unity tutorial: gui, timers, particles
    The changes we've made here are the addition of a random force to the particles on each axis, to make them appear more natural, and a size grow value of 1 so that they'll grow larger over time as shown below.
    unity tutorial: gui, timers, particles
    That's our particle system complete; we'll adjust the colours using our Pickup script.
    Finally, to update the pickup prefab, with the pickup-prefab object within the hierarchy selected, click the Apply button at the top of the Inspector. You can then delete the pickup from the Hierarchy.
    Let's now adjust our Pickup script to alter the colour of the particles depending on what type of pickup it is.
    As you may have noticed within the particle systems Animator Component a particle can animate through five different colours, each of which may have a colour and alpha (transparency) value.
    If you inspect the Script Reference page for the Particle Animator and take a closer look at the colorAnimation property you'll notice that it's an Array of Color Objects.
    Let's now introduce a variable to store the pickup's particle system so we can access its colours, and introduce three new Arrays (datatyped to Color) to our Pickup script. Go ahead and add the following code to the script:
    1
    2
    3
    4
    5
    6
    7
    // the particles gameobject
    public var particles:GameObject;
     
    // colours for each type of pickup
    public var type1:Color[];
    public var type2:Color[];
    public var type3:Color[];
    Save the script and reselect the pickup-prefab within the Project Window. Expand the pickup-prefab to view its children and drag the particle system which is a child onto the Pickup Components new particles variable.
    You should also now notice the three new arrays within the inspector; set each of their sizes to 5 as below since this is how many colours the particles need to animate through.
    unity tutorial: gui, timers, particles
    The colours are all currently black, which isn't so exciting, so select the first element of Type1 and within the resulting colour palette select a bright colour (I used green below) and set the alpha (A) to 50.
    unity tutorial: gui, timers, particles
    Repeat this for the remaining colours of Type 1, increasing the alpha to full value and then back out again so the particles fade in and out - the alpha value for each colour is represented by the white bar along the bottom of the colour as shown above. I also chose to use a slightly darker green for when the particle is fading out - you can of course colour them however you wish.
    Repeat this process using different colours for Type2 and Type3 as I have below.
    unity tutorial: gui, timers, particles

    So, that's our colours created. The last thing to do is to actually assign them to thecolorAnimation property of the particle system's Animator.
    It's worth noting, as mentioned in the colorAnimation Script Reference, that when modifying the colours via code you must grab, modify and re-assign the whole array rather than individual colours. We can thankfully just overwrite the current colorAnimation Arrays with our own ones, which is nice and easy.
    Introduce the following variable and overwrite the current Awake() function with the one below, which retrieves and stores the particles ParticleAnimator Component for us to use later on.
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    // the particles animator component
    private var particleAnimator:ParticleAnimator;
     
    function Awake()
    {
        // retrieve the particle animator Component from the particles
        particleAnimator = particles.GetComponent(ParticleAnimator);
         
        // set a random type to begin
        SwapType();
    }
    Finally, overwrite the current SwapType() function with the below:
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    function SwapType()
    {
        // generate a random number between 1 and 10
        var random:float = Random.Range(1,10);
         
        // set the type
        if (random <= 5) // 50% for type 1
        {
            type = 1;
            particleAnimator.colorAnimation = type1;
        }
        else if (random <= 8) // 30% for type 2
        {
            type = 2;
            particleAnimator.colorAnimation = type2;
        }
        else // // 20% for type 3
        {
            type = 3;
            particleAnimator.colorAnimation = type3;
        }
    }
    This introduces an extra line for each condition of the if statement, assigning the relevant array to the colorAnimation property of the particleAnimator variable. Job done.
    If you now play the game the powerups will each have coloured particles within them and there should be more with the colour used for Type1 than Type2 or Type3. They do still look a little boring, however, since they're just static on the spot; let's quickly add a little random rotation to them.
    This is a dead simple addition, but it will make our pickups look a little more interesting.
    Add the following variables and Update() function to the Pickup script:
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    16
    // min and max rotation speeds
    public var minRotationSpeed:float = 0.5;
    public var maxRotationSpeed:float = 2.0;
     
    // calculated rotation speed
    private var rotationSpeed:float;
     
     
    function Update ()
    {
        // rotate the gameobject every frame
        transform.Rotate(rotationSpeed, rotationSpeed, 0);
         
        // rotate the particles every frame (so they rotate at twice the speed of the whole object)
        particles.transform.Rotate(rotationSpeed, rotationSpeed, 0);
    }
    Then, overwrite the Awake() function with the following, which calculates the random rotationSpeed when the script initializes:
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    function Awake()
    {
        // calculate a random rotation speed
        rotationSpeed = Random.Range(minRotationSpeed, maxRotationSpeed);
         
        // retrieve the particle animator Component from the particles
        particleAnimator = particles.GetComponent(ParticleAnimator);
         
        // set a random type to begin
        SwapType();
    }
    If you now run the game again, the pickups should all rotate at random speeds! Time to start scoring!
    Before we construct our interface we have to decide on the resolution of our game and ensure our Game Window is of this resolution so we can accurately position our interface elements.
    I'm using the default WebPlayer export sizes (600x450) which you can change using the top menu, Edit -> Project Settings -> Player. You can also decide which version of the WebPlayer template you wish to use.
    unity tutorial: gui, timers, particles
    Once you've decided on the resolution of your game you need to set your Game Window to be of the same size, you can do this using the menu in the top left hand corner of the Game Window shown below
    unity tutorial: gui, timers, particles
    We can now accurately position our interface elements within the Game Window, it's important to remember to position interface elements whilst observing the Game window, NOT the Scene Window.
    Lets now start making our interface...
    Before we start scripting for the scoring we'll construct the interface to hold the score by introducing GUITextures (GUI = Graphical User Interface), which will form the static portion of the interface.
    Download this package which contains the font and texture required for our interface. The Font used is called IrisUPC and is available here. Double-click the package to extract the contents and click Import to import all the assets when prompted with the Import dialog window:
    unity tutorial: gui, timers, particles
    You'll now have two new folders within your Project Window: Fonts and GUI.
    Let's now start creating our game's GUI. First, add a new Empty GameObject (using the top menu), rename it to "GUI" and position it at (0, 0, 0). This will be the container for our GUI so our Hierarchy is neatly organised.
    Expand the GUI folder within the Project Window and select the 'game-gui' and using the top menu add a GUITexture: GameObject -> Create Other -> GUITexture. You should now have something similar to below:
    unity tutorial: gui, timers, particles
    So, at the moment this isn't too great since we want to align this graphic with the top of the screen.
    First, let's alter its pixel inset within the Inspector so that its pivot point is no longer in the centre, and then reposition it along the top of the screen. Select the game-gui and match its Transform and GUITexture Components to those shown below:
    unity tutorial: gui, timers, particles
    What we've done here is altered the GUITexture pixel inset Y value to -64 (which is the height of the image), so its pivot point is along the top of the image. Now when we set the Y value within the Transform Component to 1, the GUITexture aligns perfectly with the top of the screen; there would otherwise be a gap of 32px.
    Remember: When positioning GUI Elements within Unity, (0,0) is the bottom left corner of the screen and (1,1) is the top right corner of the screen.
    So that's it for our GUITexture; time to add the GUIText...
    With the graphics for our interface in place it's now time to introduce GUIText which will display the player's score and the time remaining.
    Expand the Fonts folder, select UPCIL within Iris, and then create a GUIText GameObject using the top menu: GameObject -> Create Other -> GUIText. Rename it to txt-score and make it a child of GUI.
    You should now have some small text saying 'Gui Text' appear in the centre of the screen using the UPCIL font. Note: When creating GUIText it's easier to select the font before creating the GUIText than to set it afterwards.
    Within the Inspector, match the Transform and GUIText Components' settings to those shown below:
    unity tutorial: gui, timers, particles
    The above Transform Component positioning will align the GUIText as shown below with the 600x450 WebPlayer resolution - if you are using a different resolution you may need to play with the values to align it correctly. Note that, by setting the Z axis value to 1, the GUIText gets positioned in front of the GUITexture.
    We set the text to '888' since this is the widest it will ever be; we've also changed the anchoring to centre the text rather than having it aligned to the left. Finally we've enlarged the font size to 36:
    unity tutorial: gui, timers, particles
    Now follow the exact same steps again - but rename the GUIText to txt-time - and set its Transform Component to the settings shown below so that you have something similar to the image:
    unity tutorial: gui, timers, particles
    So that's the building of the interface complete, now it's time to hook it all together.
    Reopen the PickupController script and add the following two variables and function to the script:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    // textfield to hold the score and score variable
    private var textfield:GUIText;
    private var score:int;
     
    function UpdateScoreText()
    {
        // update textfield with score
        textfield.text = score.ToString();
    }
    Pretty self explanatory here. Two variables, one to track the score and one to store the textfield the score's displayed in. The UpdateScoreText() function sets the text of the textfield to the string value of the score variable using the ToString()function.
    Before this function is called, however, we must assign our textfield a value. Add the following code to the Awake() function:
    1
    2
    3
    textfield = GameObject.Find("GUI/txt-score").GetComponent(GUIText);<br />
    score = 0;
    UpdateScoreText();
    This will find the 'txt-score' GameObject - assuming you've placed it within your Hierarchy as asked - and retrieves its GUIText component. The score variable is then set to 0 and UpdateScoreText() is called.
    Currently you should get a 0 on the screen when clicking Play; however there is nothing to increment the score, so replace the Collected(...) function with the one below:
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    function Collected(pickupCollected:GameObject)
    {
        // retrieve name of the collected pickup and cast to int
        var index:int = parseInt(pickupCollected.name);
         
        // pickup has been destroyed so make the spawn index available again
        spawnIndexAvailableList[index] = true;
         
        // retrieve the pickup state
        var type:int = pickupCollected.GetComponent(Pickup).type;
         
        // update the score depending on the type of pickup
        if (type == 1)
        {
            score+=2; // simply add 2 to the score
        }
        else if (type == 2)
        {
            score += Random.Range(-2, 5); // add a random score between -2 and 5 to the score
        }
         
        // update the score
        UpdateScoreText();
         
        // destroy the pickup
        Destroy(pickupCollected);
         
        // wait for a random amount of seconds between minimumSpawnDelayTime and maximumSpawnDelayTime
        yield WaitForSeconds(Random.Range(minimumSpawnDelayTime, maximumSpawnDelayTime));
         
        // spawn a new pickup
        SpawnPickup();
    }
    You should notice we've added a few lines to the centre of the function to retrieve the type variable from the pickup that was collected and then increment the score by either a static value of 2 for pickups of type 1, or a random value between -2 and 5 for both type 2 and 3 pickups.
    The textfield is then updated after the score is adjusted. Easy, right?
    unity tutorial: gui, timers, particles
    Before making the timer display lets make one of our pickups affect the player's speed.
    Open the PlayerController script and add the following variables:
    1
    2
    3
    4
    5
    6
    7
    // the PickupController component of the 'PickupSpawnPoints' gameObject
    private var characterMotor:CharacterMotor;
     
    // speed variables
    public var minSpeed:int = 5;
    public var maxSpeed:int = 35;
    private var originalSpeed:int;
    Now replace the current Awake() function with the following:
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    function Awake()
    {
        // retrieve the PickupSpawnPoints gameObject
        var pickupSpawnPoints:GameObject = gameObject.Find("PickupSpawnPoints");
         
        // and then retreive the PickupController Component of the above PickupSpawnPoints gameObject
        pickupController = pickupSpawnPoints.GetComponent("PickupController");
         
        // retrieve the players CharacterMotor Component
        characterMotor = GetComponent(CharacterMotor);
         
        // retrieve the players original speed from the characterMotor
        originalSpeed = characterMotor.movement.maxForwardSpeed;
    }
    So what's changed? We've introduced a characterMotor variable which retrieves the CharacterMotor Component of the player where we can access the player's speed. We also introduced several speed variables to track the original speed and set minimum and maximum speed values.
    This is all great so far, but it won't make a difference within our game since we're only storing the original speed. We need to adjust the speed when the player collides with one of the pickups.
    Replace the OnControllerColliderHit(...) function with the below:
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    function OnControllerColliderHit (hit:ControllerColliderHit)
    {
        // if the player hits a pickup
        if (hit.gameObject.tag == "Pickup")
        {
            // call the Collected(...) function of the PickupController Component (script) and
            // pass the pickup we hit as the parameter for the function
            pickupController.Collected(hit.gameObject);
             
            // if the pickup is set to type 3 then adjust the players speed
            if (hit.gameObject.GetComponent(Pickup).type == 3)
            {
                // stop any coroutines already running
                StopCoroutine("AdjustSpeed");
                 
                // create new coroutine for AdjustSpeed
                StartCoroutine("AdjustSpeed");
            }
        }
    }
    So we've added an extra if statement that tests whether the pickup type is equal to 3 which will then adjust the speed via the AdjustSpeed() function. Go ahead and add the AdjustSpeed() function below to the script:
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    function AdjustSpeed()
    {
        // retrieve random number between 0 and 1
        var rand:float = Random.Range(0.0, 1.0);
         
        if (rand <= 0.6) // 60% for speed boost
        {
            characterMotor.movement.maxForwardSpeed = maxSpeed;
        }
        else // 40% for slow down
        {
            characterMotor.movement.maxForwardSpeed = minSpeed;
        }
         
        // wait for 5-10 seconds before resetting the speed to the original speed
        yield WaitForSeconds(Random.Range(5,10));
         
        characterMotor.movement.maxForwardSpeed = originalSpeed;
    }
    The AdjustSpeed() function generates a random number, which is then used to decide whether to speed up or slow down the player. The function then waits for a time between 5 and 10 seconds before re-assigning the original speed. If you now play the game this should all appear to work correctly.
    There is a problem, however.
    If you collect a type 3 pickup and then collect another type 3 pickup before the original speed has been reset, then the function is still waiting and so the original speed will be reset far earlier than expected.
    The approach we're going with use to solve this issue is by using StartCoroutine(...), passing the function name as the parameter, so we can later use StopCoroutine(...)which will remove the yield WaitForSeconds(...) statement within the function.
    Replace the call to AdjustSpeed() within the if statement with the following code:
    1
    2
    3
    4
    5
    // stop any coroutines already running
    StopCoroutine("AdjustSpeed");
     
    // create new coroutine for AdjustSpeed
    StartCoroutine("AdjustSpeed");
    Now when you run the game it should function as expected if you can find two type 3 pickups in quick succession (if you've copied the above exactly they should be blue).
    Creating a countdown timer within Unity is pretty simple! Create a new script called 'CountdownTimer' and add the following variables and Awake() function:
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    16
    17
    18
    // the textfield to update the time to
    private var textfield:GUIText;
     
    // time variables
    public var allowedTime:int = 90;
    private var currentTime = allowedTime;
     
     
    function Awake()
    {
        // retrieve the GUIText Component and set the text
        textfield = GetComponent(GUIText);
         
        UpdateTimerText();
         
        // start the timer ticking
        TimerTick();
    }
    All pretty simple so far; we've declared a few variables and when the script initializes we're assigning the GUIText Component of the GameObject that the script is a Component of to the textfield variable.
    We then make two function calls to UpdateTimerText() and TimerTick(). Let's start by adding the UpdateTimerText() function below to our script:
    1
    2
    3
    4
    5
    function UpdateTimerText()
    {
        // update the textfield
        textfield.text = currentTime.ToString();
    }
    This is also pretty simple, converting the currentTime variable into a string and then updating the textfield with that string. Let's now add the timer functionality to our script with the TimerTick() function below:
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    16
    17
    function TimerTick()
    {
        // while there are seconds left
        while(currentTime > 0)
        {
            // wait for 1 second
            yield WaitForSeconds(1);
             
            // reduce the time
            currentTime--;
             
            UpdateTimerText();
        }
         
        // game over
         
    }
    So there's a little more going on in this function but it's still pretty simple; let's take a look...
    We have a while loop which keeps looping until the seconds counter equals 0 - i.e. the game has ended. Within the loop we use the yield WaitForSeconds(...)statement to stop the script executing for 1 second. When the script begins executing again, the currentTime variable is reduced by 1 and the textfield is updated by calling UpdateTimerText().
    Since it's a while loop, this flow is repeated until the currentTime equals 0, at which point the game is over and 'Game Over' is printed out to the console.
    There is one final thing you need to do to make this work - and that is, of course, adding the CountdownTimer script as a Component of the 'txt-time' GameObject, since otherwise it's just an unused script in a folder!
    Now run the game. The clock should tick down from 90 and stop at 0. (You will however be able to still run around afterwards but we'll remedy that in the next tutorial.)
    unity tutorial: gui, timers, particles
    Hopefully you've enjoyed this latest Getting Started with Unity tutorial! We've covered GUITextures, GUIText, creating countdown timers and everyones favourite - Particles! In the next and final part of this series, we'll add an intro and ending screen for our game. See you there!

    icon allbkg

    Tagged with:

    Next
    Newer Post
    Previous
    Older Post

    No comments:

Comments

The Visitors says
Download Free Software Latest Version