unity-unitask-design
Source-anchored design rules for UniTask 2.5.10
它会碰到什么
这一栏是扫描器报的事实,不是结论。命中多不等于有毒(安全工具、规则库、示例脚本本来就会包含危险写法),命中少也不等于干净。它和你手上的凭据、文件、网络有什么关系,需要你自己看。
技能内容
> Before calling any skill in this module: if you are about to call a skill with parameters guessed from its name or description, STOP — read this file (or fetch its schema via GET /skills/recommend?includeSchema=true) first. If you already have the parameter definitions from recommend/schema, you may proceed straight to dryRun.
Triggers
- Writing or reviewing async UniTask code
- Choosing PlayerLoopTiming
- Handling CancellationToken
- Composing WhenAll/WhenAny
- 编写或审查 async UniTask 代码、选择 PlayerLoopTiming、处理 CancellationToken、组合 WhenAll/WhenAny
UniTask - Design Rules
Advisory module. Every rule is distilled from Cysharp UniTask source at:
- 2.5.10 —
com.cysharp.unitask@2.5.10(Unity 2018.4 baseline; actively used with 2022.3 / Unity 6)
Each rule cites a concrete file/line so the reasoning is auditable and the AI does not improvise against stale memory.
> Mode: Documentation only — no REST skills to gate; load freely under any operating mode (Approval / Auto / Bypass).
When to Load This Module
Load before writing or reviewing any of:
- Any
async UniTask/async UniTask<T>/async UniTaskVoidmethod signature .Forget(),.AttachExternalCancellation(token),.SuppressCancellationThrow()chainingUniTask.Yield,UniTask.NextFrame,UniTask.Delay,UniTask.WaitForEndOfFrame,UniTask.WaitForFixedUpdateUniTask.WaitUntil,UniTask.WaitWhile,UniTask.WaitUntilValueChanged,UniTask.WaitUntilCanceledUniTask.WhenAll,UniTask.WhenAny,UniTask.WhenEachUniTask.SwitchToMainThread,UniTask.SwitchToThreadPool,UniTask.RunAsyncOperation.ToUniTask(),UnityWebRequest.SendWebRequest().ToUniTask(),Coroutine.ToUniTask()this.GetCancellationTokenOnDestroy(),GetAsyncStartTrigger()and otherAsyncTrigger*extensionsUniTaskCompletionSource/UniTaskCompletionSource<T>manual completion sourcesIUniTaskAsyncEnumerable<T>/UniTaskAsyncEnumerable/AsyncReactiveProperty<T>/Channel<T>- WebGL-specific async code paths where
Task.Run/SwitchToThreadPoolare forbidden
Critical Rule Summary
| # | Rule | Source anchor |
|---|------|---------------|
| 1 | UniTask is a readonly partial struct (value type). Once awaited, its IUniTaskSource is recycled; awaiting the same UniTask variable twice throws. Use .Preserve() to obtain a memoized copy that can be awaited multiple times. | UniTask.cs:34, UniTask.cs:103-113 |
| 2 | A UniTask returned by a method must be either awaited, .Forget()ed, or .AttachExternalCancellation(token)ed. Orphan UniTasks silently swallow exceptions into UniTaskScheduler.UnobservedTaskException. | UniTaskScheduler.cs:13, UniTaskVoid.cs:11-17 |
| 3 | PlayerLoopTiming defines 16 timing slots (2020.2+; 14 on older Unity). Default UniTask.Yield() / UniTask.Delay uses PlayerLoopTiming.Update. Mixing LastPostLateUpdate with legacy WaitForEndOfFrame coroutines changes observed frame ordering. | PlayerLoopHelper.cs:71-99 |
| 4 | UniTask.Delay(int ms, DelayType, PlayerLoopTiming, CancellationToken, bool cancelImmediately) accepts DelayType.DeltaTime / UnscaledDeltaTime / Realtime. The old bool ignoreTimeScale overload still exists but mixes semantics — prefer the DelayType overload for new code. | UniTask.Delay.cs:12-20, UniTask.Delay.cs:147-165 |
| 5 | this.GetCancellationTokenOnDestroy() is defined for MonoBehaviour, GameObject, and Component in AsyncTriggerExtensions. Plain C# classes do NOT receive this extension — they must own a CancellationTokenSource explicitly. | Triggers/AsyncTriggerExtensions.cs:14,22,28 |
| 6 | UniTask.WhenAll(params UniTask[] tasks) and the IEnumerable<UniTask> overload both exist. Semantically match Task.WhenAll but are zero-alloc when tasks are UniTask-native. WhenAny returns (winnerIndex, result) tuple for UniTask<T>. | UniTask.WhenAll.cs:12,22,31,41, UniTask.WhenAny.cs |
| 7 | AsyncOperation.ToUniTask(IProgress<float>, PlayerLoopTiming, CancellationToken) is the canonical adapter. await operation works too but silently leaks the progress callback if you also set operation.completed += …. | UnityAsyncExtensions.cs |
| 8 | UniTaskCompletionSource and UniTaskCompletionSource<T> support TrySetResult / TrySetException / TrySetCanceled. Once any of the three succeeds, subsequent calls return false — they do not throw. | UniTaskCompletionSource.cs:573,610,754,792 |
| 9 | UniTask.SwitchToThreadPool() and UniTask.Run(...) are compile-time available on all platforms BUT throw NotSupportedException at runtime on WebGL. Guard with #if !UNITY_WEBGL || UNITY_EDITOR or fall back to UniTask.Yield()-based cooperative work. | UniTask.Threading.cs:57 |
| 10 | Returning async UniTaskVoid is the fire-and-forget idiom that lets await be used INSIDE the method. async void methods cannot return UniTask — a common compile error when porting from Task. | UniTaskVoid.cs:11-17, UniTask.Factory.cs:112-131 |
Sub-doc Routing
| Sub-doc | When to read |
|---------|--------------|
| [BASICS.md](./BASICS.md) | UniTask vs Task differences, struct semantics, UniTaskVoid, zero-alloc state machine, AsyncUniTaskMethodBuilder |
| [PLAYERLOOP.md](./PLAYERLOOP.md) | 16-value PlayerLoopTiming table, Yield/NextFrame/Delay/WaitForEndOfFrame/WaitForFixedUpdate, DelayType, frame-ordering with legacy coroutines |
| [CANCELLATION.md](./CANCELLATION.md) | CancellationToken patterns, GetCancellationTokenOnDestroy (3 overloads), AttachExternalCancellation, CancelAfterSlim, AddTo, OperationCanceledException flow |
| [COMPOSITION.md](./COMPOSITION.md) | WhenAll, WhenAny, WhenEach, Forget, SuppressCancellationThrow, ContinueWith, timeout patterns |
| [CONVERSION.md](./CONVERSION.md) | AsyncOperation.ToUniTask, UnityWebRequest.SendWebRequest().ToUniTask, IEnumerator.ToUniTask, Task.AsUniTask, UniTask.AsTask, UniTask.ToCoroutine |
| [ASYNCENUMERABLE.md](./ASYNCENUMERABLE.md) | IUniTaskAsyncEnumerable<T>, UniTaskAsyncEnumerable, AsyncReactiveProperty<T>, Channel<T>, EveryValueChanged, Publish, LINQ-to-async operators |
| [TRIGGERS.md](./TRIGGERS.md) | AsyncTriggerBase, GetAsyncStartTrigger, GetAsyncDestroyTrigger, OnCollisionEnterAsync, OnClickAsync, MonoBehaviourMessagesTriggers, lifecycle cancellation |
| [PITFALLS.md](./PITFALLS.md) | 30 concrete hallucination / runtime pitfalls (double-await, forgotten Forget, WebGL threadpool, tracker memory, wrong PlayerLoopTiming, coroutine interop bugs) |
Routing to Other Modules
- Choice between
UniTask, rawTask, andIEnumeratorat the architecture layer → load [async](../async/SKILL.md) - DOTween tween → UniTask adapter (
tween.ToUniTask(TweenCancelBehaviour, token)) → load [dotween-design](../dotween-design/SKILL.md) - YooAsset handle → UniTask via
handle.ToUniTask()extension → load [yooasset-design](../yooasset-design/SKILL.md) - Addressables
AsyncOperationHandle.ToUniTask()rules → load [addressables-design](../addressables-design/SKILL.md) - Performance review of UniTask-heavy code paths (tracker cost, state machine alloc) → load [performance](../performance/SKILL.md)
- Asmdef layout for UniTask consumers (
Cysharp.Threading.Tasks.asmdefreference) → load [asmdef](../asmdef/SKILL.md)
Version Scope
Targets UniTask 2.5.10. Earlier 2.x versions are mostly source-compatible; key differences:
WaitForEndOfFrame(MonoBehaviour coroutineRunner)overload added in recent 2.x — on 2023.1+ a parameterless overload is available (#if UNITY_2023_1_OR_NEWER). SeeUniTask.Delay.cs:78-103.UniTask.WhenEachis a newer addition; not all 2.x builds ship it.
When in doubt, read the cited source — not your memory.
想直接用这个技能?
本站把开放许可(MIT / Apache 等)的技能按仓库打包整理到网盘,点一下转存到你自己的网盘,不用一个个从 GitHub 拉。许可未声明的技能只给原始仓库链接,不打包。
它属于哪个仓库
SkillsForUnity/unity-skills~/skills/unitask-design/SKILL.md