Skip to content

[Question] destroyCancellationToken not preventing access after destruction? #294

Description

@manuelhuber

Hello, I'm running into problems with LMotion when destroying GameObjects.
This is my code:

public class FlyingIcon : MonoBehaviour {
    private Vector3 position {
        get => RectTransform.anchoredPosition;
        set => RectTransform.anchoredPosition = value;
    }
    private RectTransform RectTransform {
        get {
            if (!_rectTransform) _rectTransform = GetComponent<RectTransform>();
            return _rectTransform;
        }
    }

    public void DoAnimation() {
        var token = destroyCancellationToken;

        await LMotion.Create(startPosition, upPosition, upDuration)
            .WithEase(Ease.OutCubic)
            .Bind(pos => position = pos)
            .ToUniTask(token);
    }

And it results in this exception

MissingReferenceException: The object of type 'ui.FlyingIcon' has been destroyed but you are still trying to access it.
Your script should either check if it is null or you should not destroy the object.
UnityEngine.Object+MarshalledUnityObject.TryThrowEditorNullExceptionObject (UnityEngine.Object unityObj, System.String parameterName) (at <ad78ec25e30a41adb27f06b0ae6b00c9>:0)
UnityEngine.Bindings.ThrowHelper.ThrowNullReferenceException (System.Object obj) (at <ad78ec25e30a41adb27f06b0ae6b00c9>:0)
UnityEngine.Component.GetComponentFastPath (System.Type type) (at <ad78ec25e30a41adb27f06b0ae6b00c9>:0)
UnityEngine.Component.GetComponent[T] () (at <ad78ec25e30a41adb27f06b0ae6b00c9>:0)
ui.FlyingIcon.get_RectTransform () (at Assets/src/ui/FlyingIcon.cs:49)
ui.FlyingIcon.set_position (UnityEngine.Vector3 value) (at Assets/src/ui/FlyingIcon.cs:36)
ui.FlyingIcon+<>c__DisplayClass37_0.<FlyInternal>b__0 (UnityEngine.Vector3 pos) (at Assets/src/ui/FlyingIcon.cs:146)

The exception is thrown in this line
if (!_rectTransform) _rectTransform = GetComponent<RectTransform>();
which is called from line 146 .Bind(pos => position = pos).

Is this expected behaviour?
I'd have thought that the destroyCancellationToken prevents the bind callback from running after the GO/component has been destroyed. Or is there a potential race condition in the frame that the GO is destroyed? If so what is the canonnical way to prevent this? Do I need an additional if(!this) return check inside my Bind callback?

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions