Forum begins after the advertisement:


[Part 16] Previous Garlic Aura are not destroyed when leveled up

Home Forums Video Game Tutorial Series Creating a Rogue-like Shoot-em Up in Unity [Part 16] Previous Garlic Aura are not destroyed when leveled up

Viewing 6 posts - 1 through 6 (of 6 total)
  • Author
    Posts
  • #15550
    Anthony
    Level 16
    No Patreon subscription
    Helpful?
    Up
    0
    ::

    Hello!

    First post on this forum, I’m happy to join the community!

    I realised that when Garlic weapon level up, the Garlic Aura are stacking up one over the other. I’m not sure it’s intended but if it’s not the case, I think this come from the Destroy(currentAura); not being effective.

    <code>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;
    
                float area = GetArea();
                currentAura.transform.localScale = new Vector3(area, area, area);
            }
        }
    
        public override void OnUnequip()
        {
            if (currentAura) Destroy(currentAura);
        }
    
        public override bool DoLevelUp()
        {
            if (!base.DoLevelUp()) return false;
    
            // Ensure that the aura is refreshed if a different aura is assigned for a higher level.
            OnEquip();
    
            // 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;
        }
    
    }</code>
    #15558
    Terence
    Level 30
    Keymaster
    Helpful?
    Up
    0
    ::

    Hi Anthony, sorry for missing your message, and thanks for your support!

    I think this has to do with currentAura not being assigned in your case. After you equip your aura, can you toggle Debug mode on your Inspector and select the Aura? Then, check if currentAura is assigned on the Aura component.

    You can toggle Debug mode here (see the Toggle Debug mode section): https://docs.unity3d.com/Manual/InspectorOptions.html

    #15559
    Anthony
    Level 16
    No Patreon subscription
    Helpful?
    Up
    0
    ::

    Hello, no worries it’s the first message which take time I assume (since it was marked as spam)

    It’s a behaviour I have seen in the version 21 of the game as well (I downloaded the project files). The Garlic is well assigned.

    View post on imgur.com

    I realise that it remove only the Aura script but not the full child object (containing animation, sprite, ect). To solve the problem, we can just change:

    <code> public override void OnEquip()
     {
         // Try to replace the aura the weapon has with a new one.
         if (currentStats.auraPrefab)
         {
             Debug.Log("Equipping aura weapon:" + currentStats.auraPrefab);
             Debug.Log("Destroying current aura:" + currentAura);
             if (currentAura)
             {
                 Debug.Log("currentAura exists");
                 // Destroy(currentAura); Remove this line (idk how to put it in red like you)
    
                 <mark class="green">Destroy(currentAura.gameObject); // change it to that
             }
             currentAura = Instantiate(currentStats.auraPrefab, transform);
             currentAura.weapon = this;
             currentAura.owner = owner;
    
             float area = GetArea();
             currentAura.transform.localScale = new Vector3(area, area, area);
         }
     }</code>

    Anthony

    #15569
    Terence
    Level 30
    Keymaster
    Helpful?
    Up
    0
    ::

    That’s a nice find Anthony. Thank you for pointing this out. Can’t believe I missed that out.

    I’ve given you a new badge on your profile. We are rolling out a new XP system on the blog, and these badges will contribute to your XP points in future. You will be able to use these XP points to get perks, as well as unlock Patron-locked content permanently for your account.

    The XP system is meant to do 2 things:

    1. Encourage participation, so that we cultivate a more vibrant community here.
    2. Make the content more accessible for people from countries with smaller currencies. US$10 is a lot of money for certain countries in Asia, and a lot of our viewers there cannot afford the content.
    Bug Reporter Badge
    #15573
    Anthony
    Level 16
    No Patreon subscription
    Helpful?
    Up
    0
    ::

    Hello,

    I also have an other bug to report but maybe it’s because I was pushing the number of enemy + weapon damage too much that it was not appearing in your situation. This bug was also replicated on the [part 21] code.

    This phenomena will make a “null pointer exception” like error due to the system of checking if the enemy have already been affected by the garlic.

    In the class Aura, the method:

    <code>void Update()
    {
        Dictionary<EnemyStats, float> affectedTargsCopy = new Dictionary<EnemyStats, float>(affectedTargets);
    
        // Loop through every target affected by the aura, and reduce the cooldown
        // of the aura for it. If the cooldown reaches 0, deal damage to it.
        foreach (KeyValuePair<EnemyStats, float> pair in affectedTargsCopy)
        {
            affectedTargets[pair.Key] -= Time.deltaTime;
            if (pair.Value <= 0)
            {
                if (targetsToUnaffect.Contains(pair.Key))
                {
                    // If the target is marked for removal, remove it.
                    affectedTargets.Remove(pair.Key);
                    targetsToUnaffect.Remove(pair.Key);
                }
                else
                {
                    // Reset the cooldown and deal damage.
                    Weapon.Stats stats = weapon.GetStats();
                    affectedTargets[pair.Key] = stats.cooldown * weapon.Owner.Stats.cooldown;
                    pair.Key.TakeDamage(GetDamage(), transform.position, stats.knockback);
    
                    // Play the hit effect if it is assigned.
                    if (stats.hitEffect)
                    {
                        Destroy(Instantiate(stats.hitEffect, pair.Key.transform.position, Quaternion.identity), 5f);
                    }
                }
            }
        }
    }</code>

    will generate an error if the enemy affected by the aura is destroyed by an other weapon. Indeed, it will have some EnemyStats not existing anymore.

    To tackle that we can add

    <code>// Check if the EnemyStats object has been destroyed
            if (pair.Key == null)
            {
                // Remove the destroyed object from the dictionary
                affectedTargets.Remove(pair.Key);
                continue;
            }
    </code>

    Before changing the “affectedTargets[pair.Key] -= Time.deltaTime;”. But this is just a tiny bandage and I think there could be a better and more efficient way to tackle that maybe with some “try” checks. Or maybe moving some bool to the EnemyStats.

    #15574
    Terence
    Level 30
    Keymaster
    Helpful?
    Up
    0
    ::

    Thanks Anthony. Another great spot! Note that you will need to remove the object from both affectedTargets and targetsToUnaffect.

    You can also do !pair.Key instead of pair.Key == null. Both mean the same thing. The ! means “not”.

    There isn’t a more efficient way — at least not that I can think of. It is important to remove the items from the arrays when the enemies are killed.

    The code after edits will look something like this:

    void Update()
    {
        Dictionary<EnemyStats, float> affectedTargsCopy = new Dictionary<EnemyStats, float>(affectedTargets);
    
        // Loop through every target affected by the aura, and reduce the cooldown
        // of the aura for it. If the cooldown reaches 0, deal damage to it.
        foreach (KeyValuePair<EnemyStats, float> pair in affectedTargsCopy)
        {
            // It's possible for enemies in our list to get killed by other enemies.
            // If they do, pair.Key will become null, so we need to remove it.
            if(!pair.Key) {
                targetsToUnaffect.Remove(null);
                affectedTargets.Remove(null);
                continue;
            }
    
            affectedTargets[pair.Key] -= Time.deltaTime;
            if (pair.Value <= 0)
            {
                if (targetsToUnaffect.Contains(pair.Key))
                {
                    // If the target is marked for removal, remove it.
                    affectedTargets.Remove(pair.Key);
                    targetsToUnaffect.Remove(pair.Key);
                }
                else
                {
                    // Reset the cooldown and deal damage.
                    Weapon.Stats stats = weapon.GetStats();
                    affectedTargets[pair.Key] = stats.cooldown * weapon.Owner.Stats.cooldown;
                    pair.Key.TakeDamage(GetDamage(), transform.position, stats.knockback);
    
                    // Play the hit effect if it is assigned.
                    if (stats.hitEffect)
                    {
                        Destroy(Instantiate(stats.hitEffect, pair.Key.transform.position, Quaternion.identity), 5f);
                    }
                }
            }
        }
    }

    P.S. I’ve given you a few more badges as thanks.

Viewing 6 posts - 1 through 6 (of 6 total)
  • You must be logged in to reply to this topic.

Go to Login Page →


Advertisement below: