DangerosoDavo
DangerosoDavo

Reputation: 127

Unity Coroutines and objects not being removed with Destroy()

Currently working on a Unity project and I'm having this issue where an object is not being destroyed. the child objects are just 2 images and a text object with no other scripts. Sometimes the object is removed correctly, but other times it is not. Can anyone see why this is? MEC is a replacement for unity coroutines but the issue happens with Unity Coroutines also and it was my first attempt to fix it.

The issue seems to happen more under load.

using MEC;
using System.Collections.Generic;
using TMPro;
using UnityEngine;

[RequireComponent(typeof(CanvasGroup))]
public class UINotificationEffect : MonoBehaviour
{
    // Private
    private CanvasGroup canvas_group;
    private float time_passed;
    private bool fading_out;

    // Public
    public float alive_time = 3.0f;
    public float fade_time = 0.5f;
    public string message = "Notification message";

    private void Awake()
    {
        canvas_group = GetComponent<CanvasGroup>();
        canvas_group.alpha = 0;
    }

    private void Start()
    {
        gameObject.GetComponentInChildren<TextMeshProUGUI>().text = message;     
        Timing.RunCoroutine(FadeTo(1.0f, fade_time), gameObject);
    }

    private void Update()
    {
        // At alive time end, fade out and get rid of this gameobject
        time_passed += Time.deltaTime;
        if (time_passed >= alive_time && !fading_out)
        {
            Timing.RunCoroutine(FadeTo(0.0f, fade_time), gameObject);
            fading_out = true;
        }

        // Destroy gameobject after alive time + fade time is over.
        if (fading_out && canvas_group.alpha <= 0.02f)
        {
            Timing.KillCoroutines(gameObject);
            Destroy(gameObject, 1f);
        }
    }

    /// <summary>
    /// Fade alpha of the canvas group in a certain direction (controlled by alpha_value).
    /// </summary>
    /// <param name="alpha_value">Fade to full (1.0) or fade to nothing (0.0)?</param>
    /// <param name="transition_time">The fading time of the alpha.</param>
    /// <returns></returns>
    IEnumerator<float> FadeTo(float alpha_value, float transition_time)
    {
        if (gameObject != null && gameObject.activeInHierarchy)
        {
            float alpha = canvas_group.alpha;
            for (float t = 0.0f; t <= 1.0f; t += Time.deltaTime / transition_time)
            {
                canvas_group.alpha = Mathf.Lerp(alpha, alpha_value, t);
                yield return Timing.WaitForOneFrame;
            }
        }
        yield break;
    }

    /// <summary>
    /// Update the text that should be displayed.
    /// </summary>
    /// <param name="text">The new message.</param>
    public void UpdateText(string text)
    {
        message = text;
        gameObject.GetComponentInChildren<TextMeshProUGUI>().text = message;
    }

    /// <summary>
    /// Stop all coroutines when the gameobject is destroyed.
    /// </summary>
    private void OnDestroy()
    {
        //StopAllCoroutines();
    }
}

Upvotes: 0

Views: 926

Answers (1)

Ruzihm
Ruzihm

Reputation: 20270

You don't have a guarantee that the loop in FadeTo ever runs with t approximately equal to 1f (really, you only know that it will be run at least once for t = 0f). Therefore, your alpha may never go below 0.2f, in which case, Destroy is never called.

Add a line at the end of your fade loop to set the canvas_group.alpha exactly to alpha_value:

IEnumerator<float> FadeTo(float alpha_value, float transition_time)
{
    if (gameObject != null && gameObject.activeInHierarchy)
    {
        float alpha = canvas_group.alpha;
        for (float t = 0.0f; t <= 1.0f; t += Time.deltaTime / transition_time)
        {
            canvas_group.alpha = Mathf.Lerp(alpha, alpha_value, t);
            yield return Timing.WaitForOneFrame;
        }

        canvas_group.alpha = alpha_value;
    }
    yield break;
}

Upvotes: 2

Related Questions