1.7
Tested against UE 5.0.3 and 5.1.1, with preliminary support for 5.2.
Async coroutine overhaul:
- Async coroutines can now
co_return
values. #7 - The canonical return type of async coroutines is now
UE5Coro::TCoroutine<T>
for a coroutine co_returning T. T is optional. All of these implicitly convert to TCoroutine<>, meaning any return type or void. - co_awaiting a TCoroutine<T> results in T.
FAsyncCoroutine
remains, but it's now nothing more than a USTRUCT wrapper for TCoroutine<>. It's still needed for latent UFUNCTIONs, etc. due to engine limitations. It implicitly converts from/to TCoroutine<>, which is the safer and preferred type.
Additional new features:
- New animation-related awaiters for various montage events, notifies, etc. in the
UE5Coro::Anim
namespace. ContinueWith
andContinueWithWeak
are more robust, thread-safe replacements of OnCompletion() that handle the coroutine completing before they're called, and support return values. Functors for TCoroutine<T> can take no parameters, T, const T&, or anything that converts. Functors for TCoroutine<> must be parameterless. For ContinueWithWeak, the object may optionally be passed as the first parameter, enabling member functions to be bound.FForceLatentCoroutine
is a new USTRUCT that lets you force latent execution mode without having to specify a valid FLatentActionInfo.
Breaking/behavioral changes, deprecations:
- If you're not using the convenient
UE5Coro.h
header, you'll probably need to adjust some of your #includes. Notably, you shouldn't be directly #includingUE5Coro/AsyncCoroutine.h
anymore. - TCoroutine<>::OnCompletion(), née FAsyncCoroutine is deprecated, will not receive support for coroutine return values, and will be removed in a future version.
- TCoroutines now keep a part of the coroutine's state alive after it's completed, notably its return value, which dramatically increases runtime safety.
This comes at the cost of some unfortunate extra overhead when starting (but not resuming) coroutines. The performance impact is negligible unless you're starting thousands per tick. If you do, TGenerator might be an alternative, which can additionally benefit from compiler HALO.
Fixes:
- Further changes to WhenAny/WhenAll behavior: an awaiter or coroutine getting destroyed while being waited on this way counts as it completing, instead of the coroutine getting "stuck" and potentially leaking memory. This is not ideal, but there are engine/language limitations with exceptions not being available.
- Fixed a crash when co_awaiting a TFuture that's already complete. #9
- Fixed a crash when an exception is not caught and thrown out of a coroutine. You'll probably still crash, but not because of this anymore.
- Latent::Timeline now clamps its Length parameter to SMALL_NUMBER to prevent a division by zero and any resulting NaNs. This is done silently by default. If ENABLE_NAN_DIAGNOSTIC is turned on, it will be a diagnostic message or
ensure
based on the value of GEnsureOnNANDiagnostic (i.e., how every other NaN diagnostic works). Negative lengths are treated the same way and replaced with positive SMALL_NUMBER instead. - Latent::Chain (C++20 only) is affected by a compiler bug on older versions of MSVC (VS2019), which will now generate a compile-time warning. Clang and newer versions of MSVC (VS2022) are not affected.