Unity 2018 By Example(Second Edition)
上QQ阅读APP看书,第一时间看更新

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:

Celebrations and fireworks!

Figure 2.29: Adding two Fireworks prefabs

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:

Celebrations and fireworks!

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:

Celebrations and fireworks!

Figure 2.31: Tagging firework objects

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, use FindGameObjectsWithTag. 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, and Box 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. The OnDestroy function in the preceding code uses GetComponent to retrieve a reference to the ParticleSystem component attached to the object. GetComponent is a highly useful and important function. More information on GetComponent can be found at the online Unity documentation at http://docs.unity3d.com/ScriptReference/GameObject.GetComponent.html.