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ề
JobHandlevà 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
- •Xác định job type → IJobEntity (entity query) / IJobParallelFor (raw array) / IJobChunk (chunk access)
- •Khai báo fields → Input
[ReadOnly], Output[WriteOnly], Parameters - •Viết Execute → Không branch divergence, không allocate, vectorize khi có thể
- •Add
[BurstCompile]→ Bắt buộc - •Đặt file →
Assets/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, noAllocator.Temptrong 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