- Home /
initialize (variable/List in Start() or Class?)
Hello, Yesterday I was facing really strange problem, and I want to know, why.
I have 2 scripts: ContainerSlot, & ContainerManager.
Firstly I had:
using UnityEngine;
using System.Collections;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class ContainerSlot: MonoBehaviour, IPointerEnterHandler, IPointerExitHandler, IBeginDragHandler, IEndDragHandler, IDragHandler, IPointerClickHandler {
public ItemType equipmentPart;
public Sprite backgroundImage;
Item item;
public Item Item {
get {
return item;
}
set {
item = value;
}
}
Image icon;
void Start () {
item = new Item();
icon = transform.GetChild(0).GetComponent<Image>();
icon.sprite = backgroundImage;
}
}
And I don't know why, when I was trying to grab Item in ContainerManager, ContainerSlot returned null all time.
When I changed script to:
using UnityEngine;
using System.Collections;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class ContainerSlot: MonoBehaviour, IPointerEnterHandler, IPointerExitHandler, IBeginDragHandler, IEndDragHandler, IDragHandler, IPointerClickHandler {
public ItemType equipmentPart;
public Sprite backgroundImage;
Item item = new Item();
public Item Item {
get {
return item;
}
set {
item = value;
}
}
Image icon;
void Start () {
icon = transform.GetChild(0).GetComponent<Image>();
icon.sprite = backgroundImage;
}
}
Everything works fine and ContainerManager can grab Item. I checked in ScriptExecutionOrder and ContainerSlot was BEFORE ContainerManager, so there sould be no problems. I had that problems in some scripts with Lists too, when was initialized in class, everything was ok, if in Start(), null exceptions spam my console.
Now Question. Is it better to always initialize variable/List inside Class to some default value? Or its only me fighting with some unknown issue?
new Item() overrides what is saved in it an makes a new instance which is equal to null. You have to set it to something after the new Item() call.
I don't think this is true. I believe that using the new
keyword with a class causes a memory allocation on the heap, and the returned value is the reference to the memory location on the heap. Null, on the other hand, means that the referenced memory location is 0, which is an invalid memory address and defined as a null pointer.
When you use new
, the constructor of the class is called, and the value that you get is a reference to the instance of that class, initialized with the constructor.
I personally dislike line 11 of the second piece of code. You don't know when this line gets called (though it is possible to look this up in some reference). I think it's better to put it in a constructor or the Start/Awake functions so that you explicitly know when you are initializing that field.
For why you may be getting null pointers when you put that line inside Start/Awake, you are probably trying to use that value before Start
function that initializes the value is called. If you need a value to be initialized by the Start
function, you can initialize it in Awake
, which is called before Start
. It's difficult to actually know what the problem is because there aren't any concrete examples. In the code that you gave, you aren't using item
anywhere.
@_Gkxd
Yeah, for me that second solution is also bad, I don't like that. I tried with Awake() and with it everyting is okey so Ill move all inits there, but tell me, why Awake() works and Start() no, even when inside ScriptExecOrder that script should run first?
@_Gkxd You are correct, I misread the getter setter, and thought he was simply overwriting a value that had already been assigned!
possibly as an alternative you could do:
Item item;
public Item Item {
get {
if(item != null) return item;
item = new Item();
return item;
}
set {
item = value;
}
}
@Scribe Yes! Thats that, I never had such problem before with get/set. Can you set your comment as answer? Ill accept it cus after checking null in getter as you suggested, everything back to normal :)
Answer by Scribe · Aug 26, 2015 at 03:48 PM
It appears they have increased the karma needed to 10,000 to convert things which is unfortunate, so I will just copy it across!
possibly as an alternative you could do:
Item item = new Item();
public Item Item {
get {
if(item != null) return item;
item = new Item();
return item;
}
set {
item = value;
}
}
in this approach on 1st line item = new Item(); is not needed ;)