You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
97 lines
2.5 KiB
97 lines
2.5 KiB
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member |
|
|
|
using System.Threading; |
|
using UnityEngine; |
|
|
|
namespace Cysharp.Threading.Tasks.Triggers |
|
{ |
|
public static partial class AsyncTriggerExtensions |
|
{ |
|
public static AsyncDestroyTrigger GetAsyncDestroyTrigger(this GameObject gameObject) |
|
{ |
|
return GetOrAddComponent<AsyncDestroyTrigger>(gameObject); |
|
} |
|
|
|
public static AsyncDestroyTrigger GetAsyncDestroyTrigger(this Component component) |
|
{ |
|
return component.gameObject.GetAsyncDestroyTrigger(); |
|
} |
|
} |
|
|
|
[DisallowMultipleComponent] |
|
public sealed class AsyncDestroyTrigger : MonoBehaviour |
|
{ |
|
bool awakeCalled = false; |
|
bool called = false; |
|
CancellationTokenSource cancellationTokenSource; |
|
|
|
public CancellationToken CancellationToken |
|
{ |
|
get |
|
{ |
|
if (cancellationTokenSource == null) |
|
{ |
|
cancellationTokenSource = new CancellationTokenSource(); |
|
} |
|
|
|
if (!awakeCalled) |
|
{ |
|
PlayerLoopHelper.AddAction(PlayerLoopTiming.Update, new AwakeMonitor(this)); |
|
} |
|
|
|
return cancellationTokenSource.Token; |
|
} |
|
} |
|
|
|
void Awake() |
|
{ |
|
awakeCalled = true; |
|
} |
|
|
|
void OnDestroy() |
|
{ |
|
called = true; |
|
|
|
cancellationTokenSource?.Cancel(); |
|
cancellationTokenSource?.Dispose(); |
|
} |
|
|
|
public UniTask OnDestroyAsync() |
|
{ |
|
if (called) return UniTask.CompletedTask; |
|
|
|
var tcs = new UniTaskCompletionSource(); |
|
|
|
// OnDestroy = Called Cancel. |
|
CancellationToken.RegisterWithoutCaptureExecutionContext(state => |
|
{ |
|
var tcs2 = (UniTaskCompletionSource)state; |
|
tcs2.TrySetResult(); |
|
}, tcs); |
|
|
|
return tcs.Task; |
|
} |
|
|
|
class AwakeMonitor : IPlayerLoopItem |
|
{ |
|
readonly AsyncDestroyTrigger trigger; |
|
|
|
public AwakeMonitor(AsyncDestroyTrigger trigger) |
|
{ |
|
this.trigger = trigger; |
|
} |
|
|
|
public bool MoveNext() |
|
{ |
|
if (trigger.called) return false; |
|
if (trigger == null) |
|
{ |
|
trigger.OnDestroy(); |
|
return false; |
|
} |
|
return true; |
|
} |
|
} |
|
} |
|
} |
|
|
|
|