Search Unity

Question How do I Set Value of Data Class In Script

Discussion in 'Scripting' started by samdaman93, Apr 4, 2021.

  1. samdaman93

    samdaman93

    Joined:
    Oct 3, 2015
    Posts:
    37
    Hello!

    I'm pretty to this so bear with me. I started following the text adventure tutorial as I'd like to make one as a bit of a hobby project. I've got it working so I can print the room descriptions, click buttons to go between rooms etc, however I'm using scriptable objects for the room data and what I've found is if the script during runtime of the game changes any of the data, it stays that way for future runs. Which isn't ideal. I've now set up a excel spreadsheet that outputs a text file which has all the room data and I'm in the process of creating a script that creates instances of the rooms from the text file.

    I can get the rooms setup, however I get stuck when trying to set values to the exits. I've copied below the room scriptable object and the exit data class. My script gets stuck at line 74 when it tries to access the array of exits on each room returning "NullReferenceException: Object reference not set to an instance of an object."

    My first thought is I'm not creating the arrays properly on the room scriptable objects however the length of the arrays are correct as when I debug the Rooms.exits.Length, it returns the correct length of 3 for each room. I've tried manually setting the text to a test string and that doesn't work either.

    All help is welcomed!

    Cheers,

    Room scriptable Object
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. [CreateAssetMenu(menuName = "TextAdventure/Room")]
    6. public class Room : ScriptableObject
    7. {
    8.     [TextArea]
    9.     public string roomName;
    10.     [TextArea]
    11.     public string description;
    12.     [TextArea]
    13.     public string returnToRoomDescription;
    14.     public Exit[] exits;
    15.  
    16. }
    Exit Data Class
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5.  
    6. [System.Serializable]
    7. public class Exit
    8. {
    9.     public string exitDescription;
    10.     public Room valueRoom;
    11.  
    12. }
    13.  
    Create Room Function
    Code (CSharp):
    1. public void createRooms(string[] textArray)
    2.     {
    3.         List<Room> Rooms = new List<Room>();
    4.         List<int> roomTextPositions = new List<int>();
    5.         Dictionary<string, Room> RoomNames = new Dictionary<string, Room>();
    6.  
    7.         int counter = 0;
    8.         foreach (string line in textArray)
    9.         {
    10.             counter += 1;
    11.             if (line.Contains("[R]"))
    12.             {
    13.                 roomTextPositions.Add(counter);
    14.                 int textline = counter;
    15.                 string lineHolder = line.Replace("[R]", "");
    16.                 Room Room = ScriptableObject.CreateInstance("Room") as Room;
    17.                 Room.roomName = lineHolder;
    18.                 Room.description = textArray[counter].Replace("[D1]","");
    19.                 Room.returnToRoomDescription = textArray[counter+1].Replace("[D2]", "");
    20.                 Rooms.Add(Room);
    21.                 RoomNames.Add(Room.roomName, Room);
    22.                
    23.             }
    24.            
    25.         }
    26.  
    27.         for (int i = 0; i < Rooms.Count; i++)
    28.         {
    29.             //checks if the next room in text file has been found, if so will break while loop and return exits.
    30.             bool bootfromscript = false;
    31.  
    32.             int Linecounter;
    33.  
    34.             //make exit array per room
    35.             for (int j = 0; j < Rooms.Count; j++)
    36.             {
    37.                 int roomExits = 0;
    38.                 Linecounter = roomTextPositions[j];
    39.                 bootfromscript = false;
    40.  
    41.                 while (bootfromscript != true)
    42.                 {
    43.                     if (textArray[Linecounter].Contains("[R]")||Linecounter==textArray.Length-1)
    44.                     {
    45.                         bootfromscript = true;
    46.                     }
    47.  
    48.                     if (textArray[Linecounter].Contains("[E]"))
    49.                     {
    50.                         roomExits++;
    51.                         Rooms[i].exits = new Exit[roomExits];
    52.                     }
    53.  
    54.                     Linecounter++;
    55.                 }
    56.  
    57.             }
    58.  
    59.             for (int j = 0; j < Rooms[i].exits.Length; j++)
    60.             {
    61.  
    62.                 Linecounter = roomTextPositions[j];
    63.                 bootfromscript = false;
    64.  
    65.                 while (bootfromscript != true)
    66.                 {
    67.                     if (textArray[Linecounter].Contains("[R]") || Linecounter == textArray.Length - 1)
    68.                     {
    69.                         bootfromscript = true;
    70.                     }
    71.  
    72.                     if (textArray[Linecounter].Contains("[E]"))
    73.                     {
    74.                         Rooms[i].exits[j].exitDescription = textArray[Linecounter+1].Replace("[ED]", "");
    75.                         Rooms[i].exits[j].valueRoom = RoomNames[textArray[Linecounter].Replace("[E]", "")];
    76.                     }
    77.  
    78.                     Linecounter++;
    79.                 }
    80.  
    81.             }
    82.  
    83.         }
    84.  
    85.     }
     
  2. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,914
    You're creating an Exit array but you aren't populating it with anything, so it's just full of null references. You need to create Exits for the array to point at.

    For example;
    Code (CSharp):
    1. Exit exit = new Exit();
    2. Rooms[i] = exit;
     
    Last edited: Apr 4, 2021
    Kurt-Dekker likes this.
  3. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,749
    Precisely what @PraetorBlue says above... there's two levels going on, the array of things and the things themselves.

    Just for future reference, here's my standard blurb on nullrefs, since they're a super-common thing... and I just fixed one ten minutes ago in fact! I do it every time I sit down to code (almost). Nothing to be ashamed of.

    Some notes on how to fix a NullReferenceException error in Unity3D
    - also known as: Unassigned Reference Exception
    - also known as: Missing Reference Exception
    - also known as: Object reference not set to an instance of an object

    http://plbm.com/?p=221

    The basic steps outlined above are:
    - Identify what is null
    - Identify why it is null
    - Fix that.

    Expect to see this error a LOT. It's easily the most common thing to do when working. Learn how to fix it rapidly. It's easy. See the above link for more tips.

    This is the kind of mindset and thinking process you need to bring to this problem:

    https://forum.unity.com/threads/why-do-my-music-ignore-the-sliders.993849/#post-6453695

    Step by step, break it down, find the problem.
     
  4. samdaman93

    samdaman93

    Joined:
    Oct 3, 2015
    Posts:
    37
    Hey thanks for the replies, I've got it working up until I try to set the first room in my room navigation class. Currently I've got the script working through the entire text file creating rooms and exits, but to start cycling through them at runtime, I need to set the first Room which I'm struggling with. My first guess is I've either not setup my Rooms correctly or I'm not "attaching" the first room correctly. I'm getting the same error, yet I'm not too sure why its not working? I've reattached code below.

    Code (CSharp):
    1.    public void createRooms(string[] textArray)
    2.     {
    3.         List<Room> Rooms = new List<Room>();
    4.         List<int> roomTextPositions = new List<int>();
    5.         Dictionary<string, Room> RoomNames = new Dictionary<string, Room>();
    6.  
    7.         //create room objects
    8.         int counter = 0;
    9.         foreach (string line in textArray)
    10.         {
    11.             counter += 1;
    12.             if (line.Contains("[R]"))
    13.             {
    14.                 roomTextPositions.Add(counter);
    15.                 int textline = counter;
    16.                 string lineHolder = line.Replace("[R]", "");
    17.                 Room Room = ScriptableObject.CreateInstance("Room") as Room;
    18.                 Room.description = textArray[counter].Replace("[D1]","");
    19.                 Room.returnToRoomDescription = textArray[counter+1].Replace("[D2]", "");
    20.                 Rooms.Add(Room);
    21.                 RoomNames.Add(lineHolder, Room);
    22.                
    23.             }
    24.            
    25.         }
    26.  
    27.         for (int i = 0; i < Rooms.Count; i++)
    28.         {
    29.             //checks if the next room in text file has been found, if so will break while loop and return exits.
    30.             bool bootfromscript = false;
    31.  
    32.             int Linecounter;
    33.  
    34.             //make exit array per room
    35.             for (int j = 0; j < Rooms.Count; j++)
    36.             {
    37.                 int roomExits = 0;
    38.                 Linecounter = roomTextPositions[j];
    39.                 bootfromscript = false;
    40.  
    41.                 while (bootfromscript != true)
    42.                 {
    43.                     if (textArray[Linecounter].Contains("[R]")||Linecounter==textArray.Length-1)
    44.                     {
    45.                         bootfromscript = true;
    46.                     }
    47.  
    48.                     if (textArray[Linecounter].Contains("[E]"))
    49.                     {
    50.                         roomExits++;
    51.                         Rooms[i].exits = new Exit[roomExits];
    52.                     }
    53.  
    54.                     Linecounter++;
    55.                 }
    56.  
    57.             }
    58.  
    59.             //Setup exits and attach to rooms
    60.             for (int j = 0; j < Rooms[i].exits.Length; j++)
    61.             {
    62.                 int Exitcounter = 0;
    63.                 Linecounter = roomTextPositions[i];
    64.                 bootfromscript = false;
    65.  
    66.                 while (bootfromscript != true)
    67.                 {
    68.                     if (textArray[Linecounter].Contains("[R]") || Linecounter == textArray.Length - 1)
    69.                     {
    70.                         bootfromscript = true;
    71.                     }
    72.  
    73.                     if (textArray[Linecounter].Contains("[E]"))
    74.                     {
    75.                         Exit exit = new Exit();
    76.                         exit.exitDescription = textArray[Linecounter + 1].Replace("[ED]", "");
    77.                         exit.valueRoom = RoomNames[textArray[Linecounter].Replace("[E]", "")];
    78.                         Rooms[i].exits[Exitcounter] = exit;
    79.                         Exitcounter++;
    80.                     }
    81.  
    82.                     Linecounter++;
    83.                 }
    84.  
    85.             }
    86.  
    87.         }
    88.  
    89.         roomNavigation.currentRoom = Rooms[0];
    90.     }