Celebrations and fireworks!
The coin collection game is nearly finished. Coins can be collected and a timer expires, but the win condition itself is not truly handled. That is, when all coins are collected before time expiry, nothing actually happens to show the player that they've won. The countdown still proceeds and even restarts the level as though the win condition hadn't been satisfied at all. Let's fix this now. Specifically, when the win scenario happens, we should delete the timer object to prevent further countdown and show visual feedback to signify that the level has been completed. In this case, I'll add some fireworks! So, let's start by creating the fireworks. You can add these easily from the Unity Particle System packages. Navigate to the Standard Assets | ParticleSystems | Prefabs folder. Then, drag and drop the Fireworks particle system in Scene.
Add a second or even a third one if you want:
By default, all firework particle systems will play when the level begins. You can test this by pressing play on the toolbar. This is not the behavior that we want. We only want the fireworks to play when the win condition has been satisfied. To disable playback on level startup, select the Particle System object in the Scene and, from the Object Inspector, disable the Play On Awake checkbox, which can be found in the Particle System component.
See Figure 2.30, Disabling Play On Awake:
Disabling Play On Awake prevents particle systems playing automatically at level startup. This is fine, but if they are ever to play at all, something must manually start them at the right time. We can achieve this through code. Before resorting to a coding solution, however, we'll first mark all firework objects with an appropriate tag. The reason for this is that, in code, we'll want to search for all firework objects in the scene and trigger them to play when needed. To isolate the firework objects from all other objects, we'll use tags. So, let's create a new Fireworks tag and assign them to the firework objects only in the Scene.
Tags were created earlier in this chapter when configuring the player character for coin collisions. See Figure 2.31:
With the firework objects now tagged, we can refine the Coin.cs script class to handle a win condition for the scene, as shown in Code Sample 2.7. Comments follow:
//------------------------- using UnityEngine; using System.Collections; //------------------------- public class Coin : MonoBehaviour { //------------------------- public static int CoinCount = 0; //------------------------- // Use this for initialization void Awake () { //Object created, increment coin count ++Coin.CoinCount; } //------------------------- void OnTriggerEnter(Collider Col) { //If player collected coin, then destroy object if(Col.CompareTag("Player")) Destroy(gameObject); } //------------------------- void OnDestroy() { --Coin.CoinCount; //Check remaining coins if(Coin.CoinCount <= 0) { //Game is won. Collected all coins //Destroy Timer and launch fireworks GameObject Timer = GameObject.Find("LevelTimer"); Destroy(Timer); GameObject[] FireworkSystems = GameObject.FindGameObjectsWithTag("Fireworks"); foreach(GameObject GO in FireworkSystems) GO.GetComponent<ParticleSystem>().Play(); } } //------------------------- } //-------------------------
Code Sample 2.7
The following points summarize the code sample:
- The
OnDestroy
function is critical. It occurs when a coin is collected and features an if statement to determine when all coins are collected (the win scenario). - When a win scenario happens, the GameObject.Find function is called to search the complete scene hierarchy for any active object named LevelTimer. If found, the object is deleted. This happens to delete the timer and prevent any further countdown when the level is won. If the scene contains multiple objects of a matching name, then only the first object is returned. This is one reason why the scene should contain one and only one timer.
Note
Avoid using the
GameObject.Find
function wherever possible. It's slow for performance. Instead, useFindGameObjectsWithTag
. It's been used here only to demonstrate its existence and purpose. Sometimes, you'll need to use it to find a single, miscellaneous object that has no specific tag. - In addition to deleting the LevelTimer object, the OnDestroy function finds all firework objects in the scene and initiates them. It finds all objects of a matching tag using the GameObject.
FindGameObjectsWithTag
function. This function returns an array of all objects with the Fireworks tag and the ParticleSystem is initiated for each object by calling the Play function.Note
As mentioned, each
GameObject
in Unity is really made from a collection of attached and related components. An object is the sum of its components. For example, a standard cube (created using GameObject | 3D Object | Cube) is made from a Transform component, Mesh Filter component, Mesh Renderer component, andBox Collider
component. These components together make the cube what it is and behave how it does.The
GetComponent
function can be called in script to retrieve a reference to any specified component, giving you direct access to its public properties. TheOnDestroy
function in the preceding code usesGetComponent
to retrieve a reference to theParticleSystem
component attached to the object.GetComponent
is a highly useful and important function. More information onGetComponent
can be found at the online Unity documentation at http://docs.unity3d.com/ScriptReference/GameObject.GetComponent.html.