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;
}
}