Displaying single object pickups with carrying and not-carrying text

Often the simplest inventory situation is to display text to tell players if they are carrying a single item (or not).

Getting ready

This recipe assumes that you are starting with the project Simple2Dgame_SpaceGirl setup from the first recipe in this chapter. So, either make a copy of that project or do the following:

  1. Create a new, empty 2D project.
  2. Import the Simple2Dgame_SpaceGirl package.
  3. Open scene Scene1 (in the Scenes folder).
  4. Set the Unity Player screen size to 800 x 600 (see the previous recipe for how to do this) and select this resolution in the Game panel the drop-down menu.
  5. Convert each sprite image to be of type Sprite (2D and UI). In the Inspector, choose Sprite (2D and UI) from drop-down menu Texture Type, and click on the Apply button.

For this recipe, we have prepared the font you need in a folder named Fonts in the 1362_02_02 folder.

How to do it...

To display text to inform the user about the status of carrying a single object pickup, follow these steps:

  1. Start with a new copy of mini-game Simple2Dgame_SpaceGirl.
  2. Add a UI Text object (Create | UI | Text). Rename it Text-carrying-star. Change its text to Carrying star: false.
  3. Import the provided Fonts folder into your project.
  4. In the Inspector panel, set the font of Text-carrying-star to Xolonium-Bold (folder Fonts), and set its color to yellow. Center the text horizontally and vertically, and set its Height to 50, and set the Font Size to 32, as shown in the following screenshot:
    How to do it...
  5. In its Rect Transform component, set its Height to 50, as shown in the next screenshot:
    How to do it...
  6. Edit its Rect Transform, and while holding down SHIFT and ALT (to set pivot and position), choose the top-stretch box, as shown in the following screenshot:
    How to do it...
  7. Your text should now be positioned at the middle top of the Game panel, and its width should stretch to match that of the whole panel, as shown in the next screenshot:
    How to do it...
  8. Add the following C# Script Player to GameObject player-SpaceGirl in the Hierarchy:
    using UnityEngine;
    using System.Collections;
    using UnityEngine.UI;
    
    public class Player : MonoBehaviour {
      public Text starText;
      private bool carryingStar = false;
    
      void Start(){
        UpdateStarText();
      }
    
      void OnTriggerEnter2D(Collider2D hit){
        if(hit.CompareTag("Star")){
          carryingStar = true;
          UpdateStarText();
          Destroy(hit.gameObject);
        }
      }
    
      private void UpdateStarText(){
        string starMessage = "no star :-(";
        if(carryingStar) starMessage = "Carrying star :-)";
        starText.text = starMessage;
      }
    }
  9. From the Hierarchy view, select the GameObject player-SpaceGirl. Then, from the Inspector, access the Player (Script) component and populate the Star Text public field with UI Text object Text-carrying-star, as shown in the following screenshot:
    How to do it...
  10. When you play the scene, after moving the character into the star, the star should disappear, and the onscreen UI Text message should change to Carrying star :-) , as shown in the following screenshot:
    How to do it...

How it works...

The Text variable starText is a reference to the UI Text object Text-carrying-star. The bool variable carryingStar represents whether or not the player is carrying the star at any point in time; it is initialized to false.

The UpdateStarText() method copies the contents of the starMessage string to the text property of starText. The default value of this string tells the user that the player is not carrying the star, but an if statement tests the value of carryingKey, and, if that is true, then the message is changed to inform the player that they are carrying the star.

Each time the player's character collides with any object that has its Is Trigger set to true, an OnTriggerEnter2D() event message is sent to both objects involved in the collision. The OnTriggerEnter2D() message is passed a parameter that is the Collider2D component inside the object just collided with.

Our player's OnTriggerEnter2D() method tests the tag string of the object collided with to see if it has the value Star. Since the GameObject star we created has its trigger set, and has the tag Star, the if statement inside this method will detect a collision with star and complete three actions: it sets the Boolean variable carryingStar to true, it calls the method UpdateStarText(), and it destroys the GameObject it has just collided with (in this case, star).

Note

NOTE: Boolean variables are often referred to as flags.

The use of a bool (true/false) variable to represent whether some feature of the game state is true or false is very common. Programmers often refer to these variables as flags. So, programmers might refer to the carryingStar variable as the star-carrying flag.

When the scene begins, via the Start()method, we call the UpdateStarText()method; this ensures that we are not relying on text typed into the UI Text object Text-carrying-star at design time, but that the UI seen by the user is always set by our run-time methods. This avoids problems where the words to be displayed to the user are changed in code and not in the Inspector panel—which leads to a mismatch between the onscreen text when the scene first runs and after it has been updated from a script.

Note

A golden rule in Unity game design is to avoid duplicating content in more than one place, and, therefore, we avoid having to maintain two or more copies of the same content. Each duplicate is an opportunity for maintenance issues when some, but not all, copies of a value are changed.

Maximizing use of prefabs is another example of this principle in action. This is also know as the DRY principal - Do Not Repeat Yourself.

There's more...

Some details you don't want to miss:

The separation of view logic

A game design pattern (best practice approach) called the Model-View-Controller pattern (MVC) is to separate the code that updates the UI from the code that changes player and game variables such as score and inventory item lists. Although this recipe has only one variable and one method to update the UI, well structured game architectures scale up to cope with more complex games, so it is often worth the effort of a little more code and an extra script class, even at this game-beginning stage, if we want our final game architecture to be well structured and maintainable.

To implement the separation of view pattern for this recipe, we need to do the following:

  1. Add the following C# Script PlayerInventoryDisplay to GameObject player-SpaceGirl in the Hierarchy:
    using UnityEngine;
    using System.Collections;
    using UnityEngine.UI;
    
    public class PlayerInventoryDisplay : MonoBehaviour
    {
      public Text starText;
    
      public void OnChangeCarryingStar(bool carryingStar){
        string starMessage = "no star :-(";
        if(carryingStar) starMessage = "Carrying star :-)";
        starText.text = starMessage;
      }
    }
  2. From the Hierarchy view, select the GameObject player-SpaceGirl. Then, from the Inspector, access the PlayerInventoryDisplay (Script) component and populate the Score Text public field with the UI Text object Text-carrying-star.
  3. Remove the existing C# Script component Player and replace it with this C# Script PlayerInventory containing the following (simplified) code:
    using UnityEngine;
    using System.Collections;
    
    public class PlayerInventory : MonoBehaviour {
      private PlayerInventoryDisplay playerInventoryDisplay;
      private bool carryingStar = false;
    
      void Start(){
        playerInventoryDisplay = GetComponent<PlayerInventoryDisplay>();
      playerInventoryDisplay.OnChangeCarryingStar(carryingStar);
      }
    
      void OnTriggerEnter2D(Collider2D hit){
        if(hit.CompareTag("Star")){
          carryingStar = true;
      playerInventoryDisplay.OnChangeCarryingStar(carryingStar);
          Destroy(hit.gameObject);
        }
      }
    }

As can be seen, the PlayerInventory script class no longer has to maintain a link to the UI Text or worry about changing the text property of that UI component—all that work is now the responsibility of the PlayerInventoryDisplay script. When the Player instance component detects a collision with the star, after changing the carryingStar bool flag's value to true, it just calls the OnChangeCarryingStar()method of the PlayerInventoryDisplay component.

The result is that the code for the script class PlayerInventory concentrates on the player collision and status variables, while the code for the script class PlayerInventoryDisplay handles the communication to the user. Another advantage of this design pattern is that the method in which the information is communicated to the user via the UI can be changed (for example, from text to an icon), without any change to the code in script class Player.

Note

Note: There is no difference in the experience of the player, and all the changes are to improve the architectural structure of our game code.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.46.141