Displaying Inventory

Checked with version: 5.5

-

Difficulty: Beginner

In this second session we will continue to learn how to program a text based adventure game in C# by adding items which can be examined, taken and used, along with a very simple inventory system. In this episode we will add the ability for the player to display the items they have taken into their inventory.

Displaying Inventory

Beginner Scripting

Download the assets for this training here

InteractableObject

Code snippet

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu (menuName = "TextAdventure/Interactable Object")]
public class InteractableObject : ScriptableObject 
{
    public string noun = "name";
    [TextArea]
    public string description = "Description in room";
    public Interaction[] interactions;

}

Interaction

Code snippet

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[System.Serializable]
public class Interaction 
{
    public InputAction inputAction;
    [TextArea]
    public string textResponse;
    public ActionResponse actionResponse;
}

InteractableItems

Code snippet

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class InteractableItems : MonoBehaviour 
{
    public List<InteractableObject> usableItemList;

    public Dictionary<string, string> examineDictionary = new Dictionary<string, string> ();
    public Dictionary<string, string> takeDictionary = new Dictionary<string, string> ();

    [HideInInspector] public List<string> nounsInRoom = new List<string>();

    Dictionary <string, ActionResponse> useDictionary = new Dictionary<string, ActionResponse> ();
    List<string> nounsInInventory = new List<string>();
    GameController controller;

    void Awake()
    {
        controller = GetComponent<GameController> ();
    }

    public string GetObjectsNotInInventory(Room currentRoom, int i)
    {
        InteractableObject interactableInRoom = currentRoom.interactableObjectsInRoom [i];

        if (!nounsInInventory.Contains (interactableInRoom.noun)) 
        {
            nounsInRoom.Add (interactableInRoom.noun);
            return interactableInRoom.description;
        }

        return null;
    }

    public void AddActionResponsesToUseDictionary()
    {
        for (int i = 0; i < nounsInInventory.Count; i++) 
        {
            string noun = nounsInInventory [i];

            InteractableObject interactableObjectInInventory = GetInteractableObjectFromUsableList (noun);
            if (interactableObjectInInventory == null)
                continue;

            for (int j = 0; j < interactableObjectInInventory.interactions.Length; j++) 
            {
                Interaction interaction = interactableObjectInInventory.interactions [j];

                if (interaction.actionResponse == null)
                    continue;

                if (!useDictionary.ContainsKey (noun)) 
                {
                    useDictionary.Add (noun, interaction.actionResponse);
                }
            }

        }
    }

    InteractableObject GetInteractableObjectFromUsableList(string noun)
    {
        for (int i = 0; i < usableItemList.Count; i++) 
        {
            if (usableItemList [i].noun == noun) 
            {
                return usableItemList [i];
            }
        }
        return null;
    }

    public void DisplayInventory()
    {
        controller.LogStringWithReturn ("You look in your backpack, inside you have: ");

        for (int i = 0; i < nounsInInventory.Count; i++) 
        {
            controller.LogStringWithReturn (nounsInInventory [i]);  
        }
    }

    public void ClearCollections()
    {
        examineDictionary.Clear();
        takeDictionary.Clear ();
        nounsInRoom.Clear();
    }

    public Dictionary<string, string> Take (string[] separatedInputWords)
    {
        string noun = separatedInputWords [1];

        if (nounsInRoom.Contains (noun)) {
            nounsInInventory.Add (noun);
            AddActionResponsesToUseDictionary ();
            nounsInRoom.Remove (noun);
            return takeDictionary;
        } 
        else 
        {
            controller.LogStringWithReturn ("There is no " + noun + " here to take.");
            return null;
        }
    }

    public void UseItem(string[] separatedInputWords)
    {
        string nounToUse = separatedInputWords [1];

        if (nounsInInventory.Contains (nounToUse)) {
            if (useDictionary.ContainsKey (nounToUse)) {
                bool actionResult = useDictionary [nounToUse].DoActionResponse (controller);
                if (!actionResult) {
                    controller.LogStringWithReturn ("Hmm. Nothing happens.");
                }
            } else {
                controller.LogStringWithReturn ("You can't use the " + nounToUse);
            }
        } else 
        {
            controller.LogStringWithReturn ("There is no " + nounToUse + " in your inventory to use");
        }
    }

}

Room

Code snippet

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(menuName = "TextAdventure/Room")]
public class Room : ScriptableObject 
{
    [TextArea]
    public string description;
    public string roomName;
    public Exit[] exits;
    public InteractableObject[] interactableObjectsInRoom;

}

GameController

Code snippet

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class GameController : MonoBehaviour {

    public Text displayText;
    public InputAction[] inputActions;

    [HideInInspector] public RoomNavigation roomNavigation;
    [HideInInspector] public List<string> interactionDescriptionsInRoom = new List<string> ();
    [HideInInspector] public InteractableItems interactableItems;

    List<string> actionLog = new List<string>();


    // Use this for initialization
    void Awake () 
    {
        interactableItems = GetComponent<InteractableItems> ();
        roomNavigation = GetComponent<RoomNavigation> (); 
    }

    void Start()
    {
        DisplayRoomText ();
        DisplayLoggedText ();
    }

    public void DisplayLoggedText()
    {
        string logAsText = string.Join ("\n", actionLog.ToArray ());

        displayText.text = logAsText;
    }

    public void DisplayRoomText()
    {
        ClearCollectionsForNewRoom ();

        UnpackRoom ();

        string joinedInteractionDescriptions = string.Join ("\n", interactionDescriptionsInRoom.ToArray ());

        string combinedText = roomNavigation.currentRoom.description + "\n" + joinedInteractionDescriptions;

        LogStringWithReturn (combinedText);
    }

    void UnpackRoom()
    {
        roomNavigation.UnpackExitsInRoom ();
        PrepareObjectsToTakeOrExamine (roomNavigation.currentRoom);
    }

    void PrepareObjectsToTakeOrExamine(Room currentRoom)
    {
        for (int i = 0; i < currentRoom.interactableObjectsInRoom.Length; i++) 
        {
            string descriptionNotInInventory = interactableItems.GetObjectsNotInInventory (currentRoom, i);
            if (descriptionNotInInventory != null) 
            {
                interactionDescriptionsInRoom.Add (descriptionNotInInventory);
            }

            InteractableObject interactableInRoom = currentRoom.interactableObjectsInRoom [i];

            for (int j = 0; j < interactableInRoom.interactions.Length; j++) 
            {
                Interaction interaction = interactableInRoom.interactions [j];
                if (interaction.inputAction.keyWord == "examine") 
                {
                    interactableItems.examineDictionary.Add (interactableInRoom.noun, interaction.textResponse);
                }

                if (interaction.inputAction.keyWord == "take") 
                {
                    interactableItems.takeDictionary.Add (interactableInRoom.noun, interaction.textResponse);
                }
            }
        }
    }

    public string TestVerbDictionaryWithNoun(Dictionary<string, string> verbDictionary, string verb, string noun)
    {
        if (verbDictionary.ContainsKey (noun)) 
        {
            return verbDictionary [noun];
        }

        return "You can't " + verb + " " + noun;
    }

    void ClearCollectionsForNewRoom()
    {
        interactableItems.ClearCollections ();
        interactionDescriptionsInRoom.Clear ();
        roomNavigation.ClearExits ();
    }

    public void LogStringWithReturn(string stringToAdd)
    {
        actionLog.Add (stringToAdd + "\n");
    }
}

InputAction

Code snippet

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public abstract class InputAction : ScriptableObject 
{
    public string keyWord;

    public abstract void RespondToInput (GameController controller, string[] separatedInputWords);
}

Examine

Code snippet

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(menuName = "TextAdventure/InputActions/Examine")]
public class Examine : InputAction 
{
    public override void RespondToInput (GameController controller, string[] separatedInputWords)
    {
        controller.LogStringWithReturn (controller.TestVerbDictionaryWithNoun (controller.interactableItems.examineDictionary, separatedInputWords [0], separatedInputWords [1]));
    }
}

Take

Code snippet

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(menuName = "TextAdventure/InputActions/Take")]
public class Take : InputAction 
{
    public override void RespondToInput (GameController controller, string[] separatedInputWords)
    {
        Dictionary<string, string> takeDictionary = controller.interactableItems.Take (separatedInputWords);

        if (takeDictionary != null) 
        {
            controller.LogStringWithReturn (controller.TestVerbDictionaryWithNoun (takeDictionary, separatedInputWords [0], separatedInputWords [1]));
        }
    }
}

Inventory

Code snippet

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(menuName = "TextAdventure/InputActions/Inventory")]
public class Inventory : InputAction 
{
    public override void RespondToInput (GameController controller, string[] separatedInputWords)
    {
        controller.interactableItems.DisplayInventory ();
    }
}

ActionResponse

Code snippet

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public abstract class ActionResponse : ScriptableObject 
{
    public string requiredString;

    public abstract bool DoActionResponse(GameController controller);

}

ChangeRoomResponse

Code snippet

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(menuName = "TextAdventure/ActionResponses/ChangeRoom")]
public class ChangeRoomResponse : ActionResponse 
{
    public Room roomToChangeTo;

    public override bool DoActionResponse (GameController controller)
    {
        if (controller.roomNavigation.currentRoom.roomName == requiredString) 
        {
            controller.roomNavigation.currentRoom = roomToChangeTo;
            controller.DisplayRoomText ();
            return true;
        }

        return false;
    }
}

Use

Code snippet

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu (menuName = "TextAdventure/InputActions/Use")]
public class Use : InputAction 
{
    public override void RespondToInput (GameController controller, string[] separatedInputWords)
    {
        controller.interactableItems.UseItem (separatedInputWords);
    }
}

Scripting

  1. Scripts as Behaviour Components
  2. Variables and Functions
  3. Conventions and Syntax
  4. C# vs JS syntax
  5. IF Statements
  6. Loops
  7. Scope and Access Modifiers
  8. Awake and Start
  9. Update and FixedUpdate
  10. Vector Maths
  11. Enabling and Disabling Components
  12. Activating GameObjects
  13. Translate and Rotate
  14. Look At
  15. Linear Interpolation
  16. Destroy
  17. GetButton and GetKey
  18. GetAxis
  19. OnMouseDown
  20. GetComponent
  21. Delta Time
  22. Data Types
  23. Classes
  24. Instantiate
  25. Arrays
  26. Invoke
  27. Enumerations
  28. Switch Statements
  1. Properties
  2. Ternary Operator
  3. Statics
  4. Method Overloading
  5. Generics
  6. Inheritance
  7. Polymorphism
  8. Member Hiding
  9. Overriding
  10. Interfaces
  11. Extension Methods
  12. Namespaces
  13. Lists and Dictionaries
  14. Coroutines
  15. Quaternions
  16. Delegates
  17. Attributes
  18. Events
  1. Building a Custom Inspector
  2. The DrawDefaultInspector Function
  3. Adding Buttons to a Custom Inspector
  4. Unity Editor Extensions – Menu Items
  1. Simple Clock
  2. MonoDevelop's Debugger
  3. Unity Editor Extensions – Menu Items
  4. Creating Meshes
  1. AssetBundles and the AssetBundle Manager
  2. Mastering Unity Project Folder Structure - Version Control Systems
  1. Installing Tools for Unity Development
  2. Building your first Unity Game with Visual Studio
  3. Editing Unity games in Visual Studio
  4. Debugging Unity games in Visual Studio
  5. Graphics debugging Unity games in Visual Studio
  6. Taking Unity games to Universal Windows Platform
  7. Testing Unity games on Android in Visual Studio
  1. Scripting Primer and Q&A
  2. Scripting Primer and Q&A - Continued
  3. Scripting Primer and Q&A - Continued (Again)
  4. Persistence - Saving and Loading Data
  5. Object Pooling
  6. Introduction to Scriptable Objects
  7. How to communicate between Scripts and GameObjects
  8. Coding in Unity for the Absolute Beginner
  9. Sound Effects & Scripting
  10. Editor Scripting Intro
  11. Writing Plugins
  12. Property Drawers & Custom Inspectors
  13. Events: Creating a simple messaging system
  14. Ability System with Scriptable Objects
  15. Character Select System with Scriptable Objects
  16. Creating Basic Editor Tools
  1. Intro and Setup
  2. Data Classes
  3. Menu Screen
  4. Game UI
  5. Answer Button
  6. Displaying Questions
  7. Click To Answer
  8. Ending The Game and Q&A
  1. Intro To Part Two
  2. High Score with PlayerPrefs
  3. Serialization and Game Data
  4. Loading Game Data via JSON
  5. Loading and Saving via Editor Script
  6. Game Data Editor GUI
  7. Question and Answer
  1. Overview and Goals
  2. Localization Data
  3. Dictionary, JSON and Streaming Assets
  4. Localization Manager
  5. Startup Manager
  6. Localized Text Component
  7. Localized Text Editor Script
  8. Localization Q&A
  1. Introduction and Session Goals
  2. Particle Launcher
  3. Particle Collisions
  4. ParticleLauncher Script
  5. Particle Collisions and Scripting
  6. Random Particle Colors
  7. Drawing Decals with Particles
  8. Collecting Particle Information For Display
  9. Displaying Particles Via Script
  10. Droplet Decals
  11. Questions and Answers
  1. Introduction and Goals
  2. Project Architecture Overview
  3. Creating Rooms
  4. Creating Exits
  5. Text Input
  6. Reacting To String Input
  7. Input Actions And The Delegate Pattern
  8. Questions and Answers
  1. Introduction and Goals
  2. Project Architecture and Review
  3. Displaying Item Descriptions
  4. Examining Items
  5. Taking Items
  6. Displaying Inventory
  7. Action Responses
  8. Preparing The Use Item Dictionary
  9. Creating The Use Action
  10. Questions and Answers