AnnulusGames / LitMotion

Lightning-fast and Zero Allocation Tween Library for Unity.

Home Page:https://annulusgames.github.io/LitMotion/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Cancellation bleeds over to other MotionHandles

EusthEnoptEron opened this issue · comments

Absolutely love this library, but there seems to be a issue with cancelling UniTask'ed LMotions. Namely, the cancellations seem to bleed over to the following UniTask.

Here's a minimal example that illustrates the problem:

[UnityTest]
public IEnumerator Test_CancelWhileAwaitFollowedByAnother() => UniTask.ToCoroutine(async () =>
{
    var cancellationTokenSource = new CancellationTokenSource();
    LMotion.Create(0f, 10f, 1.0f)
        .RunWithoutBinding()
        .ToUniTask(cancellationTokenSource.Token)
        .Forget();

    await UniTask.Delay(100);
    cancellationTokenSource.Cancel();
    
    var canceled = await LMotion.Create(10.0f, 0.0f, 1.0f)
        .RunWithoutBinding()
        .ToUniTask()
        .SuppressCancellationThrow();
    
    Assert.IsFalse(canceled);
});

I'm suspecting that the LitMotion may be cancelling the underlying UniTaskCore twice, but I didn't dig that deep.
Here you can see that the pooled object already has a cancelled state:
image

It seems your suspection is right.

if (cancellationToken.CanBeCanceled)
{
    result.cancellationRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(static x =>
    {
        var source = (MotionConfiguredSource)x;
        var motionHandle = source.motionHandle;
        if (motionHandle.IsActive()) motionHandle.Cancel(); // core.TrySetCanceled(..) is called in here.
        source.core.TrySetCanceled(source.cancellationToken);
    }, result);
}

Fixed in #113.