Hi all!
This is my first time trying to create a full, completed game with Unity. I’ve been following this tutorial on YT for creating a text-based game. I’m currently on the 2nd part, where we are creating items and a way for the system to recognize/store items. I created multiple scripts, and have been testing the game each time to make sure it runs properly. However I’ve finally received a glitch where the starting text (that loads when the starting room is loaded) is simply not displayed in the text area, and an error message that reads the following:
NullReferenceException: Object reference not set to an instance of an object
GameController.PrepareObjectsToTakeorExamine (Room currentRoom) (at Assets/Scripts/GameController.cs:79)
GameController.UnpackRoom () (at Assets/Scripts/GameController.cs:61)
GameController.DisplayRoomText () (at Assets/Scripts/GameController.cs:49)
GameController.Start () (at Assets/Scripts/GameController.cs:32)
Based on my professional level Google searches, I’m fairly certain that this means there’s an problem with the Game Controller object in the inspector. What confuses me even more however is that the game still runs–I can type the command to go into the next room, which then loads fine. I’ve attached the “GameController” script below, as well as the “Room” scriptable object script.
(Apologies for the notes, they’re what I’m using to keep track of everything that I’m doing!)
“Game Controller” Script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
//This last line is what allows the script to call upon functions in the Unity UI stuff
public class GameController : MonoBehaviour
{
public Text displayText;
public InputAction[] inputActions;
//this is what will show all the text on the screen
[HideInInspector] public RoomNavigation roomNavigation;
[HideInInspector] public List<string> interactionDescriptionsInRoom = new List<string>();
//this is the string of interactable objects (items, exits, etc) the player can interact with
//this will fill up depending on which room is called upon
[HideInInspector] public InteractableItems interactableItems;
List<string> actionLog = new List<string>();
//This list is what creates the action log, the ever-growing list of actions the player has taken.
//It is helpful to be a list bc we dont know how many actions a player can take
void Awake()
{
roomNavigation = GetComponent<RoomNavigation> ();
interactableItems = GetComponent<InteractableItems>();
}
void Start()
//This calls upon all the inserted functions every frame I think?
{
DisplayRoomText();
DisplayLoggedText();
}
public void DisplayLoggedText()
//This will display everything within the action log
{
string logAsText = string.Join("\n", actionLog.ToArray());
//this function takes the individual strings of actions and displays them as one combined string using the Array function
displayText.text = logAsText;
//this actually displays the text within the displayText function above!
}
public void DisplayRoomText()
{
ClearCollectionsForNewRoom();
UnpackRoom();
string joinedInteractionDescriptions = string.Join("\n", interactionDescriptionsInRoom.ToArray());
//converts the list of interaction exits, joins it into a string where everything is seperated into one line
string combinedText = roomNavigation.currentRoom.description + "\n" + joinedInteractionDescriptions;
LogStringWithReturn(combinedText);
}
void UnpackRoom()
{
roomNavigation.UnpackExitsInRoom ();
PrepareObjectsToTakeorExamine (roomNavigation.currentRoom);
}
private void PrepareObjectsToTakeorExamine(Room currentRoom)
{
for (int i = 0; i < currentRoom.interactableObjectsInRoom.Length; i++)
{
string descriptionNotInInventory = interactableItems.GetObjectNotInInventory(currentRoom, i);
//if the function succeeds and finds an item not in the inventory, it will store it in the string
if (descriptionNotInInventory !=null)
{
interactionDescriptionsInRoom.Add(descriptionNotInInventory);
}
InteractableObjects 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 you pass skull to the dic, you will get back interaction.text response
//we pass in the noun to the dictionary, it will check to see if it has a response, then give it back
//Here we unpack everything in the room, then unpack them into the dictionary
}
}
}
}
public string TestVerbDictionarywithNoun(Dictionary<string, string>verbDictionary, string verb, string noun)
{
if (verbDictionary.ContainsKey(noun))
//is it in the "take" dictionary?
{
return verbDictionary[noun];
//if so, we return the value tied to the called noun
}
return "You can't " + verb + " " + noun;
//if there's an error, it will spit this line back at the player
}
void ClearCollectionsForNewRoom()
{
interactionDescriptionsInRoom.Clear();
roomNavigation.ClearExits();
interactableItems.ClearCollections();
}
public void LogStringWithReturn(string stringToAdd)
//This function is called upon whenver a new string needs to be added aka whenever the player
//takes an action
{
actionLog.Add(stringToAdd + "\n");
//A function of the List class that allows us to add things-- the slash n essentially types in a line break to the log
}
// Update is called once per frame
void Update()
{
}
}
“Room” Script:
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 InteractableObjects[] interactableObjectsInRoom;
}
Please help!