Search Unity

Question Need help on referencing scriptable object.

Discussion in 'Scripting' started by Dlightb, Jan 15, 2022.

  1. Dlightb

    Dlightb

    Joined:
    Mar 9, 2021
    Posts:
    3
    I'll drop my scripts in first, I'm not sure how much of it is necessary.
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. public enum Type { Player, Enemy}
    5. public enum AttackType { Slashing, Piercing, Blunt, Arcana}
    6. [CreateAssetMenu(fileName ="New Unit", menuName ="Scriptable Objects/New Unit")]
    7. public class UnitObject : ScriptableObject
    8. {
    9.     public Sprite uiDisplay;
    10.     public Type type;
    11.     public AttackType attackType;
    12.     [TextArea(15, 20)]
    13.     public string Description;
    14.     public Unit data = new Unit();
    15.  
    16.     public string UnitName;
    17.     public int maxHP;
    18.     public int minDamage;
    19.     public int maxDamage;
    20.     public int defense;
    21.     public int evasionChance;
    22.     public int critChance;
    23.     public int critPercentExtraDamage;
    24.     public float startTimeToAttack;
    25.  
    26.     public Unit CreateUnit()
    27.     {
    28.         Unit newUnit = new Unit(this);
    29.         return newUnit;
    30.     }
    31.  
    32. }
    33. [System.Serializable]
    34. public class Unit
    35. {
    36.     public int Id = -1;
    37.     public Unit()
    38.     {
    39.         Id = -1;
    40.     }
    41.     public Unit(UnitObject unit)
    42.     {
    43.         Id = unit.data.Id;
    44.     }
    45. }
    46.  
    Code (CSharp):
    1. public class UnitInventoryObject : ScriptableObject, ISerializationCallbackReceiver
    2. {
    3.     public string savePath;
    4.     public UnitInventory UnitContainer;
    5.     public UnitDatabaseObject unitDatabase;
    6.     public UnitInventorySlot[] GetUnitSlots { get { return UnitContainer.unitSlots; } }
    7.  
    8.     public bool AddUnit(Unit _unit)
    9.     {
    10.         if (EmptyUnitSlotCount <= 0)
    11.             return false;
    12.         UnitInventorySlot slot = FindUnitOnInventory(_unit);
    13.         if (slot == null)
    14.         {
    15.             SetEmptySlot(_unit);
    16.             return true;
    17.         }
    18.         return true;
    19.     }
    20.     public int EmptyUnitSlotCount
    21.     {
    22.         get
    23.         {
    24.             int counter = 0;
    25.             for (int i = 0; i < GetUnitSlots.Length; i++)
    26.             {
    27.                 if (GetUnitSlots[i].unit.Id <= -1)
    28.                 {
    29.                     counter++;
    30.                 }
    31.             }
    32.             return counter;
    33.         }
    34.     }
    35.     public UnitInventorySlot FindUnitOnInventory(Unit _unit)
    36.     {
    37.         for (int i = 0; i < GetUnitSlots.Length; i++)
    38.         {
    39.             if (GetUnitSlots[i].unit.Id == _unit.Id)
    40.             {
    41.                 return GetUnitSlots[i];
    42.             }
    43.         }
    44.         return null;
    45.     }
    46.     public UnitInventorySlot SetEmptySlot(Unit _unit)
    47.     {
    48.         for (int i = 0; i < GetUnitSlots.Length; i++)
    49.         {
    50.             if(GetUnitSlots[i].unit.Id <= -1)
    51.             {
    52.                 GetUnitSlots[i].UpdateUnitSlot(_unit);
    53.                 return GetUnitSlots[i];
    54.             }
    55.         }
    56.         return null;
    57.     }
    58.     public void SwapUnits(UnitInventorySlot unit1, UnitInventorySlot unit2)
    59.     {
    60.         if (unit2.CanPlaceInUnitSlot(unit1.UnitObject) && unit1.CanPlaceInUnitSlot(unit2.UnitObject))
    61.         {
    62.             UnitInventorySlot temp = new UnitInventorySlot(unit2.unit);
    63.             unit2.UpdateUnitSlot(unit1.unit);
    64.             unit1.UpdateUnitSlot(temp.unit);
    65.         }
    66.     }
    67.     public void RemoveUnit(Unit _unit)
    68.     {
    69.         for (int i = 0; i < GetUnitSlots.Length; i++)
    70.         {
    71.             if(GetUnitSlots[i].unit == _unit)
    72.             {
    73.                 GetUnitSlots[i].UpdateUnitSlot(null);
    74.             }
    75.         }
    76.     }
    77.     public void OnAfterDeserialize()
    78.     {
    79.      
    80.     }
    81.  
    82.     public void OnBeforeSerialize()
    83.     {
    84.     }
    85.     [System.Serializable]
    86.     public class UnitInventory
    87.     {
    88.         public UnitInventorySlot[] unitSlots = new UnitInventorySlot[4];
    89.         public void Clear()
    90.         {
    91.             for (int i = 0; i < unitSlots.Length; i++)
    92.             {
    93.                 unitSlots[i].RemoveUnit();
    94.             }
    95.         }
    96.     }
    97.    
    98. }
    99.  
    100. public delegate void UnitSlotUpdated(UnitInventorySlot _slot);
    101.  
    102. [System.Serializable]
    103. public class UnitInventorySlot
    104. {
    105.     [System.NonSerialized]
    106.     public UserInterfaceUnit Unitparent;
    107.     [System.NonSerialized]
    108.     public UnitSlotUpdated UnitOnAfterUpdate, UnitOnBeforeUpdate;
    109.     [System.NonSerialized]
    110.     public GameObject unitSlotDisplay;
    111.     [System.NonSerialized]
    112.     public UnitSlotUpdated OnAfterUpdate, OnBeforeUpdate;
    113.     public Unit unit;
    114.  
    115.     public UnitObject UnitObject
    116.     {
    117.         get
    118.         {
    119.             if (unit.Id >= 0)
    120.                 return Unitparent.inventory.unitDatabase.GetUnit[unit.Id];
    121.    
    122.          return null;
    123.         }
    124.     }
    125.     public UnitInventorySlot()
    126.     {
    127.         UpdateUnitSlot(new Unit());
    128.     }
    129.     public UnitInventorySlot(Unit _unit)
    130.     {
    131.         UpdateUnitSlot(_unit);
    132.     }
    133.     public void UpdateUnitSlot(Unit _unit)
    134.     {
    135.         //if (OnBeforeUpdate != null)
    136.         //    UnitOnBeforeUpdate.Invoke(this);
    137.         unit = _unit;
    138.         //if (OnAfterUpdate != null)
    139.         //    UnitOnAfterUpdate.Invoke(this);
    140.     }
    141.     public void RemoveUnit()
    142.     {
    143.         UpdateUnitSlot(new Unit());
    144.     }
    145.     public bool CanPlaceInUnitSlot(UnitObject _unitObject)
    146.     {
    147.         if (_unitObject.data.Id <= -1)
    148.             return false;
    149.         return true;
    150.     }
    151.            
    152. }
    153.  
    154.        
    Code (CSharp):
    1. public class CombatController : MonoBehaviour
    2. {
    3. public List<UnitObject> Entities = new List<UnitObject>();
    4.  
    5. private void Start()
    6.     {
    7. Entities.Add(PlayerParty.UnitContainer.unitSlots[i].UnitObject);
    8. {
    9. }

    I've recently followed a tutorial on an Inventory system using scriptable objects and have adapted the system to be an Inventory system for units. A unit is a scriptable object that holds information about an entity like health and damage stats. The system works fine, however I have a problem now referencing my unit inventory. I have a inventory object that holds the scriptable objects for the units currently in my player's party. From my CombatController script I'm trying to get the scriptable objects of the units in my party to use in the combat system I'm creating. The scripts are pretty long but I'm pretty sure my error lies in how my Unit Object is declared.
    Here I create a UnitObject property.
    Code (CSharp):
    1. public class UnitInventorySlot
    2. {
    3.     public UnitObject UnitObject
    4.     {
    5.         get
    6.         {
    7.             if (unit.Id >= 0)
    8.                 return Unitparent.inventory.unitDatabase.GetUnit[unit.Id];
    9.    
    10.          return null;
    11.         }
    12.     }

    From the CombatController script I try to access the scriptableObjects in my party and add them to a list and I get a null reference exeption error.
    Code (CSharp):
    1. Entities.Add(PlayerParty.UnitContainer.unitSlots[i].UnitObject);
    How would I edit my scripts so that I can access the Scriptable Objects in my party without getting the error?
    Any help is appreciated.

    Original System That I modified -

    GitHub link for Inventory System - https://github.com/sniffle6/Scriptable-Object-Inventory
     
  2. SisusCo

    SisusCo

    Joined:
    Jan 29, 2019
    Posts:
    1,330
    You can start by figuring out which reference exactly is causing the NullReferenceException on that line.

    Code (CSharp):
    1. Debug.Assert(Entities != null, "Entities is null", this);
    2. Debug.Assert(PlayerParty.UnitContainer != null, "UnitContainer is null", this);
    3. Debug.Assert(PlayerParty.UnitContainer.unitSlots != null, "unitSlots is null", PlayerParty.UnitContainer);
    4. Debug.Assert(PlayerParty.UnitContainer.unitSlots[i] != null, $"unitSlots[{i}] is null", PlayerParty.UnitContainer);
    5.  
    6. Entities.Add(PlayerParty.UnitContainer.unitSlots[i].UnitObject);
    It could be that the UnitDatabaseObject contains a null element or it could be something else, as that is quite a long call chain you have going on there... :D
     
  3. Dlightb

    Dlightb

    Joined:
    Mar 9, 2021
    Posts:
    3
    I was at my wit's end yesterday, trying to figure out why i kept getting the error. This morning I thought about a potential work around and loaded up unity to try it and when I tested my game, I no longer got the error. I guess unity was having some kind of strange serialization error. I had thought I was misunderstanding something about properties since the null reference was coming from a property.
    Anyway thanks for your response. I'll be sure to shorten the script I include if I post here again.
     
    SisusCo likes this.