Displaying multiple pickups of different objects as text totals via a dynamic Dictionary<> of PickUp objects and "enum" pickup types

While the previous recipe worked fine, any old text might have been typed into the description for a pickup or perhaps mistyped (star, Sstar, starr, and so on). A much better way of restricting game properties to one of a predefined (enumerated) list of possible values is to use C# enums. As well as removing the chance of mistyping a string, it also means that we can write code to appropriately deal with the predefined set of possible values. In this recipe, we will improve our general purpose PickUp class by introducing three possible pickup types (Star, Heart, and Key), and write inventory display code that counts the number of each type of pickup being carried and displays these totals via a UI Text object on screen. We also switch from using a List to using a Dictionary, since the Dictionary data structure is designed specifically for key-value pairs, perfect for associating a numeric total with an enumerated pickup type.

Displaying multiple pickups of different objects as text totals via a dynamic Dictionary<> of PickUp objects and "enum" pickup types

Getting ready

This recipe follows on from the previous recipe in this chapter.

How to do it...

To display multiple pickups of different objects as text totals via a dynamic Dictionary, follow these steps:

  1. Make a copy of your work for the previous recipe.
  2. Replace the content of script class PickUp with the following code:
    using UnityEngine;
    using System.Collections;
    
    public class PickUp : MonoBehaviour {
      public enum PickUpType {
        Star, Key, Heart
      }
    
      public PickUpType type;
    }
  3. Replace the content of script class Player with the following code:
    using UnityEngine;
    using System.Collections;
    using UnityEngine.UI;
    using System.Collections.Generic;
    
    public class Player : MonoBehaviour {
      private InventoryManager inventoryManager;
    
      void Start(){
        inventoryManager = GetComponent<InventoryManager>();
      }
      
      void OnTriggerEnter2D(Collider2D hit){
        if(hit.CompareTag("Pickup")){
          PickUp item = hit.GetComponent<PickUp>();
          inventoryManager.Add( item );
          Destroy(hit.gameObject);
        }
      }
    }
  4. Replace the content of script class PlayerInventoryDisplay with the following code:
    using UnityEngine;
    using System.Collections;
    using UnityEngine.UI;
    using System.Collections.Generic;
    
    public class PlayerInventoryDisplay : MonoBehaviour {
      public Text inventoryText;
      private string newInventoryText;
      
      public void OnChangeInventory(Dictionary<PickUp.PickUpType, int> inventory){
        inventoryText.text = "";
        
        newInventoryText = "carrying: ";
        int numItems = inventory.Count;
    
        foreach(var item in inventory){
          int itemTotal = item.Value;
          string description = item.Key.ToString();
          newInventoryText += " [ " + description + " " + itemTotal +  " ]";
        }
        
        if(numItems < 1) newInventoryText = "(empty inventory)";
        
        inventoryText.text = newInventoryText;
      }
    }
  5. Add the following C# Script InventoryManager to the GameObject player-SpaceGirl in the Hierarchy:
    using UnityEngine;
    using System.Collections;
    using System.Collections.Generic;
    
    public class InventoryManager : MonoBehaviour {
      private PlayerInventoryDisplay playerInventoryDisplay;
      private Dictionary<PickUp.PickUpType, int> items = new Dictionary<PickUp.PickUpType, int>();
      
      void Start(){
        playerInventoryDisplay = GetComponent<PlayerInventoryDisplay>();
        playerInventoryDisplay.OnChangeInventory(items);
      }
      
      public void Add(PickUp pickup){
        PickUp.PickUpType type = pickup.type;
        int oldTotal = 0;
        if(items.TryGetValue(type, out oldTotal))
          items[type] = oldTotal + 1;
        else
          items.Add (type, 1);
        
        playerInventoryDisplay.OnChangeInventory(items);
      }
    }
  6. In the Hierarchy (or Scene) panel, select each pickup GameObject in turn, and choose from the drop-down menu its corresponding Type in the Inspector panel. As you can see, public variables that are of an enum type are automatically restricted to the set of possible values as a combo-box drop-down menu in the Inspector panel.
    How to do it...
  7. Play the game. First, you should see a message on screen stating the inventory is empty, and then as you pick up one or more items of each pickup type, you'll see text totals of each type you have collected.

How it works...

Each pickup GameObject in the scene has a scripted component of class PickUp. The PickUp object for each Pickup GameObject has a single property, a pickup type, which has to be one of the enumerated set of Star, Key, Heart. The Player script class gets a reference to the InventoryManager component via its Start() method, and each time the player's character collides with a pickup GameObject, it calls the Add(…) method of the inventory manager, passing the PickUp object of the object collided with.

In this recipe, the inventory being carried by the player is being represented by a C# Dictionary. In this case, we have in script class InventoryManager a dictionary of key-value pairs, where the key is one of the possible PickUp.PickUpType enumerated values, and the value is an integer total of how many of that type of pickup is being carried. Each InventoryItemTotal object has just two properties: a PickUp type and an integer total. This extra layer of the InventoryManager has been added between script class Player and PlayerInventoryDisplay to both separate the Player behavior from how the inventory is internally stored and to prevent the Player script class from becoming too large and attempting to handle too many different responsibilities.

C# dictionaries provide a TryGetValue(…) method, which receives parameters of a key and is passed a reference to a variable the same data type as the value for the Dictionary. When the Add(…) method of the inventory manager is called, the type of the PickUp object is tested to see if a total for this type is already in Dictionary items. If an item total is found inside the Dictionary for the given type, then the value for this item in the Dictionary is incremented. If no entry is found for the given type, then a new element is added to the Dictionary with a total of 1.

The last action of the Add(…) method is to call the OnChangeInventory(…) method of the PlayerInventoryDisplay scripted component of the player's GameObject to update the text totals displayed on screen. This method in PlayerInventoryDisplay iterates through the Dictionary, building up a string of the type names and totals, and then updates the text property of the UI Text object with the string showing the inventory totals to the player.

Learn more about using C# lists and dictionaries in Unity in the Unity Technologies tutorial at https://unity3d.com/learn/tutorials/modules/intermediate/scripting/lists-and-dictionaries.

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

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