AgentSkillsCN

unity-job-parallel-builder

针对Burst Compiler,优化并行作业(IJobEntity、IJobChunk、IJobParallelFor、IJobParallelForBatch),使其充分发挥效能。当用户需要创建并行处理数据的作业、优化性能,或编写与Burst兼容的逻辑时,可使用此功能。

SKILL.md
--- frontmatter
name: unity-job-parallel-builder
description: Thiết lập các Job song song (IJobEntity, IJobChunk, IJobParallelFor, IJobParallelForBatch) tối ưu với Burst Compiler. Dùng khi user yêu cầu tạo job xử lý dữ liệu song song, tối ưu hiệu suất, hoặc viết logic Burst-compatible.

Unity Job Parallel Builder

Critical Instructions

  • Burst First: MỌI job sinh ra PHẢI có attribute [BurstCompile]. Không có ngoại lệ.
  • Safety: Luôn khai báo rõ [ReadOnly], [WriteOnly], [NativeDisableParallelForRestriction] khi cần.
  • Project Convention: Đặt file vào Assets/Scripts/Core/Jobs/ trừ khi user chỉ định khác.
  • Scheduling: Luôn trả về JobHandle và chain dependency đúng cách.

Core Principles

  • No Managed Types: Job không được chứa class, string, delegate, closure. Chỉ blittable.
  • No Static Access: Không truy cập static mutable state trong job.
  • Container Safety: Dùng NativeArray, NativeParallelHashMap, NativeList, NativeQueue — luôn khai báo [ReadOnly] cho input.
  • Batch Size: Cân nhắc batch size phù hợp. Mặc định dùng 64 cho voxel jobs.

Job Types Reference

1. IJobEntity (Recommended Default)

Đơn giản nhất. Tự động query Entity theo tham số hàm Execute.

csharp
using Unity.Burst;
using Unity.Collections;
using Unity.Entities;
using Unity.Mathematics;
using Unity.Transforms;

/// <summary>
/// [Mô tả job làm gì, thuộc system nào]
/// </summary>
[BurstCompile]
public partial struct ExampleJob : IJobEntity
{
    public float DeltaTime;
    [ReadOnly] public NativeArray<float> LookupTable;

    void Execute(ref LocalTransform transform, in ExampleComponent data)
    {
        transform.Position += new float3(0, data.Value * DeltaTime, 0);
    }
}

// Scheduling trong System:
// new ExampleJob { DeltaTime = dt, LookupTable = table }.ScheduleParallel(state.Dependency);

2. IJobParallelFor (Raw Data Processing)

Dùng cho xử lý NativeArray thuần, không cần Entity query. Phù hợp nhất cho VisualWorld.

csharp
/// <summary>
/// Job xử lý [dữ liệu gì] song song trên NativeArray.
/// </summary>
[BurstCompile]
public struct RawProcessingJob : IJobParallelFor
{
    [ReadOnly] public NativeArray<float> Input;
    [WriteOnly] public NativeArray<float> Output;
    public float Multiplier;

    public void Execute(int index)
    {
        Output[index] = Input[index] * Multiplier;
    }
}

// Scheduling:
// var handle = new RawProcessingJob { ... }.Schedule(arrayLength, batchSize: 64, dependency);

3. IJobChunk (Advanced Entity Processing)

Truy cập trực tiếp ArchetypeChunk. Dùng khi cần optional components hoặc logic chunk-level.

csharp
/// <summary>
/// Job xử lý chunk-by-chunk cho [mục đích gì].
/// </summary>
[BurstCompile]
public struct ChunkProcessJob : IJobChunk
{
    public ComponentTypeHandle<ExampleComponent> ExampleHandle;
    [ReadOnly] public ComponentTypeHandle<LocalTransform> TransformHandle;

    public void Execute(in ArchetypeChunk chunk, int unfilteredChunkIndex,
        bool useEnabledMask, in v128 chunkEnabledMask)
    {
        var examples = chunk.GetNativeArray(ref ExampleHandle);
        var transforms = chunk.GetNativeArray(ref TransformHandle);

        for (int i = 0; i < chunk.Count; i++)
        {
            var e = examples[i];
            e.Value += transforms[i].Position.y;
            examples[i] = e;
        }
    }
}

4. IJobParallelForBatch (Batch Parallelism)

Chia NativeArray thành batch, mỗi thread xử lý 1 batch liên tục (cache friendly).

csharp
[BurstCompile]
public struct BatchJob : IJobParallelForBatch
{
    public NativeArray<float> Data;

    public void Execute(int startIndex, int count)
    {
        for (int i = startIndex; i < startIndex + count; i++)
        {
            Data[i] = math.sqrt(Data[i]);
        }
    }
}

// Scheduling:
// new BatchJob { Data = data }.ScheduleBatch(data.Length, batchSize: 128, dependency);

Project-Specific Patterns (VisualWorld)

Thermodynamics Job

csharp
/// <summary>
/// Cellular Automata: Lan truyền nhiệt giữa các voxel lân cận.
/// T_next = T_current + Σ(T_neighbor - T_current) × k × Δt
/// </summary>
[BurstCompile]
public struct ThermodynamicsJob : IJobParallelFor
{
    [ReadOnly] public NativeArray<VoxelData> CurrentState;
    [WriteOnly] public NativeArray<VoxelData> NextState;
    [ReadOnly] public NativeArray<int> ActiveIndices;
    [ReadOnly] public NativeArray<float> ConductivityTable; // per MaterialID
    public float DeltaTime;
    public int3 ChunkSize;

    public void Execute(int jobIndex)
    {
        int flatIndex = ActiveIndices[jobIndex];
        var voxel = CurrentState[flatIndex];

        // Lấy 6 neighbor, tính trung bình nhiệt có trọng số...
        // (implementation theo công thức README)

        NextState[flatIndex] = voxel;
    }
}

Stress Propagation Job

csharp
/// <summary>
/// BFS lan truyền tải trọng từ voxel bị phá hủy.
/// Mỗi iteration xử lý 1 wave của BFS.
/// </summary>
[BurstCompile]
public struct StressPropagationJob : IJobParallelFor
{
    [ReadOnly] public NativeArray<VoxelData> Voxels;
    public NativeArray<byte> StressMap;
    [ReadOnly] public NativeArray<int> CurrentWave;
    [WriteOnly] public NativeQueue<int>.ParallelWriter NextWave;
    public int3 ChunkSize;

    public void Execute(int index)
    {
        int flatIndex = CurrentWave[index];
        // Tính stress cho 6 neighbor, push vào NextWave nếu > threshold
    }
}

Scheduling Best Practices

csharp
// ĐÚNG: Chain dependency
JobHandle handle1 = new Job1 { ... }.Schedule(length, 64, inputDeps);
JobHandle handle2 = new Job2 { ... }.Schedule(length, 64, handle1);
state.Dependency = handle2;

// ĐÚNG: Fan-out rồi merge
JobHandle a = new JobA { ... }.Schedule(len, 64, inputDeps);
JobHandle b = new JobB { ... }.Schedule(len, 64, inputDeps);
state.Dependency = JobHandle.CombineDependencies(a, b);

// SAI: Quên chain dependency → race condition

Generation Workflow

  1. Xác định job type → IJobEntity (entity query) / IJobParallelFor (raw array) / IJobChunk (chunk access)
  2. Khai báo fields → Input [ReadOnly], Output [WriteOnly], Parameters
  3. Viết Execute → Không branch divergence, không allocate, vectorize khi có thể
  4. Add [BurstCompile] → Bắt buộc
  5. Đặt fileAssets/Scripts/Core/Jobs/{JobName}Job.cs

Validation Checklist

  • [BurstCompile] attribute trên struct
  • Tất cả fields là blittable (no managed types)
  • [ReadOnly] trên mọi input container
  • Không truy cập static mutable state
  • Không allocate bộ nhớ trong Execute (no new, no Allocator.Temp trong hot loop)
  • Batch size hợp lý (64-256 cho voxel, 1-16 cho entity nặng)
  • Có XML documentation mô tả thuật toán