I fixed the out of bounds errors and added an inventory system

In case anyone is interested, I added some logic to the conditional statements that handle player input to avoid the out of bounds array error.

I also added an inventory system because i wanted to have the option for the player to pick up items that didnt force me to make entirely different story paths depending on the item. I wanted to build the story so whatever item you pick up doesnt change what state you move to and you can then use the items somewhere down the line. I haven’t actually built much of my story yet so i dunno how I’m gunna use the items in context yet but i figured id share my work.

The first section is the AdventureGame.cs file and the second one is the State.cs file.

 public class AdventureGame : MonoBehaviour
{

    [SerializeField] Text textComponent;
    [SerializeField] State startingState;

    State state;
    State previousState; //initializing the previousState variable to store for inventory system use

    List inventory = new List(); //here we intialize a list of strings to store the inventory items in

    // Start is called before the first frame update
    void Start()
    {
        state = startingState;
        previousState = state; //this is so we can return to the state we left to check the inventory

        textComponent.text = state.GetStoryState();

        //here are the default starting inventory options
        inventory.Add(" a bit of string ");
        inventory.Add(" a piece of cheese ");

    }

    // Update is called once per frame
    void Update()
    {
        ManageState();
        AddItem(); 
    }

    private string CheckInventory()
    {
        //we create a string out of the list of strings and return it with instructions for exiting the inventory

            string all_items = string.Join(" ", inventory);
            string inventoryText = all_items + "                                                         press escape to exit inventory";
            return inventoryText;
    }

    private List AddItem()
    {   
        // here we check if the state has an item to add and if its not already in the inventory we add it
        var item = state.AddItem();
        if (!inventory.Contains(item))
        {
            inventory.Add(item);
        }
        return inventory;
    }

    private void ManageState()
    {
        var nextStates = state.GetNextState();
        int stateCount = nextStates.GetLength(0); //we check how many nextstates are available and store them in this variable


        // this section handles player input
        // all of the buttons that move the story forward check to make sure the nextStates[position] isnt out of bounds
        // i made my inventory defaul nextStates[0] for all states 
        //so below, if you press 1 and its also true that the statecount is greater than or equal to 2, i.e. position 0 = inventory and position 1 = next story state 
        //then if resolves to true
        //we just increase the number statecount must be greater than or equal to for every additional option
        //theres prolly a better way to loop and iterate this buuuuuut im gunna move on

        if ((Input.GetKeyDown(KeyCode.Alpha1)) && ((stateCount >= 2))) 
        {

            state = nextStates[1];
            textComponent.text = state.GetStoryState(); //i had to change the position of this state update
        }
        else if ((Input.GetKeyDown(KeyCode.Alpha2)) && ((stateCount >= 3)))
        {

            state = nextStates[2];
            textComponent.text = state.GetStoryState(); //it was originally outside of this whole set of conditionals for player input
        }
        else if ((Input.GetKeyDown(KeyCode.Alpha3)) && (stateCount == 4))
        {

            state = nextStates[3];
            textComponent.text = state.GetStoryState(); //but that made the inventory appear for a single frame, and then stop showing up
        }
        else if ((Input.GetKeyDown(KeyCode.Return)) && (stateCount == 2)) 
        {

            state = nextStates[1];
            textComponent.text = state.GetStoryState();
        }
        else if (Input.GetKeyDown(KeyCode.Space)) //this is to enter inventory. I made it the default nextStates[0] position of all my states so its always available
        {
            previousState = state; //saves previous state to return to from inventory
            var inventorytext = CheckInventory(); //captured from checkinventory()'s output
            textComponent.text = inventorytext; //change the text to display
            state = nextStates[0];
        }
        else if (Input.GetKeyDown(KeyCode.Escape) && (textComponent.text != state.GetStoryState()))  //second condition to ensure we only can go back from inventory
        {
            state = previousState; //return to story
            textComponent.text = state.GetStoryState(); 
        }

space


[CreateAssetMenu(menuName = "State")]
public class State : ScriptableObject
{

    [TextArea(10,14)][SerializeField] string storyText;
    [SerializeField] string item; //here i add a field so that a state can have an item to be picked up
    [SerializeField] State[] nextStates;

    public string GetStoryState()
    {
        return storyText;
    }
    public string AddItem() //here we return item so its availble in AdventureGame
    {
        return item;
    }

    public State[] GetNextState()
    {
        return nextStates;

    }

}
3 Likes

Incredible job for figuring it out and thank your for posting this so others and can learn from it. Keep up the great work!

Hi Blunder, thanks for the inventory implementation! I would like to point out a small bug in the code, specifically the else if block for entering the inventory state. As the code is currently, if the space bar is pressed twice consecutively, the previousState var will overwrite the saved state with another copy of the inventory state.

To fix this, I would recommend changing your else if block to the following:

else if ((Input.GetKeyDown(KeyCode.Space) && textComponent.text != CheckInventory())){
            ...
        }

Privacy & Terms