Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice

Question How to set a variable to null without error ?

Discussion in 'Scripting' started by ZeStef_Prod, Apr 1, 2024.

  1. ZeStef_Prod

    ZeStef_Prod

    Joined:
    Mar 20, 2023
    Posts:
    5
    Hello
    I have a question, on my inventory script, I have "currentSlot" which refers to another script, "SlotSystem", in this script "SlotSystem", I call a variable of type ItemData, which is another script creating item instances, as on the screen below. On my inventory script, I empty a variable named item present on my ItemData script, I empty this variable by doing: currentSlot.item = null;
    but when I run the code, unity informs me of an error: NullReferenceExeption: object reference not set to an instance of an object Inventory.RefreshContent() (at Assets/Scripts/Inventory.cs:156)
    Can someone help me, please.
    Thanks you

    Error :

    Capture d'écran 2024-04-01 152745.png

    Capture d'écran 2024-04-01 152705.png

    Capture d'écran 2024-04-01 152629.png

    Script Inventory :

    Code (CSharp):
    1. using System.Collections.Generic;
    2. using UnityEngine;
    3. using System.Linq;
    4.  
    5. public class Inventory : MonoBehaviour
    6. {
    7.     [Header("OTHER SCRIPTS REFERENCES")]
    8.  
    9.     [SerializeField]
    10.     private Equipment equipment;
    11.  
    12.     [SerializeField]
    13.     private ItemActionsSystem itemActionsSystem;
    14.  
    15.     [SerializeField]
    16.     private CraftingSystem craftingSystem;
    17.  
    18.     [SerializeField]
    19.     private BuildSystem buildSystem;
    20.  
    21.     [Header("INVENTORY SYSTEM VARIABLES")]
    22.  
    23.     [SerializeField]
    24.     private List<ItemInInventory> content = new List<ItemInInventory>();
    25.  
    26.     [SerializeField]
    27.     private GameObject inventoryPanel;
    28.  
    29.     [SerializeField]
    30.     private Transform inventorySlotsParent;
    31.  
    32.     [SerializeField]
    33.     private KeyCode inventoryInput;
    34.  
    35.     [SerializeField]
    36.     private SlotSystem slotSystem;
    37.  
    38.     public Sprite emptySlotVisual;
    39.  
    40.     public static Inventory instance;
    41.  
    42.     const int InventorySize = 35;
    43.     private bool isOpen = false;
    44.  
    45.     private void Awake()
    46.     {
    47.         instance = this;
    48.     }
    49.  
    50.     private void Start()
    51.     {
    52.         RefreshContent();
    53.         CloseInventory();
    54.     }
    55.  
    56.     private void Update()
    57.     {
    58.         if (Input.GetKeyDown(inventoryInput))
    59.         {
    60.             if (isOpen)
    61.             {
    62.                 CloseInventory();
    63.             }
    64.             else
    65.             {
    66.                 OpenInventory();
    67.             }
    68.         }
    69.     }
    70.  
    71.     public void AddItem(ItemData item)
    72.     {
    73.         ItemInInventory[] itemInInventory = content.Where(elem => elem.itemData == item).ToArray();
    74.  
    75.         bool itemAdded = false;
    76.  
    77.         if (itemInInventory.Length > 0 && item.stackable)
    78.         {
    79.             for (int i = 0; i < itemInInventory.Length; i++)
    80.             {
    81.                 if (itemInInventory[i].count < item.maxStack)
    82.                 {
    83.                     itemAdded = true;
    84.                     itemInInventory[i].count++;
    85.                     break;
    86.                 }
    87.             }
    88.  
    89.             if (!itemAdded)
    90.             {
    91.                 content.Add(
    92.                     new ItemInInventory
    93.                     {
    94.                         itemData = item,
    95.                         count = 1
    96.                     }
    97.                 );
    98.             }
    99.         }
    100.         else
    101.         {
    102.             content.Add(
    103.                 new ItemInInventory
    104.                 {
    105.                     itemData = item,
    106.                     count = 1
    107.                 }
    108.             );
    109.         }
    110.  
    111.         RefreshContent();
    112.     }
    113.  
    114.     public void RemoveItem(ItemData item)
    115.     {
    116.         ItemInInventory itemInInventory = content.Where(elem => elem.itemData == item).FirstOrDefault();
    117.  
    118.         if (itemInInventory != null && itemInInventory.count > 1)
    119.         {
    120.             itemInInventory.count--;
    121.         }
    122.         else
    123.         {
    124.             content.Remove(itemInInventory);
    125.         }
    126.  
    127.         RefreshContent();
    128.     }
    129.  
    130.     public List<ItemInInventory> GetContent()
    131.     {
    132.         return content;
    133.     }
    134.  
    135.     private void OpenInventory()
    136.     {
    137.         inventoryPanel.SetActive(true);
    138.         isOpen = true;
    139.     }
    140.  
    141.     public void CloseInventory()
    142.     {
    143.         inventoryPanel.SetActive(false);
    144.         itemActionsSystem.actionPanel.SetActive(false);
    145.         TooltipSystem.instance.Hide();
    146.         isOpen = false;
    147.     }
    148.  
    149.     public void RefreshContent()
    150.     {
    151.         // On vide tous les slots / visuels
    152.         for (int i = 0; i < inventorySlotsParent.childCount; i++)
    153.         {
    154.             SlotSystem currentSlot = inventorySlotsParent.GetChild(i).GetComponent<SlotSystem>();
    155.  
    156.             currentSlot.item = null;
    157.             currentSlot.itemsVisual.sprite = emptySlotVisual;
    158.             currentSlot.countText.enabled = false;
    159.         }
    160.  
    161.         // On peuple le visuel des slots selon le contenu réel de l'inventaire
    162.         for (int i = 0; i < content.Count; i++)
    163.         {
    164.             SlotSystem currentSlot = inventorySlotsParent.GetChild(i).GetComponent<SlotSystem>();
    165.  
    166.             currentSlot.item = content[i].itemData;
    167.             currentSlot.itemsVisual.sprite = content[i].itemData.visual;
    168.  
    169.             if (currentSlot.item.stackable)
    170.             {
    171.                 currentSlot.countText.enabled = true;
    172.                 currentSlot.countText.text = content[i].count.ToString();
    173.             }
    174.         }
    175.  
    176.         equipment.UpdateEquipmentDesequipButtons();
    177.         craftingSystem.UpdateDisplayedRecipes();
    178.         buildSystem.UpdateDisplayedCosts();
    179.     }
    180.  
    181.     public bool IsFull()
    182.     {
    183.         return InventorySize == content.Count;
    184.     }
    185.  
    186.     public void LoadData(List<ItemInInventory> savedData)
    187.     {
    188.         content = savedData;
    189.         RefreshContent();
    190.     }
    191.  
    192.     public void ClearContent()
    193.     {
    194.         content.Clear();
    195.     }
    196.  
    197. }
    198.  
    199. [System.Serializable]
    200. public class ItemInInventory
    201. {
    202.     public ItemData itemData;
    203.     public int count;
    204. }

    Script ItemData :


    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. //Creer un menu dans asset pour creer un scriptableObject
    6. [CreateAssetMenu(fileName = "Item", menuName = "Items/New item")]
    7. public class ItemData : ScriptableObject
    8. {
    9.     [Header("Data")]
    10.     public string itemName;
    11.     public Sprite visual;
    12.     public GameObject prefab;
    13.     public string description;
    14.     public bool stackable;
    15.     public int maxStack;
    16.  
    17.     [Header("Effects")]
    18.     public float healthEffect;
    19.     public float hungerEffect;
    20.     public float thirstEffect;
    21.  
    22.     [Header("Armor Stats")]
    23.     public float armorPoints;
    24.  
    25.     [Header("Attack Stats")]
    26.     public float attackPoints;
    27.  
    28.     [Header("Types")]
    29.     public ItemType itemType;
    30.     public EquipementType equipementType;
    31. }
    32.  
    33. //Enum pour créer les type d'item
    34. public enum ItemType
    35. {
    36.     Ressource,
    37.     Equipement,
    38.     Consumable
    39. }
    40.  
    41. //Enum pour créer les types d'équipement
    42. public enum EquipementType
    43. {
    44.     Head,
    45.     Chest,
    46.     Hands,
    47.     Legs,
    48.     Feet,
    49.     Weapon
    50. }
    51.  

    Script SlotSystem :


    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.UI;
    5. using UnityEngine.EventSystems;
    6.  
    7. public class SlotSystem : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler
    8. {
    9.     public ItemData item;
    10.     public Image itemsVisual;
    11.     public Text countText;
    12.  
    13.     [SerializeField]
    14.     private ItemActionsSystem itemActionsSystem;
    15.  
    16.     //Quand la souris est sur un Slot
    17.     public void OnPointerEnter(PointerEventData enventData)
    18.     {
    19.         //Si l'objet et différent de null, on montre le menu Tooltip et on écrit la description et le nom de l'item choisit
    20.         if (item != null)
    21.         {
    22.             TooltipSystem.instance.Show(item.description, item.name);
    23.  
    24.         }
    25.     }
    26.  
    27.     //Quand la souris n'est plus sur un Slot
    28.     public void OnPointerExit(PointerEventData enventData)
    29.     {
    30.         //Cache le menu ToolType
    31.         TooltipSystem.instance.Hide();
    32.     }
    33.    
    34.     //Quand on clique sur un Slot
    35.     public void ClickOnSlot()
    36.     {
    37.         itemActionsSystem.OpenActionPanel(item, transform.position);
    38.     }
    39.  
    40. }
    41.  
    42.  
    43.  
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    39,067
  3. ZeStef_Prod

    ZeStef_Prod

    Joined:
    Mar 20, 2023
    Posts:
    5
    What is null is "current Slot" but the fact that I set it to null is so that nothing is taken into account from the inventory
    upload_2024-4-1_15-43-56.png
     
  4. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    39,067
    If you set a variable to
    null
    and then use it, it WILL throw a NullReferenceException.

    If you intend to set a variable to
    null
    in order signal some other part of your code "hey, do not use this," then YOU still need to check it in EVERY place that uses it.

    Code (csharp):
    1. if (thing != null)
    2. {
    3.   thing.DoStuff();
    4. }
    5. else
    6. {
    7.   Debug.Log( "Cannot do stuff with thing... thing is null!");
    8. }
    This isn't really a matter of discussion, debate or opinion. This is just how it works. It's just a bog-standard nullref.
     
    Last edited: Apr 1, 2024
  5. ZeStef_Prod

    ZeStef_Prod

    Joined:
    Mar 20, 2023
    Posts:
    5
    Thank you cery much
    For a week now, I've been carrying out poor verification