Checkpoint 7

1. Job 通道数据结构改为 Unity.Mathematics 类型(float3/quaternion),并保留 Simulation 主数据结构不变。
2. 更新了通道边界转换函数:进入 Job 通道时转为数学类型,回写 Simulation 时转回 Vector3/Quaternion。
3. 敌人 Job 热路径去掉 Vector3/Quaternion 中间态,核心执行统一 math.* + float3/quaternion。
4. 投射物移动 Job 热路径同样统一为数学类型计算与输出。
5. 新增 Burst 开关 A/B 一致性回归测试(EditMode + PlayMode),并补了反射入口校验。
This commit is contained in:
SepComet
2026-02-23 10:29:47 +08:00
parent f0abf78128
commit e6d722ee1d
20 changed files with 2096 additions and 51 deletions
@@ -20,7 +20,7 @@ namespace CustomComponent
private const float CornerTapWindow = 0.6f;
private const int RequiredCornerTapCount = 3;
private Rect _windowRect = new Rect(20f, 60f, 460f, 620f);
private Rect _windowRect = new Rect(20f, 60f, 460f, 800f);
private bool _isPanelVisible;
private int _windowId;
@@ -178,6 +178,15 @@ namespace CustomComponent
$"Area Resolve: hits {simulationWorld.LastResolvedAreaHitCount}");
GUILayout.Label(
$"Broad Phase: cell {simulationWorld.LastCollisionCellSize:F2}, hasEnemyTargets {(simulationWorld.LastCollisionHasEnemyTargets ? "Yes" : "No")}");
if (simulationWorld.LastCollisionCandidateCount != 0)
{
Log.Info($"LastCollisionCandidateCount:{simulationWorld.LastCollisionCandidateCount}");
}
if (simulationWorld.LastResolvedAreaHitCount != 0)
{
Log.Info($"LastResolvedAreaHitCount:{simulationWorld.LastResolvedAreaHitCount}");
}
}
GUILayout.BeginHorizontal();
@@ -398,4 +407,4 @@ namespace CustomComponent
}
}
}
#endif
#endif
@@ -364,7 +364,8 @@ namespace Simulation
return;
}
float3 position = new float3(output.Position.x, 0f, output.Position.z);
float3 position = output.Position;
position.y = 0f;
int cellX = (int)math.floor(position.x / cellSize);
int cellZ = (int)math.floor(position.z / cellSize);
buckets.Add(SeparationCellKey(cellX, cellZ), index);
@@ -384,7 +385,8 @@ namespace Simulation
return;
}
float3 candidate = new float3(self.Position.x, 0f, self.Position.z);
float3 candidate = self.Position;
candidate.y = 0f;
float3 original = candidate;
float3 fallback =
math.normalizesafe(new float3(self.Forward.x, 0f, self.Forward.z), new float3(1f, 0f, 0f));
@@ -426,7 +428,8 @@ namespace Simulation
float minDistance = selfRadius + otherRadius;
float minDistanceSqr = minDistance * minDistance;
float3 otherPosition = new float3(other.Position.x, 0f, other.Position.z);
float3 otherPosition = other.Position;
otherPosition.y = 0f;
float3 toSelf = candidate - otherPosition;
float sqrDistance = math.lengthsq(toSelf);
@@ -486,10 +489,10 @@ namespace Simulation
float3 finalPosition = original + smoothedPush;
currentPushes[index] = new float2(smoothedPush.x, smoothedPush.z);
self.Position = new Vector3(finalPosition.x, self.Position.y, finalPosition.z);
self.Position = new float3(finalPosition.x, self.Position.y, finalPosition.z);
if (math.lengthsq(smoothedPush) > float.Epsilon)
{
self.Forward = new Vector3(fallback.x, self.Forward.y, fallback.z);
self.Forward = new float3(fallback.x, self.Forward.y, fallback.z);
}
outputs[index] = self;
@@ -569,17 +572,16 @@ namespace Simulation
float attackRange = input.AttackRange > 0f ? input.AttackRange : DefaultAttackRange;
float attackRangeSqr = attackRange * attackRange;
float3 currentPosition = new float3(input.Position.x, input.Position.y, input.Position.z);
float3 currentPosition = input.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 && input.Speed > 0f && sqrDistance > float.Epsilon;
float3 forward = new float3(input.Forward.x, input.Forward.y, input.Forward.z);
float3 forward = input.Forward;
float3 desiredPosition = currentPosition;
quaternion rotation =
new quaternion(input.Rotation.x, input.Rotation.y, input.Rotation.z, input.Rotation.w);
quaternion rotation = input.Rotation;
if (canChase)
{
@@ -608,9 +610,9 @@ namespace Simulation
outputs[index] = new EnemyJobOutputData
{
EntityId = input.EntityId,
Position = new Vector3(desiredPosition.x, desiredPosition.y, desiredPosition.z),
Forward = new Vector3(forward.x, forward.y, forward.z),
Rotation = new Quaternion(rotation.value.x, rotation.value.y, rotation.value.z, rotation.value.w),
Position = desiredPosition,
Forward = forward,
Rotation = rotation,
Speed = input.Speed,
AttackRange = attackRange,
AvoidEnemyOverlap = input.AvoidEnemyOverlap,
@@ -11,9 +11,9 @@ namespace Simulation
private struct EnemyJobInputData
{
public int EntityId;
public Vector3 Position;
public Vector3 Forward;
public Quaternion Rotation;
public float3 Position;
public float3 Forward;
public quaternion Rotation;
public float Speed;
public float AttackRange;
public bool AvoidEnemyOverlap;
@@ -26,9 +26,9 @@ namespace Simulation
private struct EnemyJobOutputData
{
public int EntityId;
public Vector3 Position;
public Vector3 Forward;
public Quaternion Rotation;
public float3 Position;
public float3 Forward;
public quaternion Rotation;
public float Speed;
public float AttackRange;
public bool AvoidEnemyOverlap;
@@ -42,9 +42,9 @@ namespace Simulation
{
public int EntityId;
public int OwnerEntityId;
public Vector3 Position;
public Vector3 Forward;
public Vector3 Velocity;
public float3 Position;
public float3 Forward;
public float3 Velocity;
public float Speed;
public float LifeTime;
public float Age;
@@ -57,9 +57,9 @@ namespace Simulation
{
public int EntityId;
public int OwnerEntityId;
public Vector3 Position;
public Vector3 Forward;
public Vector3 Velocity;
public float3 Position;
public float3 Forward;
public float3 Velocity;
public float Speed;
public float LifeTime;
public float Age;
@@ -474,7 +474,7 @@ namespace Simulation
SourceType = CollisionSourceTypeProjectile,
SourceEntityId = projectile.EntityId,
SourceOwnerEntityId = projectile.OwnerEntityId,
Position = new float3(projectile.Position.x, projectile.Position.y, projectile.Position.z),
Position = projectile.Position,
Radius = radius,
MaxTargets = math.max(1, maxTargets),
ShapeType = CollisionShapeCircle,
@@ -700,9 +700,9 @@ namespace Simulation
return new EnemyJobInputData
{
EntityId = enemy.EntityId,
Position = enemy.Position,
Forward = enemy.Forward,
Rotation = enemy.Rotation,
Position = new float3(enemy.Position.x, enemy.Position.y, enemy.Position.z),
Forward = new float3(enemy.Forward.x, enemy.Forward.y, enemy.Forward.z),
Rotation = new quaternion(enemy.Rotation.x, enemy.Rotation.y, enemy.Rotation.z, enemy.Rotation.w),
Speed = enemy.Speed,
AttackRange = enemy.AttackRange,
AvoidEnemyOverlap = enemy.AvoidEnemyOverlap,
@@ -718,9 +718,9 @@ namespace Simulation
return new EnemyJobOutputData
{
EntityId = enemy.EntityId,
Position = enemy.Position,
Forward = enemy.Forward,
Rotation = enemy.Rotation,
Position = new float3(enemy.Position.x, enemy.Position.y, enemy.Position.z),
Forward = new float3(enemy.Forward.x, enemy.Forward.y, enemy.Forward.z),
Rotation = new quaternion(enemy.Rotation.x, enemy.Rotation.y, enemy.Rotation.z, enemy.Rotation.w),
Speed = enemy.Speed,
AttackRange = enemy.AttackRange,
AvoidEnemyOverlap = enemy.AvoidEnemyOverlap,
@@ -736,9 +736,10 @@ namespace Simulation
return new EnemySimData
{
EntityId = enemy.EntityId,
Position = enemy.Position,
Forward = enemy.Forward,
Rotation = enemy.Rotation,
Position = new Vector3(enemy.Position.x, enemy.Position.y, enemy.Position.z),
Forward = new Vector3(enemy.Forward.x, enemy.Forward.y, enemy.Forward.z),
Rotation = new Quaternion(enemy.Rotation.value.x, enemy.Rotation.value.y, enemy.Rotation.value.z,
enemy.Rotation.value.w),
Speed = enemy.Speed,
AttackRange = enemy.AttackRange,
AvoidEnemyOverlap = enemy.AvoidEnemyOverlap,
@@ -755,9 +756,9 @@ namespace Simulation
{
EntityId = projectile.EntityId,
OwnerEntityId = projectile.OwnerEntityId,
Position = projectile.Position,
Forward = projectile.Forward,
Velocity = projectile.Velocity,
Position = new float3(projectile.Position.x, projectile.Position.y, projectile.Position.z),
Forward = new float3(projectile.Forward.x, projectile.Forward.y, projectile.Forward.z),
Velocity = new float3(projectile.Velocity.x, projectile.Velocity.y, projectile.Velocity.z),
Speed = projectile.Speed,
LifeTime = projectile.LifeTime,
Age = projectile.Age,
@@ -773,9 +774,9 @@ namespace Simulation
{
EntityId = projectile.EntityId,
OwnerEntityId = projectile.OwnerEntityId,
Position = projectile.Position,
Forward = projectile.Forward,
Velocity = projectile.Velocity,
Position = new float3(projectile.Position.x, projectile.Position.y, projectile.Position.z),
Forward = new float3(projectile.Forward.x, projectile.Forward.y, projectile.Forward.z),
Velocity = new float3(projectile.Velocity.x, projectile.Velocity.y, projectile.Velocity.z),
Speed = projectile.Speed,
LifeTime = projectile.LifeTime,
Age = projectile.Age,
@@ -791,9 +792,9 @@ namespace Simulation
{
EntityId = projectile.EntityId,
OwnerEntityId = projectile.OwnerEntityId,
Position = projectile.Position,
Forward = projectile.Forward,
Velocity = projectile.Velocity,
Position = new Vector3(projectile.Position.x, projectile.Position.y, projectile.Position.z),
Forward = new Vector3(projectile.Forward.x, projectile.Forward.y, projectile.Forward.z),
Velocity = new Vector3(projectile.Velocity.x, projectile.Velocity.y, projectile.Velocity.z),
Speed = projectile.Speed,
LifeTime = projectile.LifeTime,
Age = projectile.Age,
@@ -957,9 +957,9 @@ namespace Simulation
return;
}
float3 position = new float3(input.Position.x, input.Position.y, input.Position.z);
float3 forward = new float3(input.Forward.x, input.Forward.y, input.Forward.z);
float3 velocity = new float3(input.Velocity.x, input.Velocity.y, input.Velocity.z);
float3 position = input.Position;
float3 forward = input.Forward;
float3 velocity = input.Velocity;
if (math.lengthsq(velocity) <= float.Epsilon && input.Speed > 0f)
{
float3 moveDirection = math.normalizesafe(forward, new float3(0f, 0f, 1f));
@@ -994,8 +994,8 @@ namespace Simulation
shouldExpire = math.abs(nextPosition.y - playerPosition.y) > maxVerticalOffsetFromPlayer;
}
output.Position = new Vector3(nextPosition.x, nextPosition.y, nextPosition.z);
output.Velocity = new Vector3(velocity.x, velocity.y, velocity.z);
output.Position = nextPosition;
output.Velocity = velocity;
output.Age = nextAge;
output.RemainingLifetime = nextRemainingLifetime;
output.Active = !shouldExpire;
@@ -1004,7 +1004,7 @@ namespace Simulation
if (math.lengthsq(velocity) > float.Epsilon)
{
float3 moveForward = math.normalizesafe(velocity, forward);
output.Forward = new Vector3(moveForward.x, moveForward.y, moveForward.z);
output.Forward = moveForward;
}
outputs[index] = output;