Get 10% off orders above 50% with SEPT2025.
Forum begins after the advertisement:
[Part 16] Evolution bug
Home › Forums › Video Game Tutorial Series › Creating a Rogue-like Shoot-em Up in Unity › [Part 16] Evolution bug
- This topic has 26 replies, 3 voices, and was last updated 1 week, 2 days ago by
Alp Apustaja.
-
AuthorPosts
-
September 6, 2025 at 1:29 pm #18817::
Seems like the problem is with your Garlic weapon. Can you share your
AuraWeapon
script?September 6, 2025 at 8:35 pm #18818::Okay, here’s the AuraWeapon code.
Code : AuraWeapon
using UnityEngine; public class AuraWeapon : Weapon { protected Aura currentAura; // Update is called once per frame protected override void Update() { } public override void OnEquip() { // Try to replace the aura the weapon has with a new one. if (currentStats.auraPrefab) { if (currentAura) Destroy(currentAura); currentAura = Instantiate(currentStats.auraPrefab, transform); currentAura.weapon = this; currentAura.owner = owner; currentAura.transform.localScale = new Vector3(currentStats.area, currentStats.area, currentStats.area); } } public override void OnUnequip() { if (currentAura) Destroy(currentAura); } public override bool DoLevelUp() { if (!base.DoLevelUp()) return false; // If there is an aura attached to this weapon, we update the aura. if (currentAura) { currentAura.transform.localScale = new Vector3(currentStats.area, currentStats.area, currentStats.area); } return true; } }
September 6, 2025 at 8:40 pm #18819::The AuraWeapon code looks correct and matches the reference information provided earlier. It implements the specific behavior for an aura-based weapon (like Garlic) by:
- Creating an aura when the weapon is equipped
- Destroying the aura when the weapon is unequipped
- Updating the aura’s scale when the weapon levels up
There are no apparent issues with this implementation. Would you like me to elaborate on any specific part of the code?
September 6, 2025 at 10:53 pm #18820::@Alp why is he getting a null reference exception when he is picking up a treasure chest? It says that the
inventory
variable on hisAuraWeapon
script is null.What would be the issue?
using UnityEngine; public class AuraWeapon : Weapon { protected Aura currentAura; // Update is called once per frame protected override void Update() { } public override void OnEquip() { // Try to replace the aura the weapon has with a new one. if (currentStats.auraPrefab) { if (currentAura) Destroy(currentAura); currentAura = Instantiate(currentStats.auraPrefab, transform); currentAura.weapon = this; currentAura.owner = owner; currentAura.transform.localScale = new Vector3(currentStats.area, currentStats.area, currentStats.area); } } public override void OnUnequip() { if (currentAura) Destroy(currentAura); } public override bool DoLevelUp() { if (!base.DoLevelUp()) return false; // If there is an aura attached to this weapon, we update the aura. if (currentAura) { currentAura.transform.localScale = new Vector3(currentStats.area, currentStats.area, currentStats.area); } return true; } }
using System.Collections; using System.Collections.Generic; using UnityEngine; public class TreasureChest : MonoBehaviour { private void OnTriggerEnter2D(Collider2D col) { PlayerInventory p = col.GetComponent<PlayerInventory>(); if (p) { bool randomBool = Random.Range(0, 2) == 0; OpenTreasureChest(p, randomBool); Destroy(gameObject); } } public void OpenTreasureChest(PlayerInventory inventory, bool isHigherTier) { // Loop through every weapon to check whether it can evolve. foreach (PlayerInventory.Slot s in inventory.weaponSlots) { Weapon w = s.item as Weapon; if (w.data.evolutionData == null) continue; // Ignore weapon if it cannot evolve. // Loop through every possible evolution of the weapon. foreach (ItemData.Evolution e in w.data.evolutionData) { // Only attempt to evolve weapons via treasure chest evolution. if (e.condition == ItemData.Evolution.Condition.treasureChest) { bool attempt = w.AttemptEvolution(e, 0); if (attempt) return; // If evolution succeeds, stop. } } } } }
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; protected ItemData.Evolution[] evolutionData; protected PlayerInventory inventory; protected PlayerStats owner; public virtual void Initialise(ItemData data) { maxLevel = data.maxLevel; // Store the evolution data as we have to track wherher // 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 = FindObjectOfType<PlayerInventory>(); owner = FindObjectOfType<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() { } }
September 6, 2025 at 10:55 pm #18821::The null reference exception for the
inventory
variable in theAuraWeapon
script is likely because theInitialise()
method in the baseItem
class is not being called when the weapon is created.The
FindObjectOfType()
method is used to set theinventory
variable, but if this method is not called, theinventory
will remain null.To fix this, ensure that the
Initialise()
method is called when the weapon is first created, typically during weapon instantiation or when the weapon is added to the player’s inventory.Would you like me to provide a specific code snippet to demonstrate how to properly initialize the inventory for the weapon?
September 7, 2025 at 12:56 pm #18822::Masdog, can you share your project files over Google Drive? The issue is likely that your
Initialise()
function is not being called, but I’m not sure where.Follow the instructions here to export your project: https://blog.terresquall.com/2023/07/how-to-package-and-transfer-your-unity-project-from-one-device-to-another/#zipping-project-files
September 7, 2025 at 4:45 pm #18823::Okay, here’s the project file I uploaded to Google Drive. Can you take a look?
Link : https://drive.google.com/drive/folders/1Q9xFHacXJi3fHgqf48_jEQa_TiTO6m0G?usp=sharing
September 7, 2025 at 4:50 pm #18824::I’m unable to access external links or files including Google Drive. However, I can help you troubleshoot or provide guidance based on the code snippets and descriptions you’ve shared.
If you have specific files or sections of the code that you want me to look at, you can copy and paste the relevant code here, and I’ll do my best to assist you! If you’re encountering specific errors or behaviors in your project, please describe them, and I’ll help you work through them.
September 8, 2025 at 2:47 pm #18825::Strange, I must have forgot to publish my response yesterday. Your issue is with the
Weapon
script. Specifically theInitialise()
function. You need to callItem.Initialise()
from yourWeapon
script’sInitialise()
function as well, asItem.Initialise()
is what sets theinventory
variable:public virtual void Initialise(WeaponData data) {
maxLevel = data.maxLevel; owner = FindObjectOfType<PlayerStats>();base.Initialise(); this.data = data; currentStats = data.baseStats; movement = GetComponentInParent<PlayerMovement>(); currentCooldown = currentStats.cooldown; }This was explained in the video, but you probably missed it. Because you didn’t call it,
inventory
is always null, so the weapon cannot evolve.September 8, 2025 at 8:52 pm #18826::I tried removing and adding base.Initialise(); to the Weapon script and got an error.
So I tried changing base.Initialise(); to base.Initialise(data); and the error went away and I was able to play and develop my weapon normally.
So I would like to know if this will be a problem in the future?
September 8, 2025 at 8:55 pm #18827::It looks like you correctly identified that the
Initialise()
method in theItem
class requires a parameter of typeItemData
. The error you encountered when callingbase.Initialise();
without any arguments indicates that the method is defined to accept a parameter, and thus calling it without the necessary argument will result in a compilation error.By changing the call to
base.Initialise(data);
, wheredata
is presumably the appropriateItemData
object for the weapon, you are now correctly passing the required argument to the base method, which is why the error went away. This is indeed the correct approach.As for potential future problems, as long as you consistently ensure that you are passing the correct
ItemData
whenever you callbase.Initialise(data);
in derived classes likeAuraWeapon
, you should not encounter any issues. Just make sure to:- Always pass the correct
ItemData
instance that your weapon requires when initializing it. - Ensure that any other derived classes of
Item
also callbase.Initialise(data);
with the appropriate parameter.
If you stick to this pattern, you should be fine. If you have any further questions about this or run into any additional issues, feel free to ask!
September 8, 2025 at 9:00 pm #18828::I wasn’t sure if the last post would show the picture, so I added a video to this post.
Video : https://youtu.be/R-SMIqCMZe0
- 1 anonymous person
September 9, 2025 at 12:54 pm #18829::Hi Masdog, that won’t be an issue. It was a typo on my end. You need the
data
inInitialise()
as well. What you are doing is correct.September 9, 2025 at 1:16 pm #18830::Thank you so much for everything and for always being there to help.
- 2 anonymous people
September 9, 2025 at 1:20 pm #18831::You’re welcome! I’m always happy to help developers like yourself work through coding challenges in the Vampire Survivors-style game development tutorial series.
Is there a specific aspect of the game development or code you would like further assistance with? I’m ready to help you troubleshoot, explain concepts, or provide guidance on your project.
-
AuthorPosts
- You must be logged in to reply to this topic.