SCHEDULER
kinematic_solver broad_phase overlap_solver world_solver consumer NativeQueue<int2> SoA · F/B swap
Pawn Movement · Sub-document

Movement
Scheduler

Job System 기반 이동 연산의 스케줄링 구조 — 더블 버퍼, 페어 큐, 솔버 체인 명세

Kinematic Scheduler Solver Consumer
scroll

PawnKinematicSchedules → PawnUpdateSchedules

프레임마다 두 단계로 실행됩니다. Kinematic이 먼저 이동 벡터를 결정하고, 이후 Update 단계에서 페어 큐를 초기화·수집하고 솔버를 순서대로 스케줄합니다.

01
Kinematic
PawnKinematicSchedules(out capsules, out cubes, out spheres)
shape 타입별로 kinematic solver Job을 스케줄합니다. 이동 요청(requests)과 deltaTime을 입력받아 이동 벡터(moves)를 생성합니다. 결과는 즉시 F/B 버퍼 스왑으로 확정됩니다.
02
페어 큐 초기화 + Broad Phase
PawnUpdateSchedules(capsulesCount, cubesCount, spheresCount, …)
11개 페어 큐를 전부 Clear합니다. 이후 PawnToBlockUpdateSchedule과 PawnToPawnUpdateSchedule로 충돌 후보 쌍을 AABB 스윕 볼륨 기준으로 수집합니다.
03
Narrow Phase 솔버
PawnCapsulesUpdateSchedule / PawnCubesUpdateSchedule / PawnSpheresUpdateSchedule
수집된 페어에 대해 실제 충돌·미끄러짐 연산을 최대 해상도로 실행합니다. Pawn-to-Block → Pawn-to-Pawn → World 순서로 체인됩니다.
04
컨슈머
이벤트 발송 · 트랜스폼 업데이트
솔버가 확정한 최종 이동 벡터를 응용 레이어로 전달합니다. TODO: Pawn-to-Location overlap check가 예정되어 있습니다.

F / B 버퍼 스왑

moves 배열은 Front(F)와 Back(B) 두 벌로 관리됩니다. 각 Job은 F를 읽고 B에 씁니다. Job이 완료된 직후 F↔B를 튜플 스왑으로 교체해, 다음 Job에서 최신 결과를 F로 읽을 수 있도록 합니다.

이 패턴은 동일 배열에 대한 Job 간 읽기/쓰기 레이스를 제거하고, 스케줄러가 의존성을 예측 가능하게 추적할 수 있도록 합니다.

moves_F
AsReadOnly()
swap
moves_B
Write target
// Job 스케줄
new solver {
  moves      = pawnCapsulesMovesF.AsReadOnly(),
  moves_write = pawnCapsulesMovesB,
}.Schedule(count, 32, frameJob);

// Job 완료 후 즉시 스왑
(pawnCapsulesMovesF, pawnCapsulesMovesB)
  = (pawnCapsulesMovesB, pawnCapsulesMovesF);

Capsule, Cube, Sphere 각각 독립된 F/B 버퍼 쌍을 보유합니다. 스왑은 각 Job 직후 수행되므로, 동일 frame 내에서 solver 순서대로 이동 벡터가 누적·갱신됩니다.

NativeQueue<int2> 페어 수집

스케줄러 단계에서 Broad Phase가 충돌 후보 쌍 (pawnIndex, blockIndex) 또는 (pawnA, pawnB)를 수집합니다. 매 프레임 시작 시 전량 Clear된 뒤, 솔버가 소비합니다.

pawnCapsule
ToBlockCapsule
Capsule × Capsule
pawnCapsule
ToBlockCube
Capsule × Cube
pawnCapsule
ToBlockSphere
Capsule × Sphere
pawnCube
ToBlockCube
Cube × Cube
pawnSphere
ToBlockCube
Sphere × Cube
pawnCapsule
ToPawnCapsule
Capsule ↔ Capsule
pawnCapsule
ToPawnCube
Capsule ↔ Cube
pawnCapsule
ToPawnSphere
Capsule ↔ Sphere
pawnCube
ToPawnCube
Cube ↔ Cube
pawnCube
ToPawnSphere
Cube ↔ Sphere
pawnSphere
ToPawnSphere
Sphere ↔ Sphere

Pawn shape × Block shape 조합은 5종, Pawn shape × Pawn shape 조합은 6종입니다. 각 큐는 shape 타입 쌍별로 분리되어 있어, 솔버가 필요한 타입의 쌍만 소비합니다.

Pawn-to-Block / Pawn-to-Pawn / World Solver

모든 overlap solver는 동일한 더블 버퍼 패턴을 공유합니다. 각 Job은 아래 필드를 입력받고, 실행 후 반드시 F/B 스왑이 따릅니다.

Pawn-to-Block
pawn_capsule_to_block_* _pairs_overlap_solver
PawnCapsuleToBlocksSchedule()

Capsule×Capsule, Capsule×Cube, Capsule×Sphere 3개의 Job이 순차 체인으로 스케줄됩니다. 각 Job 완료마다 F/B 스왑이 수행됩니다.

필드 타입 접근 설명
pairs NativeQueue<int2>.ReadOnly R Broad Phase가 수집한 (pawnIdx, blockIdx) 쌍
pawns NativeArray.ReadOnly R Pawn shape 데이터 (F 버퍼)
blocks NativeArray.ReadOnly R Block shape 데이터 (F 버퍼)
requests NativeArray.ReadOnly R Pawn 이동 요청 원본 (이번 프레임 입력)
pawn_priorities NativeArray.ReadOnly R Pawn 간 충돌 우선순위 (높은 쪽이 밀림)
moves / moves_write NativeArray (F / B) R / W 이동 벡터. F를 읽고 B에 씀. swap after job
block_positions
block_rotations
NativeArray.ReadOnly R Block 트랜스폼 (B 버퍼 — 이전 프레임 확정값)
block_priorities NativeArray.ReadOnly R Block 우선순위
cheats TactilesSystemDebug R #if DEBUG 치트 플래그 (충돌 무시 등)
Pawn-to-Pawn
pawn_capsule_to_pawn_capsule_overlap_solver
PawnCapsuleToPawnsSchedule()

Pawn 상호 충돌 솔버입니다. Block solver와 비교해 block 관련 필드가 없고, 양방향 우선순위로 이동 벡터를 조정합니다.

필드 타입 접근 설명
pairs NativeQueue<int2>.ReadOnly R Broad Phase가 수집한 (pawnA, pawnB) 쌍
pawns NativeArray.ReadOnly R 양측 Pawn shape 데이터
moves / moves_write NativeArray (F / B) R / W 이동 벡터 더블 버퍼. swap after job
priorities NativeArray.ReadOnly R Pawn 우선순위 — 낮은 쪽이 밀려납니다
cheats TactilesSystemDebug R #if DEBUG
World
pawn_capsule_to_world_solver
PawnCapsuleToPawnsSchedule() — 마지막 단계

Pawn-to-Block, Pawn-to-Pawn이 완료된 이후 마지막으로 실행됩니다. 월드 삼각형 데이터(floor/wall)와 Traversal을 참조해 최종 이동 벡터를 확정합니다.

필드 타입 접근 설명
pawns NativeArray.ReadOnly R Pawn shape
moves / moves_write NativeArray (F / B) R / W 최종 이동 벡터. swap after job
query_floor
query_wall
NativeArray<floor_triangle>
NativeArray<wall_triangle>
R Pawn 주변 샘플링된 삼각형 버퍼
traversals NativeArray<int> R 이동 가능 영역 인덱스 버퍼
floor_view
wall_view
VolumeOctree View R Native Volume Octree Read View — Broad Phase 이후 Narrow 샘플링용
battle_area_segments Segments View R 이동 가능 영역 경계 세그먼트
pawnCount int R 이번 프레임 active Pawn 수 (batch size)
cheats TactilesSystemDebug R #if DEBUG
01
pawn_capsule_kinematic_solver
↕ swap
02
pawn_capsule_to_block_capsule_pairs_overlap_solver
↕ swap
03
pawn_capsule_to_block_cube_pairs_overlap_solver
↕ swap
04
pawn_capsule_to_block_sphere_pairs_overlap_solver
↕ swap
05
pawn_capsule_to_pawn_capsule_overlap_solver
↕ swap
06
pawn_capsule_to_world_solver
↕ swap

모든 Job은 frameJob에 의존성이 연결된 단일 체인으로 동작합니다. Cube, Sphere shape도 동일한 구조를 따릅니다.