AGENT SKILL

wave8-dependency-complete-editor-only-fence

Use state.Dependency.Complete() only as an editor-mode diagnostic fence to inspect intermediate job state, never as a production pattern for forcing job completion.

License 许可
MIT
最近更新
2026-07-25
Stars
★ 8
Forks
0

01 前言 Front Matter

name
wave8-dependency-complete-editor-only-fence
tags
[ "jobs", "antipattern", "debug" ]
metadata
{ "tier": 3, "internal-only": true }
description
Use state.Dependency.Complete() only as an editor-mode diagnostic fence to inspect intermediate job state, never as a production pattern for forcing job completion.

03 SKILL.md 正文

state.Dependency.Complete() — Editor-Only Diagnostic Fence

Intent

Use state.Dependency.Complete() only as an editor-mode diagnostic fence to inspect intermediate job state, never as a production pattern for forcing job completion.

Use When

  • Adding a temporary diagnostic fence in editor builds to isolate a job scheduling bug or verify intermediate NativeArray state
  • Confirming a job's output in isolation before wiring it into a dependency chain

Avoid When

  • In any shipping build or production system — Complete() is a sync point anti-pattern
  • As a substitute for proper job dependency chaining — fix the chain, do not paper over it

Senior Pattern

// EDITOR-ONLY diagnostic fence — not for production:
public partial struct DiagnosticSystem : ISystem
{
    public void OnUpdate(ref SystemState state)
    {
        var results = CollectionHelper.CreateNativeArray<int>(100, state.WorldUpdateAllocator);
        var job = new ComputeJob { Results = results };
        state.Dependency = job.Schedule(state.Dependency);

#if UNITY_EDITOR
        // Force sync to inspect intermediate state — remove before shipping:
        state.Dependency.Complete();
        UnityEngine.Debug.Log($"Intermediate result[0]: {results[0]}");
#endif
        // Production: dependency chain propagates — no Complete() needed
    }
}

// PRODUCTION correct pattern — never forced Complete():
[BurstCompile]
public partial struct ProductionSystem : ISystem
{
    [BurstCompile]
    public void OnUpdate(ref SystemState state)
    {
        var results = CollectionHelper.CreateNativeArray<int>(100, state.WorldUpdateAllocator);
        state.Dependency = new ComputeJob { Results = results }
            .ScheduleParallel(state.Dependency);
        // Dependency propagates to consuming systems automatically
    }
}

Anti-Patterns

  • state.Dependency.Complete() in every OnUpdate "to be safe" — full sync point every frame; eliminates all job parallelism; main-thread stall equal to all scheduled job duration.
  • Using Complete() to read job output without #if UNITY_EDITOR guard — ships the anti-pattern into production builds.
  • Using Complete() as a substitute for proper dependency chaining — masks scheduling bugs rather than fixing them.
  • Calling Complete() at the start of OnUpdate to "wait for last frame's jobs" — indicates incorrect Allocator.Persistent usage; switch to WorldUpdateAllocator.

Runtime Risks

  • Unguarded Complete() forces the main thread to wait for all scheduled jobs — destroying frame parallelism.
  • On a frame with 10ms of scheduled jobs, a Complete() in the middle stalls the main thread for up to 10ms.
  • In profiler: main thread shows "WaitForJobGroupID" — this is the Complete() stall.

Performance Notes

  • One unguarded Complete() in a hot system can raise frame time by 5–15ms on complex ECS worlds.
  • Use Unity Profiler job markers to identify the stall: look for main thread "WaitForJobGroupID" immediately followed by the system that called Complete().
  • Eliminating a single misplaced Complete() in a 10,000-entity system commonly recovers 2–8ms per frame.

Architecture Guidance

  • If you feel the need to call Complete() in production: this signals the dependency chain is broken. Fix the chain; do not paper over it.
  • For temporary diagnostics: always use #if UNITY_EDITOR guard; remove before merging to main.
  • For reading job output on the same frame: pass results via WorldUpdateAllocator NativeArray through state.Dependency to a consuming system.

Related Skills

[[job-dependency-chain]], [[wave4-jobhandle-combine-dependencies]], [[wave8-handle-complete-sync-point-antipattern]], [[wave4-world-update-allocator-per-frame-native]]

04 同仓库更多 Skills

dyCuong03
dyCuong03/unity-agent-team

dots-update-groups

How to choose the right ECS system group and ordering so per-frame and per-fixed-step work is deterministic and never races its own readers. Covers InitializationSystemGroup / SimulationSystemGroup / PresentationSystemGroup / FixedStepSimulationSystemGroup / VariableRateSimulationSystemGroup, UpdateBefore / UpdateAfter peer ordering, OrderFirst / OrderLast group-boundary placement, RateManager, and the cross-group ordering trap. Use when adding an ISystem, fixing "value visible one frame late" bugs, or coupling simulation to a fixed timestep.

★ 8
dyCuong03
dyCuong03/unity-agent-team

dots-transform-patterns

The Entities 1.x transform model — LocalTransform (writable input) vs LocalToWorld (system-owned matrix), Parent/Child hierarchy, reparenting cost, uniform vs non-uniform scale (PostTransformMatrix), and when to opt out with custom transform systems. Use when designing parent/child hierarchies, runtime reparenting (mount/dismount/socket), or choosing transform components at the Baker boundary.

★ 8
dyCuong03
dyCuong03/unity-agent-team

dots-singleton-patterns

Model cross-system shared configuration and game state as a single-entity component with a strict single-writer contract. Covers RequireForUpdate gating, SystemAPI.GetSingleton / GetSingletonRW / HasSingleton / TryGetSingleton, bake-time vs runtime-created vs ECB-system singletons, the "exactly one entity" runtime invariant, and the single-writer rule. Use when designing frame-stable global config, shared mutable state, or any component intended to exist on exactly one entity.

律师与法务
★ 8
dyCuong03
dyCuong03/unity-agent-team

dots-hybrid-bridge

The one-way bridge between DOTS-owned runtime state and Unity-owned presentation. Covers UnityObjectRef for managed asset refs in components, the DOTS-writes / Unity-reads ownership rule, when to use managed IComponentData vs UnityObjectRef vs CompanionComponent, baker-bridge vs runtime-bridge, and SubScene boundary rules. Use when an entity must reference Unity assets (Mesh, Material, AudioClip, ScriptableObject), a MonoBehaviour view must read entity state, or input/UI must trigger ECS work.

★ 8
dyCuong03
dyCuong03/unity-agent-team

dots-event-driven-ecs

Model one-frame events and external requests in ECS without dual ownership, polling, or persistent state leaks. Covers request-tag pattern with ECB, enableable command components (no structural change), event buffers (IBufferElementData), explicit consumer ownership, one-frame latency rules, and the banned C# event / UnityEvent / static bus anti-patterns. Use when input/UI/network must trigger ECS work, when a one-frame signal fans out to N consumers (damage, hit, collision), or when state changes must be processed exactly once.

★ 8
dyCuong03
dyCuong03/unity-agent-team

valid_skill

A complete, well-formed test fixture skill for SkillHub validation testing. Covers basic task routing and code review for Unity projects.

代码审查测试与质量
★ 8