- Home /
The question is answered, right answer was accepted
NullReferenceException: but I have checked that there is a object and have a if(obj != null) before
Hi everyone. I'm making a small top down shooter in my spare time and I have been stuck for the last days on this problem. I have a scriptable object for items called Item and in my PlayerController script i have a reference to a Item in the variabel public Item baseWeapon (line 38) that I have assigned from the inspector. I also have a if(baseWeapon != null) before the use of it to make sure that it exists and I have been able to check that it exists with debug.log. But when I try to add it to my Inventory (line 46) I get this error:
NullReferenceException: Object reference not set to an instance of an object InventorySlot.AddItem (.Item newItem) (at Assets/Code/UI/InventorySlot.cs:33) InventoryUI.UpdateUI () (at Assets/Code/UI/InventoryUI.cs:38) Inventory.Add (.Item item, Int32 id) (at Assets/Code/Management/Inventory.cs:58) PlayerController.Start () (at Assets/Code/Entities/Player/PlayerController.cs:46)
All scripts referenced here are referring to the same baseWeapon that I put in (line 46)
My PlayerController script public class PlayerController : MonoBehaviour {
public Rigidbody2D rig;
public float speed;
public Transform target;
public Transform gunPoint;
public GameObject bullet;
public Animator playerAnimator;
public Animator feetAnimator;
bool moving;
bool doingSomething = false;
float waitTime;
int ammo;
public int baseAmmo;
public float fireRate;
public float weaponBaseDmg;
public float weaponDmgRange;
public float reloadTime;
public Text ammoText;
public float health;
public bool dead;
public string gameOver;
public Item baseWeapon;
//this is the item I'm referring to
void Start ()
{
ammo = baseAmmo;
Equip (baseWeapon.baseAmmo, baseWeapon.fireRate, baseWeapon.weaponBaseDmg, baseWeapon.weaponDmgRange, baseWeapon.reloadTime);
if (baseWeapon != null)
{
Inventory.instance.Add (baseWeapon, 16);
//This is where I add baseWeapon to my inventory
}
}
My Inventory script
#region Singelton
public static Inventory instance;
void Awake ()
{
if (instance != null)
{
Debug.LogWarning ("More than one instance of Inventory found!");
return;
}
instance = this;
}
#endregion
public delegate void OnItemChanged ();
public OnItemChanged onItemChangedCallback;
public int inventorySize;
public Item[] items;
void Start ()
{
items = new Item[inventorySize];
}
public bool Add (Item item)
{
for (int i = 0; i < inventorySize; i++)
{
if (items [i] == null)
{
items [i] = item;
if (onItemChangedCallback != null)
{
onItemChangedCallback.Invoke ();
}
return true;
}
}
return false;
}
public void Add (Item item, int id)
{
items [id] = item;
if (onItemChangedCallback != null)
{
onItemChangedCallback.Invoke ();
}
}
public void Remove (int id)
{
items [id] = null;
if (onItemChangedCallback != null)
{
onItemChangedCallback.Invoke ();
}
}
}
My Item script
[CreateAssetMenu (fileName = "New Item", menuName = "Inventory/Item")] public class Item : ScriptableObject {
new public string name = "New Item";
public Sprite icon = null;
public bool stackable = false;
public GameObject dropItem;
public int baseAmmo;
public float fireRate;
public float weaponBaseDmg;
public float weaponDmgRange;
public float reloadTime;
InventorySlot script {
public GameObject moveImage;
GameObject instMoveImage;
Vector3 pin;
Vector2 offset;
public Color none;
public Color normal;
Image icon;
public Item item;
Inventory inv;
public int slotID;
void Start ()
{
icon = gameObject.GetComponent<Image> ();
inv = Inventory.instance;
}
public void AddItem (Item newItem)
{
item = newItem;
icon.sprite = item.icon;
icon.color = normal;
inv.items[slotID] = newItem;
}
public void ClearSlot ()
{
item = null;
icon.sprite = null;
icon.color = none;
inv.items[slotID] = null;
}
public void OnBeginDrag(PointerEventData eventData)
{
if (item != null)
{
pin = transform.position;
instMoveImage = Instantiate (moveImage, transform.parent);
instMoveImage.transform.position = transform.position;
instMoveImage.GetComponent<Image> ().sprite = item.icon;
instMoveImage.GetComponent<Image> ().preserveAspect = true;
instMoveImage.GetComponent<Image> ().enabled = true;
instMoveImage.GetComponent<MoveImage> ().target = transform;
offset = eventData.position - (Vector2)transform.position;
transform.position = eventData.position - offset;
GetComponent<CanvasGroup> ().blocksRaycasts = false;
//MovingItem script = instDragItem.GetComponent <MovingItem> ();
//script.item = item;
//script.slot = this;
//instDragItem.GetComponent<Image> ().sprite = script.item.icon;
//instDragItem.GetComponent<Image> ().preserveAspect = true;
//ClearSlot ();
}
}
public void OnDrag (PointerEventData eventData)
{
transform.position = eventData.position - offset;
}
public virtual void OnDrop(PointerEventData eventData)
{
if (item == null)
{
InventorySlot dropedItem = eventData.pointerDrag.GetComponent<InventorySlot> ();
AddItem (dropedItem.item);
dropedItem.ClearSlot ();
} else {
InventorySlot dropedItem = eventData.pointerDrag.GetComponent<InventorySlot> ();
Item transfer = dropedItem.item;
dropedItem.AddItem (item);
AddItem(transfer);
}
}
public void OnEndDrag (PointerEventData eventData)
{
GetComponent<CanvasGroup> ().blocksRaycasts = true;
Destroy (instMoveImage);
transform.position = pin;
}
}
Any ideas on whats wrong and how I can fixe it would be very much appreciated and thanks in advance
I'm 99% sure the problem comes from Inventory.instance
. If you don't have any gameObject with the Inventory script attached in your scene, Inventory.instance
will return null.
I thought about that as well but I tested that by creating a test function on Inventory that just made a debug.log statement in the console and called that from PlayerController and that worked fine. But thanks for the answer.
Try
if(gameObject)
ins$$anonymous$$d of
if(gameObject != null)
I always had better results. In fact I always wondered why people nullchecked GameObjects as that has literally NEVER worked for me. Not even one single time.
As far as I know, null is a SPECIFIC ASSIGN$$anonymous$$ENT whereas 'undefined' is just that and can include a lot of spurious things.
What does your InventorySlot class look like? Especially line 33 since this is where you get the NullReferenceException from.
I added it to the question but the null reference exception shows up not just in that script but in all the other stated as they all trigger when Inventory.Add and uses the Item in question. Inventory Slot is just the last one to trigger.
The error message tells you the 'path' from the first function to the last (where the error happens)
PlayerController.Start()
Inventory.Add()
InventoryUI.UpdateUI()
InventorySlot.AddItem() -> This is where the error happens
So the error is happening in line 33 of your InventorySlot script, inside the AddItem() function.
I think the error happens here:
inv.items[slotID] = newItem;
inv is probably not assigned because the Start() function of PlayerController is called before the Start() function of InventorySlot.
So try changing inv.items[slotID] = newItem;
to Inventory.instance.items[slotID] = newItem;
I would also advise you to put the items = new Item[inventorySize];
into the Awake() function of your InventoryScript and to put the icon = gameObject.GetComponent<Image> ();
into the Awake function of your InventorySlot script
It may be that your inventory.instance is initializing AFTER playercontroller, so it is null when the player controller tries to access it in start. You can chance the script execution order and move the inventory script to initialize first.
Follow this Question
Related Questions
How to unfreeze a Script in a unity5 Scene? 1 Answer
Is it possible to write a function in the backend of an editor script for a scriptableObject? 0 Answers
Set default length for an array of elements of a custom class in inspector 0 Answers
Confused about custom GameObjects,Custom GameObject confusion 0 Answers
Creating an instance of a ScriptableObject, that will not change the base asset. 2 Answers