Forum begins after the advertisement:
[Part 15] Evolution level blocking upgrading items to that level
Home › Forums › Video Game Tutorial Series › Creating a Rogue-like Shoot-em Up in Unity › [Part 15] Evolution level blocking upgrading items to that level
- This topic has 16 replies, 3 voices, and was last updated 2 months, 2 weeks ago by Terence.
-
AuthorPosts
-
October 6, 2024 at 8:42 am #15969::
Hello. So if i set for ex. evolution Level to 2 for garlic to evolve in Soul Eater, I cant upgrade garlic to level 2. this error pop up:
View post on imgur.com
View post on imgur.com
<code>NullReferenceException: Object reference not set to an instance of an object PlayerInventory.Get (PassiveData type) (at Assets/Scripts/Player/PlayerInventory.cs:88) PlayerInventory.Get (ItemData type) (at Assets/Scripts/Player/PlayerInventory.cs:77) Item.CanEvolve (ItemData+Evolution evolution, System.Int32 levelUpAmount) (at Assets/Scripts/Passive Items/Item.cs:51) Item.AttemptEvolution (ItemData+Evolution evolutionData, System.Int32 levelUpAmount) (at Assets/Scripts/Passive Items/Item.cs:64) Item.DoLevelUp () (at Assets/Scripts/Passive Items/Item.cs:109) Weapon.DoLevelUp () (at Assets/Scripts/Weapons/Weapon.cs:102) AuraWeapon.DoLevelUp () (at Assets/Scripts/Weapons/AuraWeapon.cs:34) PlayerInventory.LevelUpWeapon (System.Int32 slotIndex, System.Int32 upgradeIndex) (at Assets/Scripts/Player/PlayerInventory.cs:266) PlayerInventory+<>c__DisplayClass21_1.<ApplyUpgradeOptions>b__1 () (at Assets/Scripts/Player/PlayerInventory.cs:349) UnityEngine.Events.InvokableCall.Invoke () (at <914d6100afbb4dcbb0365e05b2154b62>:0) UnityEngine.Events.UnityEvent.Invoke () (at <914d6100afbb4dcbb0365e05b2154b62>:0) UnityEngine.UI.Button.Press () (at Library/PackageCache/com.unity.ugui@1.0.0/Runtime/UI/Core/Button.cs:70) UnityEngine.UI.Button.OnPointerClick (UnityEngine.EventSystems.PointerEventData eventData) (at Library/PackageCache/com.unity.ugui@1.0.0/Runtime/UI/Core/Button.cs:114) UnityEngine.EventSystems.ExecuteEvents.Execute (UnityEngine.EventSystems.IPointerClickHandler handler, UnityEngine.EventSystems.BaseEventData eventData) (at Library/PackageCache/com.unity.ugui@1.0.0/Runtime/EventSystem/ExecuteEvents.cs:57) UnityEngine.EventSystems.ExecuteEvents.Execute[T] (UnityEngine.GameObject target, UnityEngine.EventSystems.BaseEventData eventData, UnityEngine.EventSystems.ExecuteEvents+EventFunction1[T1] functor) (at Library/PackageCache/com.unity.ugui@1.0.0/Runtime/EventSystem/ExecuteEvents.cs:272) UnityEngine.EventSystems.EventSystem:Update() (at Library/PackageCache/com.unity.ugui@1.0.0/Runtime/EventSystem/EventSystem.cs:514)</code>
If i set the level to 3 for garlic to evolve to Soul Eater, it can be upgraded to level 3 but not any further.
But if i have the other catalyst, for ex Pummarola and garlic i set to evolve in Soul Eater in level 2. if i get pummarola first, i can upgrade garlic to leve 2 and it evolves to Soul Eater.
Heres my code: Item.cs
<code>using System.Collections; using System.Collections.Generic; using UnityEditor.Build; using UnityEngine; public abstract class Item : MonoBehaviour { public int currentLevel = 1, maxLevel = 1; protected ItemData.Evolution[] evolutionData; protected PlayerInventory inventory; public PlayerStats owner; public virtual void Initialise(ItemData data) { maxLevel = data.maxLevel; // Store the evolution data as we have to track whether all catalysts are in the inventory so we can evolve evolutionData = data.evolutionData; // NOTE: Have to find a better way to refference the player inventory in future, this is inefficiant inventory = FindObjectOfType<PlayerInventory>(); owner = FindObjectOfType<PlayerStats>(); } // Call this function to get all the evolutions that the wepaon can currently evolve to public virtual ItemData.Evolution[] CanEvolve() { List<ItemData.Evolution> possibleEvolutions = new(); // Check each listed evolution and whether it is on the inventory foreach(ItemData.Evolution e in evolutionData) { if(CanEvolve(e)) possibleEvolutions.Add(e); } return possibleEvolutions.ToArray(); } // Checks if a specific evolution is possible public virtual bool CanEvolve(ItemData.Evolution evolution, int levelUpAmount = 1) { // Cannot evolve if the item hasnt reached the level to evolve if (evolution.evolutionLevel > currentLevel + levelUpAmount) { Debug.LogWarning(string.Format("Evolution Failed. Current level {0}, evolution level {1}", currentLevel, evolution.evolutionLevel)); return false; } // Checks to see if all the catalysts are in the inventory foreach(ItemData.Evolution.Config c in evolution.catalysts) { Item item = inventory.Get(c.itemType); if(!item || item.currentLevel < c.level) { Debug.LogWarning(string.Format("Evolution Failed. Missing {0}", c.itemType.name)); return false; } } return true; } // AttemptEvolution will spawn a new weapon for the character,a nd remove all the weapons that are supposed to be consumed public virtual bool AttemptEvolution(ItemData.Evolution evolutionData, int levelUpAmount = 1) { if(!CanEvolve(evolutionData, levelUpAmount)) return false; // should passives/weapons be consumed? bool consumePassives = (evolutionData.consumes & ItemData.Evolution.Consumption.passives) > 0; bool consumeWeapons = (evolutionData.consumes & ItemData.Evolution.Consumption.weapons) > 0; // Loop through the catalysts and check if we should consume them foreach(ItemData.Evolution.Config c in evolutionData.catalysts) { if (c.itemType is PassiveData && consumePassives) inventory.Remove(c.itemType, true); if (c.itemType is WeaponData && consumeWeapons) inventory.Remove(c.itemType, true); } // Should we consume ourselves as well if (this is Passive && consumePassives) inventory.Remove((this as Passive).data, true); else if (this is Weapon && consumeWeapons) inventory.Remove((this as Weapon).data, true); // Ad the new weapon onto inventory inventory.Add(evolutionData.outcome.itemType); return true; } public virtual bool CanLevelUp() { return currentLevel <= maxLevel; } // Whenever an item levels up, attemp to evolve public virtual bool DoLevelUp() { if (evolutionData == null) return true; // Tries to evolve into every listed evolution of this weapon if the weapons evolution condition is levelinh ip foreach(ItemData.Evolution e in evolutionData) { if(e.condition == ItemData.Evolution.Condition.auto) AttemptEvolution(e); } return true; } // What effects owner recieve on equiping an item public virtual void OnEquip() { } // What effects are removed on unequiping an utem public virtual void OnUnequip() { } }</code>
PlayerInventory.cs
<code>using System; using System.Collections; using System.Collections.Generic; using TMPro; using UnityEngine; using UnityEngine.UI; public class PlayerInventory : MonoBehaviour { [System.Serializable] public class Slot { public Item item; public Image image; public void Assign(Item assignedItem) { this.item = assignedItem; if(item is Weapon) { Weapon w = item as Weapon; image.enabled = true; image.sprite = w.data.icon; } else { Passive p = item as Passive; image.enabled = true; image.sprite = p.data.icon; } Debug.Log(string.Format("Assigned {0} to player", item.name)); } public void Clear() { item = null; image.enabled = false; image.sprite = null; } public bool IsEmpty() { return item == null; } } public List<Slot> weaponSlots = new(6); public List<Slot> passiveSlots = new(6); [System.Serializable] public class UpgradeUI { public TMP_Text upgradeNameDisplay; public TMP_Text upgradeDescriptionDisplay; public Image upgradeIcon; public Button upgradeButton; } [Header("UI elements")] public List<WeaponData> avaiableWeapons = new(); public List<PassiveData> avaiablePassives = new(); public List<UpgradeUI> upgradeUIOptions = new(); PlayerStats player; void Start() { player = GetComponent<PlayerStats>(); } // Checks if the inventory has an item of a certaint type public bool Has(ItemData type) { return Get(type); } public Item Get(ItemData type) { if(type is WeaponData) return Get(type as WeaponData); else if(type is PassiveData) return Get(type as PassiveData); return null; } // Find a passive of a certain type in the inventory public Passive Get(PassiveData type) { foreach(Slot s in passiveSlots) { Passive p = s.item as Passive; if(p.data == type) return p; } return null; } //Find a weapon of certain type in the inventory public Weapon Get(WeaponData type) { foreach (Slot s in weaponSlots) { Weapon w = s.item as Weapon; if (w.data == type) return w; } return null; } //Removes a weapon of a particular type, as specified by data public bool Remove(WeaponData data, bool removeUpgradeAvailability = false) { // Remove this weapon from the upgrade pool if (removeUpgradeAvailability) avaiableWeapons.Remove(data); for (int i = 0; i < weaponSlots.Count; i++) { Weapon w = weaponSlots[i].item as Weapon; if (w.data == data) { weaponSlots[i].Clear(); w.OnUnequip(); Destroy(w.gameObject); return true; } } return false; } //Removes a passive of a particular type, as specified by data public bool Remove(PassiveData data, bool removeUpgradeAvailability = false) { if (removeUpgradeAvailability) avaiablePassives.Remove(data); for (int i = 0; i < passiveSlots.Count; i++) { Passive p = passiveSlots[i].item as Passive; if (p.data == data) { weaponSlots[i].Clear(); p.OnUnequip(); Destroy(p.gameObject); return true; } } return false; } // If an ItemData is passed, determine what type it is and call the respective overload public bool Remove(ItemData data, bool removeUpgradeAvailability = false) { if(data is PassiveData) return Remove(data as PassiveData, removeUpgradeAvailability); else if(data is WeaponData) return Remove(data as WeaponData, removeUpgradeAvailability); return false; } // Finds an empty slot and adds a wepaon of certain type, returns the slot number that the item was put in public int Add(WeaponData data) { int slotNum = -1; // Try to find an empty slot for(int i = 0; i < weaponSlots.Capacity; i++) { if (weaponSlots[i].IsEmpty()) { slotNum = i; break; } } // if theres no empty slot, exit if (slotNum < 0) return slotNum; // Otherwise create the weapon in the slot // Get the type of the weapon we want to spawn Type weaponType = Type.GetType(data.behaviour); if(weaponType != null) { // Spawn the weapon gameObject GameObject go = new(data.baseStats.name + " Controller"); Weapon spawnedWeapon = (Weapon)go.AddComponent(weaponType); spawnedWeapon.Initialise(data); spawnedWeapon.transform.SetParent(transform); spawnedWeapon.transform.localPosition = Vector2.zero; spawnedWeapon.OnEquip(); // Assign the weapon to the slot weaponSlots[slotNum].Assign(spawnedWeapon); // Close the level ip UI if it is on if(GameManager.Instance != null && GameManager.Instance.choosingUpgrade) GameManager.Instance.EndLevelUp(); return slotNum; } else { Debug.LogWarning(string.Format("Invalid weapon type specified for {0}", data.name)); } return -1; } // Finds an empty slot and adds a passive of a certain type, returns the slot number that the item was put in public int Add(PassiveData data) { int slotNum = -1; // Try to find an empty slot for (int i = 0; i < passiveSlots.Capacity; i++) { if (passiveSlots[i].IsEmpty()) { slotNum = i; break; } } // if theres no empty slot, exit if (slotNum < 0) return slotNum; // Otherwise create the weapon in the slot // Get the type of the weapon we want to spawn // Spawn the weapon gameObject GameObject go = new(data.baseStats.name + " Passive"); Passive p = go.AddComponent<Passive>(); p.Initialise(data); p.transform.SetParent(transform); p.transform.localPosition = Vector2.zero; // Assign the weapon to the slot passiveSlots[slotNum].Assign(p); // Close the level ip UI if it is on if (GameManager.Instance != null && GameManager.Instance.choosingUpgrade) GameManager.Instance.EndLevelUp(); player.RecalculateStats(); return slotNum; } // If we dont know what item is being added, this function will determine that public int Add(ItemData data) { if(data is WeaponData) return Add(data as WeaponData); else if(data is PassiveData) return Add(data as PassiveData); return -1; } public void LevelUpWeapon(int slotIndex, int upgradeIndex) { if(weaponSlots.Count > slotIndex) { Weapon weapon = weaponSlots[slotIndex].item as Weapon; // Dont level up the weapon if it is already at max level if (!weapon.DoLevelUp()) { Debug.LogWarning(string.Format("Failed to level up {0}", weapon.name)); return; } } if (GameManager.Instance != null && GameManager.Instance.choosingUpgrade) GameManager.Instance.EndLevelUp(); } public void LevelUpPassiveItem(int slotIndex, int upgradeIndex) { if(passiveSlots.Count > slotIndex) { Passive p = passiveSlots[slotIndex].item as Passive; if (!p.DoLevelUp()) { Debug.LogWarning(string.Format("Failed to level up {0}", p.name)); return; } } if(GameManager.Instance != null && GameManager.Instance.choosingUpgrade) GameManager.Instance.EndLevelUp(); player.RecalculateStats(); } // Determaines what upgrade options should apear void ApplyUpgradeOptions() { // Make a duplicate of the avaiable weapon / passive upgrade lists List<WeaponData> avaiableWeaponUpgrades = new(avaiableWeapons); List<PassiveData> avaiablePassiveItemUpgrades = new(avaiablePassives); // Iterate through each slot in the upgrade UI foreach (UpgradeUI upgradeOption in upgradeUIOptions) { // If there are no more avaiable upgrades, then abort if (avaiableWeaponUpgrades.Count == 0 && avaiablePassiveItemUpgrades.Count == 0) return; // Determine whether this upgrade should be for a passive or active weapons int upgradeType; if (avaiableWeaponUpgrades.Count == 0) upgradeType = 2; else if (avaiablePassiveItemUpgrades.Count == 0) upgradeType = 1; else // random generates a number between 1 and 2 upgradeType = UnityEngine.Random.Range(1, 3); // Generates an active weapon upgrade if (upgradeType == 1) { // Pick a weapon upgrade, them remove it so that we dont get it twice WeaponData chosenWeaponUpgrade = avaiableWeaponUpgrades[UnityEngine.Random.Range(0, avaiableWeaponUpgrades.Count)]; avaiableWeaponUpgrades.Remove(chosenWeaponUpgrade); // Ensures that the selected weapon data is valid if (chosenWeaponUpgrade != null) { // Turns on the UI slot EnableUpgradeUI(upgradeOption); // Loops through all existing weapons. If we find a match, will hook an event listtener to the button that will level up the weapon when the upgrade option is clicked bool isLevelUp = false; for (int i = 0; i < weaponSlots.Count; i++) { Weapon w = weaponSlots[i].item as Weapon; if (w != null && w.data == chosenWeaponUpgrade) { // If the weapon is already at max level, do not allow upgrade if (chosenWeaponUpgrade.maxLevel <= w.currentLevel) { DisableUpgradeUI(upgradeOption); isLevelUp = true; break; } // Set the Event Listener, item and level description to be that of the next level upgradeOption.upgradeButton.onClick.AddListener(() => LevelUpWeapon(i, i)); Weapon.Stats nextLevel = chosenWeaponUpgrade.GetLevelData(w.currentLevel + 1); upgradeOption.upgradeDescriptionDisplay.text = nextLevel.description; upgradeOption.upgradeNameDisplay.text = nextLevel.name; upgradeOption.upgradeIcon.sprite = chosenWeaponUpgrade.icon; isLevelUp = true; break; } } // If the code gets here, it means that it will be adding a new weapon, instead of upgrading existing weapon if (!isLevelUp) { upgradeOption.upgradeButton.onClick.AddListener(() => Add(chosenWeaponUpgrade)); upgradeOption.upgradeDescriptionDisplay.text = chosenWeaponUpgrade.baseStats.description; upgradeOption.upgradeNameDisplay.text = chosenWeaponUpgrade.baseStats.name; upgradeOption.upgradeIcon.sprite = chosenWeaponUpgrade.icon; } } } else if (upgradeType == 2) { // NOTE: I have to recode this system, as right now it disables an upgrade slot if i hit a weapon that has already reached max level PassiveData chosenPassiveUpgrade = avaiablePassiveItemUpgrades[UnityEngine.Random.Range(0, avaiablePassiveItemUpgrades.Count)]; avaiablePassiveItemUpgrades.Remove(chosenPassiveUpgrade); if (chosenPassiveUpgrade != null) { // Turn on the UI slot EnableUpgradeUI(upgradeOption); // Loops through all existing passives. If theres a match it will hook an event listener to the button what will level up the passive bool isLevelUp = false; for (int i = 0; i < passiveSlots.Count; i++) { Passive p = passiveSlots[i].item as Passive; if (p != null && p.data == chosenPassiveUpgrade) { // If the passive is already at max level, do not allow upgrade if (chosenPassiveUpgrade.maxLevel <= p.currentLevel) { DisableUpgradeUI(upgradeOption); isLevelUp = true; break; } upgradeOption.upgradeButton.onClick.AddListener(() => LevelUpPassiveItem(i, i)); Passive.Modifier nextLevel = chosenPassiveUpgrade.GetLevelData(p.currentLevel + 1); upgradeOption.upgradeDescriptionDisplay.text = nextLevel.description; upgradeOption.upgradeNameDisplay.text = nextLevel.name; upgradeOption.upgradeIcon.sprite = chosenPassiveUpgrade.icon; isLevelUp = true; break; } } if (!isLevelUp) // Spawn a new passive item { upgradeOption.upgradeButton.onClick.AddListener(() => Add(chosenPassiveUpgrade)); Passive.Modifier nextLevel = chosenPassiveUpgrade.baseStats; upgradeOption.upgradeDescriptionDisplay.text = nextLevel.description; upgradeOption.upgradeNameDisplay.text = nextLevel.name; upgradeOption.upgradeIcon.sprite = chosenPassiveUpgrade.icon; } } } } } void RemoveUpgradeOptions() { foreach(UpgradeUI upgradeOption in upgradeUIOptions) { upgradeOption.upgradeButton.onClick.RemoveAllListeners(); DisableUpgradeUI(upgradeOption); } } public void RemoveAndApplyUpgrades() { RemoveUpgradeOptions(); ApplyUpgradeOptions(); } void DisableUpgradeUI(UpgradeUI ui) { ui.upgradeNameDisplay.transform.parent.gameObject.SetActive(false); } void EnableUpgradeUI(UpgradeUI ui) { ui.upgradeNameDisplay.transform.parent.gameObject.SetActive(true); } }</code>
October 6, 2024 at 4:00 pm #15970::It seems like the
NullReferenceException
is blocking the complete execution of your code. Change theGet()
andRemove()
functions in your code as follows:// Find a passive of a certain type in the inventory public Passive Get(PassiveData type) { foreach(Slot s in passiveSlots) { Passive p = s.item as Passive; if(p && p.data == type) return p; } return null; } //Find a weapon of certain type in the inventory public Weapon Get(WeaponData type) { foreach (Slot s in weaponSlots) { Weapon w = s.item as Weapon; if (w && w.data == type) return w; } return null; } //Removes a weapon of a particular type, as specified by data public bool Remove(WeaponData data, bool removeUpgradeAvailability = false) { // Remove this weapon from the upgrade pool if (removeUpgradeAvailability) avaiableWeapons.Remove(data); for (int i = 0; i < weaponSlots.Count; i++) { Weapon w = weaponSlots[i].item as Weapon; if (w && w.data == data) { weaponSlots[i].Clear(); w.OnUnequip(); Destroy(w.gameObject); return true; } } return false; } //Removes a passive of a particular type, as specified by data public bool Remove(PassiveData data, bool removeUpgradeAvailability = false) { if (removeUpgradeAvailability) avaiablePassives.Remove(data); for (int i = 0; i < passiveSlots.Count; i++) { Passive p = passiveSlots[i].item as Passive; if (p && p.data == data) { weaponSlots[i].Clear(); p.OnUnequip(); Destroy(p.gameObject); return true; } } return false; }
This is because a
NullReferenceException
occurs in the lines where we accessp.data
orw.data
if either of the variables is null. These variables will be null if we are searching for a passive, and come across a weapon instead, becauses.item as Passive
will fail and return null, and vice versa if we are searching for a weapon and come across a passive.By adding the green highlighted sections, we prevent the code from executing if the conversion fails.
Let me know if this fixes the issue!
October 6, 2024 at 9:56 pm #15972::Hello Terence. Thank your for your help. This fixed the upgrade lock issue. But now i have another. If soul eater requires Level 2 Harlic and Level 1 Pummarola, if i get Garlic to level 2 and Pummarola to level 1, it doesnt evolve, but if i upgrade Pummarola to Level 2 too, then it proceeds to evolve.
I get this console error when i have Garlic Level 2 and get Pummarola Level 1:
<code>Evolution Failed. Missing Pummarola UnityEngine.Debug:LogWarning (object) Item:CanEvolve (ItemData/Evolution,int) (at Assets/Scripts/Passive Items/Item.cs:54) Item:AttemptEvolution (ItemData/Evolution,int) (at Assets/Scripts/Passive Items/Item.cs:64) Item:DoLevelUp () (at Assets/Scripts/Passive Items/Item.cs:109) Weapon:DoLevelUp () (at Assets/Scripts/Weapons/Weapon.cs:102) AuraWeapon:DoLevelUp () (at Assets/Scripts/Weapons/AuraWeapon.cs:34) PlayerInventory:LevelUpWeapon (int,int) (at Assets/Scripts/Player/PlayerInventory.cs:266) PlayerInventory/<>c__DisplayClass21_1:<ApplyUpgradeOptions>b__1 () (at Assets/Scripts/Player/PlayerInventory.cs:349) UnityEngine.EventSystems.EventSystem:Update () (at Library/PackageCache/com.unity.ugui@1.0.0/Runtime/EventSystem/EventSystem.cs:514)</code>
View post on imgur.com
But again if i get First Pummarola to Level 1, and then upgrade Garlic to Level 2, it works jsut fine.
So if i first meet the passive catalyst requiremets it works fine, but if i start firt with meeting weapon catalyst requirements, something goes wrong.
Also this message pops up when i first upgrade Garlic to level 2 without having Pammarola in inventory.
View post on imgur.com
Evolution Failed. Missing Pummarola
<code>UnityEngine.Debug:LogWarning (object) Item:CanEvolve (ItemData/Evolution,int) (at Assets/Scripts/Passive Items/Item.cs:54) Item:AttemptEvolution (ItemData/Evolution,int) (at Assets/Scripts/Passive Items/Item.cs:64) Item:DoLevelUp () (at Assets/Scripts/Passive Items/Item.cs:109) Weapon:DoLevelUp () (at Assets/Scripts/Weapons/Weapon.cs:102) AuraWeapon:DoLevelUp () (at Assets/Scripts/Weapons/AuraWeapon.cs:34) PlayerInventory:LevelUpWeapon (int,int) (at Assets/Scripts/Player/PlayerInventory.cs:266) PlayerInventory/<>c__DisplayClass21_1:<ApplyUpgradeOptions>b__1 () (at Assets/Scripts/Player/PlayerInventory.cs:349) UnityEngine.EventSystems.EventSystem:Update () (at Library/PackageCache/com.unity.ugui@1.0.0/Runtime/EventSystem/EventSystem.cs:514)</code>
I think its something with the order of catalysts requrements for evolution.
Thank you for your quick responses, your wisdom is much appreciated.
October 6, 2024 at 10:11 pm #15973::You need to add the Evolution data on both sides. The Garlic requires the Pummarola, and on the Pummarola you need to add the Garlic as well.
October 6, 2024 at 10:17 pm #15974October 7, 2024 at 3:04 pm #15981::Can you add the following line to the
CanEvolve()
function and show me the output on your Console when you try evolving it the other way?// Checks if a specific evolution is possible public virtual bool CanEvolve(ItemData.Evolution evolution, int levelUpAmount = 1) { // Cannot evolve if the item hasnt reached the level to evolve if (evolution.evolutionLevel > currentLevel + levelUpAmount) { Debug.LogWarning(string.Format("Evolution Failed. Current level {0}, evolution level {1}", currentLevel, evolution.evolutionLevel)); return false; } // Checks to see if all the catalysts are in the inventory foreach(ItemData.Evolution.Config c in evolution.catalysts) { Item item = inventory.Get(c.itemType); print($"Trying to evolve {c.itemType}. Current level is {item.currentLevel} and requirement is {c.level}."); if(!item || item.currentLevel < c.level) { Debug.LogWarning(string.Format("Evolution Failed. Missing {0}", c.itemType.name)); return false; } } return true; }
October 7, 2024 at 9:58 pm #15989::Hello boss. This is what pops up when i click the upgrade the garlic to level 2 without having Pummarola.
View post on imgur.com
<code>NullReferenceException: Object reference not set to an instance of an object Item.CanEvolve (ItemData+Evolution evolution, System.Int32 levelUpAmount) (at Assets/Scripts/Passive Items/Item.cs:54) Item.AttemptEvolution (ItemData+Evolution evolutionData, System.Int32 levelUpAmount) (at Assets/Scripts/Passive Items/Item.cs:67) Item.DoLevelUp () (at Assets/Scripts/Passive Items/Item.cs:112) Weapon.DoLevelUp () (at Assets/Scripts/Weapons/Weapon.cs:90) AuraWeapon.DoLevelUp () (at Assets/Scripts/Weapons/AuraWeapon.cs:35) PlayerInventory.LevelUpWeapon (System.Int32 slotIndex, System.Int32 upgradeIndex) (at Assets/Scripts/Player/PlayerInventory.cs:266) PlayerInventory+<>c__DisplayClass21_1.<ApplyUpgradeOptions>b__1 () (at Assets/Scripts/Player/PlayerInventory.cs:349) UnityEngine.Events.InvokableCall.Invoke () (at <914d6100afbb4dcbb0365e05b2154b62>:0) UnityEngine.Events.UnityEvent.Invoke () (at <914d6100afbb4dcbb0365e05b2154b62>:0) UnityEngine.UI.Button.Press () (at Library/PackageCache/com.unity.ugui@1.0.0/Runtime/UI/Core/Button.cs:70) UnityEngine.UI.Button.OnPointerClick (UnityEngine.EventSystems.PointerEventData eventData) (at Library/PackageCache/com.unity.ugui@1.0.0/Runtime/UI/Core/Button.cs:114) UnityEngine.EventSystems.ExecuteEvents.Execute (UnityEngine.EventSystems.IPointerClickHandler handler, UnityEngine.EventSystems.BaseEventData eventData) (at Library/PackageCache/com.unity.ugui@1.0.0/Runtime/EventSystem/ExecuteEvents.cs:57) UnityEngine.EventSystems.ExecuteEvents.Execute[T] (UnityEngine.GameObject target, UnityEngine.EventSystems.BaseEventData eventData, UnityEngine.EventSystems.ExecuteEvents+EventFunction 1[T1] functor) (at Library/PackageCache/com.unity.ugui@1.0.0/Runtime/EventSystem/ExecuteEvents.cs:272) UnityEngine.EventSystems.EventSystem:Update() (at Library/PackageCache/com.unity.ugui@1.0.0/Runtime/EventSystem/EventSystem.cs:514)</code>
And now its not giving me to upgrade the Garlic to level 2. Again if i first get Pammarola first, no problem at sight. Thank you for giving your time for me.
Item.cs
<code>using System.Collections; using System.Collections.Generic; using UnityEditor.Build; using UnityEngine; public abstract class Item : MonoBehaviour { public int currentLevel = 1, maxLevel = 1; protected ItemData.Evolution[] evolutionData; protected PlayerInventory inventory; protected PlayerStats owner; public PlayerStats Owner { get { return owner; } } public virtual void Initialise(ItemData data) { maxLevel = data.maxLevel; // Store the evolution data as we have to track whether all catalysts are in the inventory so we can evolve evolutionData = data.evolutionData; // NOTE: Have to find a better way to refference the player inventory in future, this is inefficiant inventory = FindObjectOfType<PlayerInventory>(); owner = FindObjectOfType<PlayerStats>(); } // Call this function to get all the evolutions that the wepaon can currently evolve to public virtual ItemData.Evolution[] CanEvolve() { List<ItemData.Evolution> possibleEvolutions = new(); // Check each listed evolution and whether it is on the inventory foreach(ItemData.Evolution e in evolutionData) { if(CanEvolve(e)) possibleEvolutions.Add(e); } return possibleEvolutions.ToArray(); } // Checks if a specific evolution is possible public virtual bool CanEvolve(ItemData.Evolution evolution, int levelUpAmount = 1) { // Cannot evolve if the item hasnt reached the level to evolve if (evolution.evolutionLevel > currentLevel + levelUpAmount) { Debug.LogWarning(string.Format("Evolution Failed. Current level {0}, evolution level {1}", currentLevel, evolution.evolutionLevel)); return false; } // Checks to see if all the catalysts are in the inventory foreach(ItemData.Evolution.Config c in evolution.catalysts) { Item item = inventory.Get(c.itemType); print($"Trying to evolve {c.itemType}. Current level is {item.currentLevel} and requirement is {c.level}."); if (!item || item.currentLevel < c.level) { Debug.LogWarning(string.Format("Evolution Failed. Missing {0}", c.itemType.name)); return false; } } return true; } // AttemptEvolution will spawn a new weapon for the character,a nd remove all the weapons that are supposed to be consumed public virtual bool AttemptEvolution(ItemData.Evolution evolutionData, int levelUpAmount = 1) { if(!CanEvolve(evolutionData, levelUpAmount)) return false; // should passives/weapons be consumed? bool consumePassives = (evolutionData.consumes & ItemData.Evolution.Consumption.passives) > 0; bool consumeWeapons = (evolutionData.consumes & ItemData.Evolution.Consumption.weapons) > 0; // Loop through the catalysts and check if we should consume them foreach(ItemData.Evolution.Config c in evolutionData.catalysts) { if (c.itemType is PassiveData && consumePassives) inventory.Remove(c.itemType, true); if (c.itemType is WeaponData && consumeWeapons) inventory.Remove(c.itemType, true); } // Should we consume ourselves as well if (this is Passive && consumePassives) inventory.Remove((this as Passive).data, true); else if (this is Weapon && consumeWeapons) inventory.Remove((this as Weapon).data, true); // Ad the new weapon onto inventory inventory.Add(evolutionData.outcome.itemType); return true; } public virtual bool CanLevelUp() { return currentLevel <= maxLevel; } // Whenever an item levels up, attemp to evolve public virtual bool DoLevelUp() { if (evolutionData == null) return true; // Tries to evolve into every listed evolution of this weapon if the weapons evolution condition is levelinh ip foreach(ItemData.Evolution e in evolutionData) { if(e.condition == ItemData.Evolution.Condition.auto) AttemptEvolution(e); } return true; } // What effects owner recieve on equiping an item public virtual void OnEquip() { } // What effects are removed on unequiping an utem public virtual void OnUnequip() { } }</code>
October 7, 2024 at 11:08 pm #15992::My bad, the null reference isn’t supposed to happen. It’s an oversight with my line of code. Can you move it into the if condition again and tell me what it prints?
// Checks if a specific evolution is possible public virtual bool CanEvolve(ItemData.Evolution evolution, int levelUpAmount = 1) { // Cannot evolve if the item hasnt reached the level to evolve if (evolution.evolutionLevel > currentLevel + levelUpAmount) { Debug.LogWarning(string.Format("Evolution Failed. Current level {0}, evolution level {1}", currentLevel, evolution.evolutionLevel)); return false; } // Checks to see if all the catalysts are in the inventory foreach(ItemData.Evolution.Config c in evolution.catalysts) { Item item = inventory.Get(c.itemType);
print($"Trying to evolve {c.itemType}. Current level is {item.currentLevel} and requirement is {c.level}.");if(!item || item.currentLevel < c.level) { print($"Trying to evolve {c.itemType}. Current level is {item.currentLevel} and requirement is {c.level}."); Debug.LogWarning(string.Format("Evolution Failed. Missing {0}", c.itemType.name)); return false; } } return true; }October 7, 2024 at 11:11 pm #15993::<code>NullReferenceException: Object reference not set to an instance of an object Item.CanEvolve (ItemData+Evolution evolution, System.Int32 levelUpAmount) (at Assets/Scripts/Passive Items/Item.cs:56) Item.AttemptEvolution (ItemData+Evolution evolutionData, System.Int32 levelUpAmount) (at Assets/Scripts/Passive Items/Item.cs:67) Item.DoLevelUp () (at Assets/Scripts/Passive Items/Item.cs:112) Weapon.DoLevelUp () (at Assets/Scripts/Weapons/Weapon.cs:90) AuraWeapon.DoLevelUp () (at Assets/Scripts/Weapons/AuraWeapon.cs:37) PlayerInventory.LevelUpWeapon (System.Int32 slotIndex, System.Int32 upgradeIndex) (at Assets/Scripts/Player/PlayerInventory.cs:266) PlayerInventory+<>c__DisplayClass21_1.<ApplyUpgradeOptions>b__1 () (at Assets/Scripts/Player/PlayerInventory.cs:349) UnityEngine.Events.InvokableCall.Invoke () (at <914d6100afbb4dcbb0365e05b2154b62>:0) UnityEngine.Events.UnityEvent.Invoke () (at <914d6100afbb4dcbb0365e05b2154b62>:0) UnityEngine.UI.Button.Press () (at Library/PackageCache/com.unity.ugui@1.0.0/Runtime/UI/Core/Button.cs:70) UnityEngine.UI.Button.OnPointerClick (UnityEngine.EventSystems.PointerEventData eventData) (at Library/PackageCache/com.unity.ugui@1.0.0/Runtime/UI/Core/Button.cs:114) UnityEngine.EventSystems.ExecuteEvents.Execute (UnityEngine.EventSystems.IPointerClickHandler handler, UnityEngine.EventSystems.BaseEventData eventData) (at Library/PackageCache/com.unity.ugui@1.0.0/Runtime/EventSystem/ExecuteEvents.cs:57) UnityEngine.EventSystems.ExecuteEvents.Execute[T] (UnityEngine.GameObject target, UnityEngine.EventSystems.BaseEventData eventData, UnityEngine.EventSystems.ExecuteEvents+EventFunction1[T1] functor) (at Library/PackageCache/com.unity.ugui@1.0.0/Runtime/EventSystem/ExecuteEvents.cs:272) UnityEngine.EventSystems.EventSystem:Update() (at Library/PackageCache/com.unity.ugui@1.0.0/Runtime/EventSystem/EventSystem.cs:514)</code>
View post on imgur.com
The same thing boss :(
October 8, 2024 at 1:42 am #15995::Hi, I have the same problem, my pummarola is blocked from leveling up to lv2(max level to evolve), it popped up NullReferenceException when I try to select the upgrade. The error is at this line
Item item = inventory.Get(c.itemType);
Item.cs<code> using System.Collections.Generic; using UnityEngine; /// <summary> /// Base class for both the Passive and the Weapon classes. It is primarily intended /// to handle weapon evolution, as we want both weapons and passives to be evolve-able. /// </summary> public abstract class Item : MonoBehaviour { public int currentLevel = 1, maxLevel = 1; [HideInInspector] public ItemData data; protected ItemData.Evolution[] evolutionData; protected PlayerInventory inventory; protected PlayerStats owner; public PlayerStats Owner { get { return owner; } } [System.Serializable] public class LevelData { public string name, description; } public virtual void Initialise(ItemData data) { maxLevel = data.maxLevel; // Store the evolution data as we have to track whether // all the catalysts are in the inventory so we can evolve. evolutionData = data.evolutionData; // We have to find a better way to reference the player inventory // in future, as this is inefficient. inventory = GetComponentInParent<PlayerInventory>(); owner = GetComponentInParent<PlayerStats>(); } // Call this function to get all the evolutions that the weapon // can currently evolve to. public virtual ItemData.Evolution[] CanEvolve() { List<ItemData.Evolution> possibleEvolutions = new List<ItemData.Evolution>(); // Check each listed evolution and whether it is in // the inventory. foreach (ItemData.Evolution e in evolutionData) { if (CanEvolve(e)) possibleEvolutions.Add(e); } return possibleEvolutions.ToArray(); } // Checks if a specific evolution is possible. public virtual bool CanEvolve(ItemData.Evolution evolution, int levelUpAmount = 1) { // Cannot evolve if the item hasn't reached the level to evolve. if (evolution.evolutionLevel > currentLevel + levelUpAmount) { Debug.LogWarning(string.Format("Evolution failed. Current level {0}, evolution level {1}", currentLevel, evolution.evolutionLevel)); return false; } // Checks to see if all the catalysts are in the inventory. foreach (ItemData.Evolution.Config c in evolution.catalysts) { Item item = inventory.Get(c.itemType); if (!item || item.currentLevel < c.level) { Debug.LogWarning(string.Format("Evolution failed. Missing {0}", c.itemType.name)); return false; } } return true; } // AttemptEvolution will spawn a new weapon for the character, and remove all // the weapons that are supposed to be consumed. public virtual bool AttemptEvolution(ItemData.Evolution evolutionData, int levelUpAmount = 1) { if (!CanEvolve(evolutionData, levelUpAmount)) return false; // Should we consume passives / weapons? bool consumePassives = (evolutionData.consumes & ItemData.Evolution.Consumption.passives) > 0; bool consumeWeapons = (evolutionData.consumes & ItemData.Evolution.Consumption.weapons) > 0; // Loop through all the catalysts and check if we should consume them. foreach (ItemData.Evolution.Config c in evolutionData.catalysts) { if (c.itemType is PassiveData && consumePassives) inventory.Remove(c.itemType, true); if (c.itemType is WeaponData && consumeWeapons) inventory.Remove(c.itemType, true); } // Should we consume ourselves as well? if (this is Passive && consumePassives) inventory.Remove((this as Passive).data, true); else if (this is Weapon && consumeWeapons) inventory.Remove((this as Weapon).data, true); // Add the new weapon onto our inventory. inventory.Add(evolutionData.outcome.itemType); return true; } public virtual bool CanLevelUp() { return currentLevel <= maxLevel; } // Whenever an item levels up, attempt to make it evolve. public virtual bool DoLevelUp() { if (evolutionData == null) return true; // Tries to evolve into every listed evolution of this weapon, // if the weapon's evolution condition is levelling up. foreach (ItemData.Evolution e in evolutionData) { if (e.condition == ItemData.Evolution.Condition.auto) AttemptEvolution(e); } return true; } // What effects you receive on equipping an item. public virtual void OnEquip() { } // What effects are removed on unequipping an item. public virtual void OnUnequip() { } } </code>
October 8, 2024 at 8:03 pm #15999::It looks like
inventory.Get()
isn’t working properly. Can you add these messages onto theGet()
function in yourPlayerInventory
script and test this again?// Find a passive of a certain type in the inventory public Passive Get(PassiveData type) { print("Calling Get() for Passive"); foreach(Slot s in passiveSlots) { Passive p = s.item as Passive; if(p && p.data == type) return p; } return null; } //Find a weapon of certain type in the inventory public Weapon Get(WeaponData type) { print("Calling Get() for Weapon"); foreach (Slot s in weaponSlots) { Weapon w = s.item as Weapon; if (w && w.data == type) return w; } return null; } public Item Get(ItemData type) { print("Calling Get() for with undetermined Item type"); if(type is WeaponData) return Get(type as WeaponData); else if(type is PassiveData) return Get(type as PassiveData); return null; }
October 8, 2024 at 10:21 pm #16002::Kai, your issue seems to be different. It seems like your Item script is unable to find the
PlayerInventory
, causing theinventory
variable to be null. That is why when you doinventory.Get()
, you get a NullReferenceException.Make sure that your items are parented under the player GameObject, and that the
PlayerInventory
script is on the player GameObject, because the items useGetComponentInParent()
to find thePlayerInventory
script.October 9, 2024 at 9:37 am #16009::Hello boss. So i start the game as a Garlic character and the controller is set up right:
View post on imgur.com
After i kill the first enemy and player level goes to 2 and the Upgrade window shows up this is in console:
After i pick Garlic Level 2 this shows up:
After i get Pummarola the evolve doesnt happen and this shows up in the console:
Heres the whole console if i get Garlic Level 1 > Garlic Level 2 > Pummarola Level 1 – the evolve doesnt happen:
And heres the whole console if i go Garlic Level 1 > Pummarola Level 1 > Garlic Level 2 – the evolve does happen:
I tried with more weapons but the result is the same if i go weapon first then passive the evolve doesnt happen. Here is the test with the knife. Im really demotivated rn. Trying to solve this for a weak :(
Thank you for your time, and for trying helping me.
October 9, 2024 at 8:41 pm #16013::Do you mind sending your project files to me over Google Drive? I am streaming tomorrow and I can do the debugging on stream tomorrow so you can see how I find the issue, if you don’t mind. Zip up your Asset, ProjectSettings and Packages folder and share the zip using a Google Drive link.
October 9, 2024 at 11:34 pm #16015::It would be interresting watching the stream to see there did i screw up :). What timezone are you in boss?
Also there is another problem that i cant deal with it. In Levelup screen when there is the upgrade option template. when there are 4 options, the top one is the template with the default text and images, and the other 3 are overrited with the correct item data. Idk why the template doenst show itemdata. If the upgrade options are 3, there is no such a problem.
-
AuthorPosts
- You must be logged in to reply to this topic.
Advertisement below: