Demigiant / dotween

A Unity C# animation engine. HOTween v2
http://dotween.demigiant.com
Other
2.36k stars 350 forks source link

DOTween.KillAll on scene unload #447

Closed gayanW closed 3 years ago

gayanW commented 3 years ago

I'm killing all the running tweens on scene unloads. This is to prevent DOTween from failing due to null references on scene loads. Just wanna make sure the approach I took to handle it is correct.

BTW autoKillOnCompletion is set to TRUE.

    public class KillAllOnSceneUnload : MonoBehaviour
    {
        private void OnEnable()
        {
            SceneManager.sceneUnloaded += SceneManagerOnSceneUnloaded;
        }

        private static void SceneManagerOnSceneUnloaded(Scene scene)
        {
            DOTween.KillAll();
        }

        private void OnDisable()
        {
            SceneManager.sceneUnloaded -= SceneManagerOnSceneUnloaded;
        }
    }
Demigiant commented 3 years ago

Ahoy! Sorry if I saw this just now, but yes, it's definitely the correct approach :)

Barina commented 2 years ago

How does one kill all tweens in a specific scene before unloading it?

I see we can do something like this:

if (DOTween.TotalActiveTweens() > 0)
{
    var tweens = DOTween.PausedTweens();
    tweens.AddRange(DOTween.PlayingTweens());
    for (int i = 0; i < tweens.Count; i++)
        tweens[i]?.Kill();
}

But this will kill tweens resides in other scenes as well. We can expand it to:

if (DOTween.TotalActiveTweens() > 0)
{
    var tweens = DOTween.PausedTweens();
    tweens.AddRange(DOTween.PlayingTweens());
    for (int i = 0; i < tweens.Count; i++)
    {
        var tween = tweens[i];
        if (tween != null && tween.target is GameObject target && target.scene == gameObject.scene) // <= this
            tween.Kill();
    }
}

But it doesn't work.. I'm still getting Target or field is missing/null afterwards. What is the correct approach for this? Plus, what guarantees we have that the target object is always of type UnityEngine.GameObject? Is there a way to determine if a tween is part of some scene?

Maybe an override for methods DOTween.PausedTweens() and DOTween.PlayingTweens() that accept a scene as a filter? Or a new method DOTween.ActiveTweensForScene(UnityEngine.SceneManagement.Scene scene)?

Edit: I've noticed we can also use DOTween.TweensById(gameObject.scene) but this requires us to .SetID(gameObject.scene) on every tween we create.. (I'm using DOTween.Sequence() a lot) and we can't do this to tweens created using the DOTweenAnimation component.