using Unity.Burst; using Unity.Collections; using Unity.Jobs; using Unity.Mathematics; namespace SepCore.Simulation { internal static class EnemyMovementSystem { // 读写集:R EnemyTransform / EnemyMoveInput / EnemyAttack;W EnemyTransform / EnemyBehavior public static JobHandle Schedule(EnemyStore enemies, float deltaTime, float3 playerPosition, JobHandle dependency) { int enemyCount = enemies.Count; if (enemyCount == 0) { return dependency; } EnemyMovementJob job = new EnemyMovementJob { Transforms = enemies.Transform.Data.AsArray(), MoveInputs = enemies.MoveInput.Data.AsArray(), Attacks = enemies.Attack.Data.AsArray(), Behaviors = enemies.Behavior.Data.AsArray(), DeltaTime = deltaTime, PlayerPosition = playerPosition }; return job.Schedule(enemyCount, 64, dependency); } } [BurstCompile] internal struct EnemyMovementJob : IJobParallelFor { public NativeArray Transforms; [ReadOnly] public NativeArray MoveInputs; [ReadOnly] public NativeArray Attacks; public NativeArray Behaviors; public float DeltaTime; public float3 PlayerPosition; public void Execute(int index) { EnemyMoveInputSim moveInput = MoveInputs[index]; EnemyAttackSim attack = Attacks[index]; EnemyTransformSim transform = Transforms[index]; float attackRange = attack.AttackRange > 0f ? attack.AttackRange : EnemyAttackSim.DefaultAttackRange; float attackRangeSqr = attackRange * attackRange; float3 currentPosition = transform.Position; float3 horizontalPosition = new float3(currentPosition.x, 0f, currentPosition.z); float3 toPlayer = PlayerPosition - horizontalPosition; float sqrDistance = math.lengthsq(toPlayer); bool isInAttackRange = sqrDistance <= attackRangeSqr; bool canChase = !isInAttackRange && moveInput.Speed > 0f && sqrDistance > float.Epsilon; float3 forward = transform.Forward; float3 desiredPosition = currentPosition; quaternion rotation = transform.Rotation; if (canChase) { forward = math.normalizesafe(toPlayer, forward); desiredPosition = currentPosition + forward * moveInput.Speed * DeltaTime; if (math.lengthsq(forward) > float.Epsilon) { rotation = quaternion.LookRotationSafe(forward, math.up()); } } int nextState; if (isInAttackRange) { nextState = EnemyBehaviorSim.StateInAttackRange; } else if (canChase) { nextState = EnemyBehaviorSim.StateChasing; } else { nextState = EnemyBehaviorSim.StateIdle; } transform.Position = desiredPosition; transform.Forward = forward; transform.Rotation = rotation; Transforms[index] = transform; Behaviors[index] = new EnemyBehaviorSim { State = nextState }; } } }