/unitask-design
Source-anchored design rules for UniTask 2.5.10. 为 UniTask 2.5.10 提供源码锚定的设计规则。
$ npx -y skills add Besty0728/Unity-Skills --skill unitask-design --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/unitask-design
Context preview
The summary Claude sees to decide when to auto-load this skill.
Source-anchored design rules for UniTask 2.5.10. 为 UniTask 2.5.10 提供源码锚定的设计规则。
SKILL.md
unitask-design.SKILL.mdname: unity-unitask-design
description: Source-anchored design rules for UniTask 2.5.10. 为 UniTask 2.5.10 提供源码锚定的设计规则。
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 UniTaskVoid` method signature
- `.Forget()`, `.AttachExternalCancellation(token)`, `.SuppressCancellationThrow()` chaining
- `UniTask.Yield`, `UniTask.NextFrame`, `UniTask.Delay`, `UniTask.WaitForEndOfFrame`, `UniTask.WaitForFixedUpdate`
- `UniTask.WaitUntil`, `UniTask.WaitWhile`, `UniTask.WaitUntilValueChanged`, `UniTask.WaitUntilCanceled`
- `UniTask.WhenAll`, `UniTask.WhenAny`, `UniTask.WhenEach`
- `UniTask.SwitchToMainThread`, `UniTask.SwitchToThreadPool`, `UniTask.Run`
- `AsyncOperation.ToUniTask()`, `UnityWebRequest.SendWebRequest().ToUniTask()`, `Coroutine.ToUniTask()`
- `this.GetCancellationTokenOnDestroy()`, `GetAsyncStartTrigger()` and other `AsyncTrigger*` extensions
- `UniTaskCompletionSource` / `UniTaskCompletionSource<T>` manual completion sources
- `IUniTaskAsyncEnumerable<T>` / `UniTaskAsyncEnumerable` / `AsyncReactiveProperty<T>` / `Channel<T>`
- WebGL-specific async code paths where `Task.Run` / `SwitchToThreadPool` are 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 `await`ed, `.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 operato
Read more
name: unity-unitask-design description: Source-anchored design rules for UniTask 2.5.10. 为 UniTask 2.5.10 提供源码锚定的设计规则。
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 UniTaskVoid` method signature
- `.Forget()`, `.AttachExternalCancellation(token)`, `.SuppressCancellationThrow()` chaining
- `UniTask.Yield`, `UniTask.NextFrame`, `UniTask.Delay`, `UniTask.WaitForEndOfFrame`, `UniTask.WaitForFixedUpdate`
- `UniTask.WaitUntil`, `UniTask.WaitWhile`, `UniTask.WaitUntilValueChanged`, `UniTask.WaitUntilCanceled`
- `UniTask.WhenAll`, `UniTask.WhenAny`, `UniTask.WhenEach`
- `UniTask.SwitchToMainThread`, `UniTask.SwitchToThreadPool`, `UniTask.Run`
- `AsyncOperation.ToUniTask()`, `UnityWebRequest.SendWebRequest().ToUniTask()`, `Coroutine.ToUniTask()`
- `this.GetCancellationTokenOnDestroy()`, `GetAsyncStartTrigger()` and other `AsyncTrigger*` extensions
- `UniTaskCompletionSource` / `UniTaskCompletionSource<T>` manual completion sources
- `IUniTaskAsyncEnumerable<T>` / `UniTaskAsyncEnumerable` / `AsyncReactiveProperty<T>` / `Channel<T>`
- WebGL-specific async code paths where `Task.Run` / `SwitchToThreadPool` are 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 `await`ed, `.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 operato
REST API-based AI-driven Unity Editor Automation Engine Let AI control Unity scenes directly through Skills 🎉 We are now indexed by DeepWiki! Got questions? Check out the AI-generated docs → The current official maintenance baseline is Unity 2022.3+.
Other skills on unity-skills.
- /addressables-design
Source-anchored design rules for Unity Addressables 1.22.3/2.9.1. 为 Unity Addressables 1.22.3/2.9.1 提供源码锚定的设计规则。
Open skill - /adr
Record Unity architecture decisions (ADR) with rationale. 记录 Unity 架构决策(ADR)与理由。
Open skill - /animator
Edit Unity Animator Controllers and drive runtime parameters. 编辑 Unity Animator Controller 并驱动运行时参数。
Open skill - /architecture
Advise on Unity gameplay and system architecture. 为 Unity 游戏与系统架构提供建议。
Open skill - /asmdef
Advise on Unity assembly definitions (asmdef). 为 Unity 程序集定义(asmdef)提供建议。
Open skill - /asset
Manage Unity AssetDatabase operations. 管理 Unity AssetDatabase 操作。
Open skill

