When pressing the play button, my player controller immediately becomes disabled, I assume it's something to do with the error message: NullReferenceException: Object reference not set to an instance of an object Player.PlayerController.Awake () (at Assets/Scripts/PlayerController.cs:57) Code (CSharp): private SpellSlot[] SpellArray; ... void Awake() { CameraLocked = false; rb = GetComponent<Rigidbody>(); SpellArray = new SpellSlot[4]; int Y = Screen.height - 110; SpellArray[0].GUISize = new Rect(10, Y, 100, 100); //Line 57 SpellArray[1].GUISize = new Rect(120, Y, 100, 100); SpellArray[2].GUISize = new Rect(230, Y, 100, 100); SpellArray[3].GUISize = new Rect(340, Y, 100, 100); } I can't tell what's actually wrong with this. Supposedly the array of objects isn't instantiated, but it very clearly is. EDIT: SpellSlot is a class with a constructor. Is the constructor not being called on instantiation?
The array is instantiated, yes, but it's empty. You're trying to access elements that aren't there yet.
SpellSlot is a class. Is the constructor not being called? Also, I'm trying to set the elements, not read them
No, the constructors aren't called. You've just made an empty array of size 4, that CAN contain SpellSlot objects. And your lines 11 - 14 don't set the elements, they try to retrieve the elements and set their GUISize.
How do I put SpellSlot objects into the array in that case? Alternatively, if I convert SpellSlot into a struct instead of a class, would that resolve the issue?
Hmm.. I'm not sure what your constructor is, but: Code (csharp): for(int i = 0; i < SpellArray.Length; ++i) SpellArray[i] = new SpellSlot();
This hasn't worked, nor has changing the declaration of the array to: Code (CSharp): public SpellSlot[] SpellArray = new SpellSlot[] { new SpellSlot(), new SpellSlot(), new SpellSlot(), new SpellSlot() }; This is getting incredibly frustrating
How did it not work? the same error as before, do you mean? Feel free to post the SpellSlot class if that's relevant.
If SpellSlot is class you need to create instance of it. Code (CSharp): SpellArray = new SpellSlot[4]; int Y = Screen.height - 110; int temp = 10; int length = SpellArray.Length; for (int i = 0; i < length; i++) { SpellArray[i] = new SpellSlot(); // You'll achieve the same result, but it's better solution than "manual" writing. SpellArray[i].GUISize = new Rect(temp + (i * 110), Y, 100, 100); }
I'm not sure that the number of times we explain that fact is going to help, in this case. Something else is in @Hosomi's way.
I've made some changes, but the error is still occurring. I'll show everything related to the issue Code (CSharp): public SpellSlot[] SpellArray; ... void Awake() { CameraLocked = false; rb = GetComponent<Rigidbody>(); int length = SpellArray.Length; for (int i = 0; i < length; ++i) { SpellArray[i] = new SpellSlot(); } } ... void OnGUI() { int Y = Screen.height - 110; int length = SpellArray.Length; for (int i = 0; i < length; ++i) { GUI.Box(new Rect(10+(i*110), Y, 100, 100), SpellArray[i].name); //This line is now where the error points } } and what's left of the SpellSlot class after taking it apart trying to solve this issue Code (CSharp): public class SpellSlot : MonoBehaviour { public int ID; public string Name; public bool Occupied; public SpellSlot() { ID = 0; Name = ""; Occupied = false; } }
Of course, I didn't realize (or think to ask) if SpellSlot is a MonoBehaviour. If it doesn't have to be one, then do not make it inherit from (that). If you want it to be one, you cannot create a mono behaviour with the 'new' keyword. You must AddComponent to some game object. You'll have to know/decide what you want to do with that.
As methos5k is saying, a MonoBehaviour needs to be a component attached to a GameObject. If that is what you want, then you should create a prefab of a GameObject with this SpellSlot component attached, and instead of creating new SpellSlot instances you instead instantiate new GameObjects from that prefab. Then to access the SpellSlot component you would use GetComponent<SpellSlot>() on that instantiated GameObject. Otherwise remove MonoBehaviour.
Everything in C# is case sensitive. SpellSlot doesn't have a property called name, it has a property called Name. Your code editor, such as Visual Studio, should be pointing out these issues long before you even try compiling.
Still giving NullReferenceException: Object reference not set to an instance of an object Player.PlayerController.Awake () (at Assets/Scripts/PlayerController.cs:55) This time pointing to the line int length = SpellArray.Length; I spotted that and quickly deleted that post commenting out the SpellArray.Length lines and just using a constant in place of length now gives the following NullReferenceException: Object reference not set to an instance of an object (wrapper stelemref) object:stelemref (object,intptr,object) Player.PlayerController.Awake () (at Assets/Scripts/PlayerController.cs:58) Code (CSharp): //int length = SpellArray.Length; for (int i = 0; i < 4; ++i) { SpellArray[i] = new SpellSlot(); //Error now points to this line }
I highly suggest going through some very basic C# tutorials. Stuff like how to properly declare an array in C#. In your case you are trying to use SpellArray before you have initialized it, based on the line of code you say the error is on. https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/arrays/single-dimensional-arrays
Why are they so bloody awkward to work with? C# isn't my first language, but it has a reputation of being easy to learn, yet using an array of objects is so incredibly unintuitive And I've read these tutorials, but they don't seem to be at all relevant Regardless, I've changed the declaration of SpellArray and it works now, but I can't say I've learnt much from the experience
Lists were created partly because arrays are horrible to work with. I use Lists whenever I don't have to use an array. Simple example: Code (csharp): List<SpellSlot> SpellList = new List<SpellSlot>(); SpellList.Add(new SpellSlot()); int length = SpellList.Count; foreach (SpellSlot ss in SpellList) { ss.Name = "New Name"; Debug.Log(ss.Name); }