Forum begins after the advertisement:

 


[Part 16] Evolution bug

Viewing 15 posts - 21 through 35 (of 35 total)
  • Author
    Posts
  • #18817
    Terence
    Level 31
    Keymaster
    Helpful?
    Up
    0
    ::

    Seems like the problem is with your Garlic weapon. Can you share your AuraWeapon script?

    #18818
    Masdog Jooner
    Level 4
    Participant
    Helpful?
    Up
    0
    ::

    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;
        }
    }
    #18819
    Alp Apustaja
    Level 10
    AI Assistant
    (BETA)
    Helpful?
    Up
    0
    ::

    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:

    1. Creating an aura when the weapon is equipped
    2. Destroying the aura when the weapon is unequipped
    3. 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?

    #18820
    Terence
    Level 31
    Keymaster
    Helpful?
    Up
    0
    ::

    @Alp why is he getting a null reference exception when he is picking up a treasure chest? It says that the inventory variable on his AuraWeapon 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() { }
    }
    #18821
    Alp Apustaja
    Level 10
    AI Assistant
    (BETA)
    Helpful?
    Up
    0
    ::

    The null reference exception for the inventory variable in the AuraWeapon script is likely because the Initialise() method in the base Item class is not being called when the weapon is created.

    The FindObjectOfType() method is used to set the inventory variable, but if this method is not called, the inventory 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?

    #18822
    Terence
    Level 31
    Keymaster
    Helpful?
    Up
    0
    ::

    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

    #18823
    Masdog Jooner
    Level 4
    Participant
    Helpful?
    Up
    0
    ::

    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

    #18824
    Alp Apustaja
    Level 10
    AI Assistant
    (BETA)
    Helpful?
    Up
    0
    ::

    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.

    #18825
    Terence
    Level 31
    Keymaster
    Helpful?
    Up
    0
    ::

    Strange, I must have forgot to publish my response yesterday. Your issue is with the Weapon script. Specifically the Initialise() function. You need to call Item.Initialise() from your Weapon script’s Initialise() function as well, as Item.Initialise() is what sets the inventory 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.

    #18826
    Masdog Jooner
    Level 4
    Participant
    Helpful?
    Up
    0
    ::

    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?

    #18827
    Alp Apustaja
    Level 10
    AI Assistant
    (BETA)
    Helpful?
    Up
    0
    ::

    It looks like you correctly identified that the Initialise() method in the Item class requires a parameter of type ItemData. The error you encountered when calling base.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);, where data is presumably the appropriate ItemData 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 call base.Initialise(data); in derived classes like AuraWeapon, you should not encounter any issues. Just make sure to:

    1. Always pass the correct ItemData instance that your weapon requires when initializing it.
    2. Ensure that any other derived classes of Item also call base.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!

    #18828
    Masdog Jooner
    Level 4
    Participant
    Helpful?
    Up
    1
    ::

    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
    has upvoted this post.
    #18829
    Terence
    Level 31
    Keymaster
    Helpful?
    Up
    0
    ::

    Hi Masdog, that won’t be an issue. It was a typo on my end. You need the data in Initialise() as well. What you are doing is correct.

    #18830
    Masdog Jooner
    Level 4
    Participant
    Helpful?
    Up
    2
    ::

    Thank you so much for everything and for always being there to help.

      2 anonymous people
    have upvoted this post.
    #18831
    Alp Apustaja
    Level 10
    AI Assistant
    (BETA)
    Helpful?
    Up
    0
    ::

    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.

Viewing 15 posts - 21 through 35 (of 35 total)
  • You must be logged in to reply to this topic.

Go to Login Page →


Advertisement below: