1
\$\begingroup\$

So I'm trying to create a simple script that is going to handle the logic for cutting down a tree I'm experiencing some strange behaviour with my script.

I have a private field which holds the "HP" for the tree which starts at 100, and when I hit the tree it goes down by 25 every time, so I need to hit it four times in order for me to cut it down. Once the tree reaches <= 0 in terms of HP it should play an animation which simulates the tree being cut down, wait a couple of seconds and then play another animation of it appearing again. Most of this works fine, it's not until after the animation, where I start my CoRoutine to wait for a couple of seconds it starts messing up.

ISSUE

The first time I cut it down, it works fine.. However.. After it respawns I need to hit it like 4-5 times for it to go down to 50 health and then it works like normal. So I hit it once, it gets to 75, I hit it twice, still at 75, 3 times.. still at 75.. And eventually, it starts going to to 50, 25, 0 etc.. This only happens after I cut it down the first time, and the first time it works fine.

Here is my Tree script NormalTree.cs

public class NormalTree : MonoBehaviour
{
    public static NormalTree instance;
    private int health = 100;

    public Animator animator;
    private void Awake()
    {
        if (instance == null)
        {
            instance = this;
        }
        animator = GetComponent<Animator>();
    }

    private void Update()
    {
        if (health <= 0)
        {
            KillTree();

            
        }
    }

    private void KillTree()
    {
        StartCoroutine(TreeSleep());
    }

    IEnumerator TreeSleep()
    {
        animator.SetBool("treedead", true);
        gameObject.tag = "DeadTree";
        
        yield return new WaitForSeconds(3f);

        animator.SetBool("treedead", false);
        gameObject.tag = "Tree";
        health = 100;
    }

    public Item DamageTree(int damage)
    {
        health -= damage;
        Debug.Log($"Tree health {health}");
        if (health <= 0)
        {
            return new Item { Amount = 1, ItemRarity = Item.ItemRarityEnum.Gray, ItemType = Item.ItemTypeEnum.Log };
        }
        else
        {
            return null;
        }
    }
}

And in my PlayerController I have this, which essentially checks if my hitbox collides with an object that has the tag "Tree"

private void OnTriggerEnter2D(Collider2D other)
{
    if (other.CompareTag("Tree"))
    {
        var wc = Skills.FirstOrDefault(x => x.Name == "Woodcutting");

        var tree = other.GetComponent<NormalTree>().DamageTree(25);
        
        if (tree != null)
        {
            inventory.AddItem(tree);
            wc.AddExperience(25);
            Debug.Log(wc.Level);
        }
    }
}
\$\endgroup\$
2
  • 2
    \$\begingroup\$ Can it be that since your killtree is in update, your coroutine gets called more often and each time it finishes, it resets the health back to 100. You should only start killtree if it is of type tree and not already deadtree \$\endgroup\$ – Zibelas Dec 23 '20 at 15:25
  • \$\begingroup\$ You could put the kill tree as well in the damage tree if condition to solve the issue \$\endgroup\$ – Zibelas Dec 23 '20 at 15:49
0
\$\begingroup\$

You need to right away set health back to 100.

private void Update()
    {
        if (health <= 0)
        {
            health = 100;
            KillTree();

            
        }
    }

Your StartCoroutine(TreeSleep()); is being called n times per frame - since health < = 0 is true the whole time until the end of your Coroutine.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.