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;

    }

}
1 Like

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