Skip to content

Instantly share code, notes, and snippets.

@JanikHelbig
Last active September 27, 2022 04:42
Show Gist options
  • Save JanikHelbig/74398ba1d9d4726d8faab1c228acefa7 to your computer and use it in GitHub Desktop.
Save JanikHelbig/74398ba1d9d4726d8faab1c228acefa7 to your computer and use it in GitHub Desktop.
Asynchronous equivalent of .NET's System.Action and System.Action<T> using UniTask for Unity
public delegate UniTask ActionAsync(CancellationToken cancellationToken);
public delegate UniTask ActionAsync<in T>(T value, CancellationToken cancellationToken);
public static class ActionAsyncExtensions
{
public static UniTask InvokeAsync(this ActionAsync handler, CancellationToken cancellationToken)
{
Delegate[] delegates = handler?.GetInvocationList();
if (delegates == null || delegates.Length == 0)
return UniTask.CompletedTask;
var tasks = new UniTask[delegates.Length];
for (var i = 0; i < delegates.Length; i++)
tasks[i] = (UniTask) delegates[i].DynamicInvoke(cancellationToken);
return UniTask.WhenAll(tasks);
}
public static UniTask InvokeAsync<T>(this ActionAsync<T> handler, T value, CancellationToken cancellationToken)
{
Delegate[] delegates = handler?.GetInvocationList();
if (delegates == null || delegates.Length == 0)
return UniTask.CompletedTask;
var tasks = new UniTask[delegates.Length];
for (var i = 0; i < delegates.Length; i++)
tasks[i] = (UniTask) delegates[i].DynamicInvoke(value, cancellationToken);
return UniTask.WhenAll(tasks);
}
}
public class Door : MonoBehaviour
{
public event ActionAsync OnOpening;
public event Action OnOpened;
public event ActionAsync OnClosing;
public event Action OnClosed;
public async UniTask OpenDoor(CancellationToken cancellationToken)
{
await OnOpening.InvokeAsync(cancellationToken);
OnOpened?.Invoke();
}
public async UniTask CloseDoor(CancellationToken cancellationToken)
{
await OnClosing.InvokeAsync(cancellationToken);
OnClosed?.Invoke();
}
}
public class DoorAnimationBehaviour : MonoBehaviour
{
[SerializeField]
private Door door;
[SerializeField]
private Animator doorAnimator;
private void OnEnable()
{
door.OnOpening += AnimateDoorOpening;
door.OnClosing += AnimateDoorClosing;
}
private void OnDisable()
{
door.OnOpening -= AnimateDoorOpening;
door.OnClosing -= AnimateDoorClosing;
}
private async UniTask AnimateDoorOpening(CancellationToken cancellationToken)
{
doorAnimator.SetBool("IsOpen", true);
await UniTask.WaitWhile(() => doorAnimator.GetCurrentAnimatorStateInfo(0).IsName("Opening"), PlayerLoopTiming.Update, cancellationToken);
}
private async UniTask AnimateDoorClosing(CancellationToken cancellationToken)
{
doorAnimator.SetBool("IsOpen", false);
await UniTask.WaitWhile(() => doorAnimator.GetCurrentAnimatorStateInfo(0).IsName("Closing"), PlayerLoopTiming.Update, cancellationToken);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment