简单重构拆分 SimulationWorld
This commit is contained in:
+222
-114
@@ -1,4 +1,5 @@
|
||||
using SepCore.Entity;
|
||||
using UnityEngine;
|
||||
|
||||
namespace SepCore.Simulation
|
||||
{
|
||||
@@ -16,11 +17,8 @@ namespace SepCore.Simulation
|
||||
_areaCollisionRequests.Clear();
|
||||
_areaCollisionHitEvents.Clear();
|
||||
_areaCollisionHitDedupKeys.Clear();
|
||||
_fixedStepAccumulator = 0d;
|
||||
ClearJobDataChannels();
|
||||
|
||||
EnemyBinding.Clear();
|
||||
ProjectileBinding.Clear();
|
||||
PickupBinding.Clear();
|
||||
ClearPlayerMovementState();
|
||||
}
|
||||
|
||||
@@ -28,46 +26,96 @@ namespace SepCore.Simulation
|
||||
|
||||
#region Enemy Simulation State
|
||||
|
||||
private int AddEnemy(in EnemySimData simData)
|
||||
{
|
||||
int simulationIndex = _enemies.Count;
|
||||
_enemies.Add(simData);
|
||||
EnemyBinding.Bind(simData.EntityId, simulationIndex);
|
||||
OnEnemyAddedToSeparationTemporalBuffers();
|
||||
MarkEnemyTargetSpatialIndexDirty();
|
||||
return simulationIndex;
|
||||
}
|
||||
public int EnemyCount => _enemies.Count;
|
||||
|
||||
private int UpsertEnemy(in EnemySimData simData)
|
||||
public bool TryGetEnemySnapshot(int entityId, out EnemySimData snapshot)
|
||||
{
|
||||
if (!EnemyBinding.TryGetSimulationIndex(simData.EntityId, out int simulationIndex))
|
||||
if (!_enemies.TryGetSimulationIndex(entityId, out int index))
|
||||
{
|
||||
return AddEnemy(simData);
|
||||
snapshot = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
_enemies[simulationIndex] = simData;
|
||||
EnemyTransformSim transform = _enemies.Transform[index];
|
||||
EnemyMoveInputSim moveInput = _enemies.MoveInput[index];
|
||||
EnemyMoveConfigSim moveConfig = _enemies.MoveConfig[index];
|
||||
EnemyAttackSim attack = _enemies.Attack[index];
|
||||
EnemyBehaviorSim behavior = _enemies.Behavior[index];
|
||||
snapshot = new EnemySimData
|
||||
{
|
||||
EntityId = entityId,
|
||||
Position = ToVector3(transform.Position),
|
||||
Forward = ToVector3(transform.Forward),
|
||||
Rotation = ToQuaternion(transform.Rotation),
|
||||
Speed = moveInput.Speed,
|
||||
AttackRange = attack.AttackRange,
|
||||
AvoidEnemyOverlap = moveConfig.AvoidOverlap,
|
||||
EnemyBodyRadius = moveConfig.BodyRadius,
|
||||
SeparationIterations = moveConfig.SeparationIterations,
|
||||
State = behavior.State
|
||||
};
|
||||
return true;
|
||||
}
|
||||
|
||||
private int AddEnemy(in EnemySimData simData)
|
||||
{
|
||||
InitializeJobDataChannels();
|
||||
|
||||
int index = _enemies.Add(
|
||||
new EnemyIdentitySim { EntityId = simData.EntityId },
|
||||
new EnemyTransformSim
|
||||
{
|
||||
Position = ToFloat3(simData.Position),
|
||||
Forward = ToFloat3(simData.Forward),
|
||||
Rotation = ToQuaternion(simData.Rotation)
|
||||
},
|
||||
new EnemyMoveInputSim { Speed = simData.Speed },
|
||||
new EnemyMoveConfigSim
|
||||
{
|
||||
AvoidOverlap = simData.AvoidEnemyOverlap,
|
||||
BodyRadius = simData.EnemyBodyRadius,
|
||||
SeparationIterations = simData.SeparationIterations
|
||||
},
|
||||
new EnemyAttackSim { AttackRange = simData.AttackRange },
|
||||
new EnemyBehaviorSim { State = simData.State });
|
||||
MarkEnemyTargetSpatialIndexDirty();
|
||||
return simulationIndex;
|
||||
return index;
|
||||
}
|
||||
|
||||
internal int UpsertEnemy(in EnemySimData simData)
|
||||
{
|
||||
if (!_enemies.TryGetSimulationIndex(simData.EntityId, out int index))
|
||||
{
|
||||
return AddEnemy(in simData);
|
||||
}
|
||||
|
||||
_enemies.Identity[index] = new EnemyIdentitySim { EntityId = simData.EntityId };
|
||||
_enemies.Transform[index] = new EnemyTransformSim
|
||||
{
|
||||
Position = ToFloat3(simData.Position),
|
||||
Forward = ToFloat3(simData.Forward),
|
||||
Rotation = ToQuaternion(simData.Rotation)
|
||||
};
|
||||
_enemies.MoveInput[index] = new EnemyMoveInputSim { Speed = simData.Speed };
|
||||
_enemies.MoveConfig[index] = new EnemyMoveConfigSim
|
||||
{
|
||||
AvoidOverlap = simData.AvoidEnemyOverlap,
|
||||
BodyRadius = simData.EnemyBodyRadius,
|
||||
SeparationIterations = simData.SeparationIterations
|
||||
};
|
||||
_enemies.Attack[index] = new EnemyAttackSim { AttackRange = simData.AttackRange };
|
||||
_enemies.Behavior[index] = new EnemyBehaviorSim { State = simData.State };
|
||||
MarkEnemyTargetSpatialIndexDirty();
|
||||
return index;
|
||||
}
|
||||
|
||||
private bool RemoveEnemyByEntityId(int entityId)
|
||||
{
|
||||
if (!EnemyBinding.TryGetSimulationIndex(entityId, out int simulationIndex))
|
||||
if (!_enemies.RemoveByEntityId(entityId))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int lastIndex = _enemies.Count - 1;
|
||||
if (simulationIndex != lastIndex)
|
||||
{
|
||||
EnemySimData movedData = _enemies[lastIndex];
|
||||
_enemies[simulationIndex] = movedData;
|
||||
EnemyBinding.RemapIndex(movedData.EntityId, simulationIndex);
|
||||
}
|
||||
|
||||
_enemies.RemoveAt(lastIndex);
|
||||
OnEnemyRemovedFromSeparationTemporalBuffers(simulationIndex);
|
||||
EnemyBinding.UnbindByEntityId(entityId);
|
||||
MarkEnemyTargetSpatialIndexDirty();
|
||||
return true;
|
||||
}
|
||||
@@ -88,85 +136,122 @@ namespace SepCore.Simulation
|
||||
RemoveEnemyByEntityId(entityId);
|
||||
}
|
||||
|
||||
private bool TryGetEnemyData(int entityId, out EnemySimData enemyData)
|
||||
{
|
||||
if (!EnemyBinding.TryGetSimulationIndex(entityId, out int simulationIndex) || simulationIndex < 0 ||
|
||||
simulationIndex >= _enemies.Count)
|
||||
{
|
||||
enemyData = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
enemyData = _enemies[simulationIndex];
|
||||
return true;
|
||||
}
|
||||
|
||||
public void SyncEnemyMovementInput(int entityId, bool isMoving, in UnityEngine.Vector3 direction, float speed,
|
||||
public void SyncEnemyMovementInput(int entityId, bool isMoving, in Vector3 direction, float speed,
|
||||
bool avoidEnemyOverlap, float enemyBodyRadius, int separationIterations)
|
||||
{
|
||||
if (!EnemyBinding.TryGetSimulationIndex(entityId, out int simulationIndex) || simulationIndex < 0 ||
|
||||
simulationIndex >= _enemies.Count)
|
||||
if (!_enemies.TryGetSimulationIndex(entityId, out int index))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
EnemySimData enemyData = _enemies[simulationIndex];
|
||||
enemyData.Speed = isMoving ? UnityEngine.Mathf.Max(0f, speed) : 0f;
|
||||
enemyData.AvoidEnemyOverlap = avoidEnemyOverlap;
|
||||
enemyData.EnemyBodyRadius = UnityEngine.Mathf.Max(0.01f, enemyBodyRadius);
|
||||
enemyData.SeparationIterations = UnityEngine.Mathf.Max(1, separationIterations);
|
||||
|
||||
UnityEngine.Vector3 planarDirection = direction;
|
||||
planarDirection.y = 0f;
|
||||
if (planarDirection.sqrMagnitude > UnityEngine.Mathf.Epsilon)
|
||||
_enemies.MoveInput[index] = new EnemyMoveInputSim
|
||||
{
|
||||
enemyData.Forward = planarDirection.normalized;
|
||||
}
|
||||
Speed = isMoving ? Mathf.Max(0f, speed) : 0f
|
||||
};
|
||||
_enemies.MoveConfig[index] = new EnemyMoveConfigSim
|
||||
{
|
||||
AvoidOverlap = avoidEnemyOverlap,
|
||||
BodyRadius = Mathf.Max(0.01f, enemyBodyRadius),
|
||||
SeparationIterations = Mathf.Max(1, separationIterations)
|
||||
};
|
||||
|
||||
_enemies[simulationIndex] = enemyData;
|
||||
Vector3 planarDirection = direction;
|
||||
planarDirection.y = 0f;
|
||||
if (planarDirection.sqrMagnitude > Mathf.Epsilon)
|
||||
{
|
||||
planarDirection.Normalize();
|
||||
EnemyTransformSim transform = _enemies.Transform[index];
|
||||
transform.Forward = ToFloat3(planarDirection);
|
||||
_enemies.Transform[index] = transform;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Projectile Simulation State
|
||||
|
||||
private int AddProjectile(in ProjectileSimData simData)
|
||||
{
|
||||
int simulationIndex = _projectiles.Count;
|
||||
_projectiles.Add(simData);
|
||||
ProjectileBinding.Bind(simData.EntityId, simulationIndex);
|
||||
return simulationIndex;
|
||||
}
|
||||
public int ProjectileCount => _projectiles.Count;
|
||||
|
||||
private int UpsertProjectile(in ProjectileSimData simData)
|
||||
public bool TryGetProjectileSnapshot(int entityId, out ProjectileSimData snapshot)
|
||||
{
|
||||
if (!ProjectileBinding.TryGetSimulationIndex(simData.EntityId, out int simulationIndex))
|
||||
if (!_projectiles.TryGetSimulationIndex(entityId, out int index))
|
||||
{
|
||||
return AddProjectile(simData);
|
||||
snapshot = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
_projectiles[simulationIndex] = simData;
|
||||
return simulationIndex;
|
||||
ProjectileIdentitySim identity = _projectiles.Identity[index];
|
||||
ProjectileTransformSim transform = _projectiles.Transform[index];
|
||||
ProjectileVelocitySim velocity = _projectiles.Velocity[index];
|
||||
ProjectileLifeSim life = _projectiles.Life[index];
|
||||
snapshot = new ProjectileSimData
|
||||
{
|
||||
EntityId = identity.EntityId,
|
||||
OwnerEntityId = identity.OwnerEntityId,
|
||||
Position = ToVector3(transform.Position),
|
||||
Forward = ToVector3(transform.Forward),
|
||||
Velocity = ToVector3(velocity.Velocity),
|
||||
LifeTime = life.LifeTime,
|
||||
Age = life.Age,
|
||||
Active = life.Active
|
||||
};
|
||||
return true;
|
||||
}
|
||||
|
||||
private int AddProjectile(in ProjectileSimData simData)
|
||||
{
|
||||
InitializeJobDataChannels();
|
||||
|
||||
return _projectiles.Add(
|
||||
new ProjectileIdentitySim
|
||||
{
|
||||
EntityId = simData.EntityId,
|
||||
OwnerEntityId = simData.OwnerEntityId
|
||||
},
|
||||
new ProjectileTransformSim
|
||||
{
|
||||
Position = ToFloat3(simData.Position),
|
||||
Forward = ToFloat3(simData.Forward)
|
||||
},
|
||||
new ProjectileVelocitySim { Velocity = ToFloat3(simData.Velocity) },
|
||||
new ProjectileLifeSim
|
||||
{
|
||||
Age = simData.Age,
|
||||
LifeTime = simData.LifeTime,
|
||||
Active = simData.Active
|
||||
});
|
||||
}
|
||||
|
||||
internal int UpsertProjectile(in ProjectileSimData simData)
|
||||
{
|
||||
if (!_projectiles.TryGetSimulationIndex(simData.EntityId, out int index))
|
||||
{
|
||||
return AddProjectile(in simData);
|
||||
}
|
||||
|
||||
_projectiles.Identity[index] = new ProjectileIdentitySim
|
||||
{
|
||||
EntityId = simData.EntityId,
|
||||
OwnerEntityId = simData.OwnerEntityId
|
||||
};
|
||||
_projectiles.Transform[index] = new ProjectileTransformSim
|
||||
{
|
||||
Position = ToFloat3(simData.Position),
|
||||
Forward = ToFloat3(simData.Forward)
|
||||
};
|
||||
_projectiles.Velocity[index] = new ProjectileVelocitySim { Velocity = ToFloat3(simData.Velocity) };
|
||||
_projectiles.Life[index] = new ProjectileLifeSim
|
||||
{
|
||||
Age = simData.Age,
|
||||
LifeTime = simData.LifeTime,
|
||||
Active = simData.Active
|
||||
};
|
||||
return index;
|
||||
}
|
||||
|
||||
private bool RemoveProjectileByEntityId(int entityId)
|
||||
{
|
||||
if (!ProjectileBinding.TryGetSimulationIndex(entityId, out int simulationIndex))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int lastIndex = _projectiles.Count - 1;
|
||||
if (simulationIndex != lastIndex)
|
||||
{
|
||||
ProjectileSimData movedData = _projectiles[lastIndex];
|
||||
_projectiles[simulationIndex] = movedData;
|
||||
ProjectileBinding.RemapIndex(movedData.EntityId, simulationIndex);
|
||||
}
|
||||
|
||||
_projectiles.RemoveAt(lastIndex);
|
||||
ProjectileBinding.UnbindByEntityId(entityId);
|
||||
return true;
|
||||
return _projectiles.RemoveByEntityId(entityId);
|
||||
}
|
||||
|
||||
private void RegisterProjectileLifecycle(EntityBase projectileEntity, object userData)
|
||||
@@ -188,43 +273,66 @@ namespace SepCore.Simulation
|
||||
|
||||
#region Pickup Simulation State
|
||||
|
||||
private int AddPickup(in PickupSimData simData)
|
||||
{
|
||||
int simulationIndex = _pickups.Count;
|
||||
_pickups.Add(simData);
|
||||
PickupBinding.Bind(simData.EntityId, simulationIndex);
|
||||
return simulationIndex;
|
||||
}
|
||||
public int PickupCount => _pickups.Count;
|
||||
|
||||
private int UpsertPickup(in PickupSimData simData)
|
||||
public bool TryGetPickupSnapshot(int entityId, out PickupSimData snapshot)
|
||||
{
|
||||
if (!PickupBinding.TryGetSimulationIndex(simData.EntityId, out int simulationIndex))
|
||||
if (!_pickups.TryGetSimulationIndex(entityId, out int index))
|
||||
{
|
||||
return AddPickup(simData);
|
||||
snapshot = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
_pickups[simulationIndex] = simData;
|
||||
return simulationIndex;
|
||||
PickupTransformSim transform = _pickups.Transform[index];
|
||||
PickupRadiusSim radius = _pickups.Radius[index];
|
||||
PickupStateSim state = _pickups.State[index];
|
||||
snapshot = new PickupSimData
|
||||
{
|
||||
EntityId = entityId,
|
||||
Position = ToVector3(transform.Position),
|
||||
PickupRadius = radius.Radius,
|
||||
State = state.State
|
||||
};
|
||||
return true;
|
||||
}
|
||||
|
||||
private int AddPickup(in PickupSimData simData)
|
||||
{
|
||||
InitializeJobDataChannels();
|
||||
|
||||
return _pickups.Add(
|
||||
new PickupIdentitySim { EntityId = simData.EntityId },
|
||||
new PickupTransformSim { Position = ToFloat3(simData.Position) },
|
||||
new PickupRadiusSim { Radius = simData.PickupRadius },
|
||||
new PickupStateSim { State = simData.State });
|
||||
}
|
||||
|
||||
internal int UpsertPickup(in PickupSimData simData)
|
||||
{
|
||||
if (!_pickups.TryGetSimulationIndex(simData.EntityId, out int index))
|
||||
{
|
||||
return AddPickup(in simData);
|
||||
}
|
||||
|
||||
_pickups.Identity[index] = new PickupIdentitySim { EntityId = simData.EntityId };
|
||||
_pickups.Transform[index] = new PickupTransformSim { Position = ToFloat3(simData.Position) };
|
||||
_pickups.Radius[index] = new PickupRadiusSim { Radius = simData.PickupRadius };
|
||||
_pickups.State[index] = new PickupStateSim { State = simData.State };
|
||||
return index;
|
||||
}
|
||||
|
||||
public void TriggerFullMapMagnet()
|
||||
{
|
||||
int pickupCount = _pickups.Count;
|
||||
for (int i = 0; i < pickupCount; i++)
|
||||
{
|
||||
_pickups.State[i] = new PickupStateSim { State = PickupStateSim.StateAbsorbing };
|
||||
}
|
||||
}
|
||||
|
||||
private bool RemovePickupByEntityId(int entityId)
|
||||
{
|
||||
if (!PickupBinding.TryGetSimulationIndex(entityId, out int simulationIndex))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int lastIndex = _pickups.Count - 1;
|
||||
if (simulationIndex != lastIndex)
|
||||
{
|
||||
PickupSimData movedData = _pickups[lastIndex];
|
||||
_pickups[simulationIndex] = movedData;
|
||||
PickupBinding.RemapIndex(movedData.EntityId, simulationIndex);
|
||||
}
|
||||
|
||||
_pickups.RemoveAt(lastIndex);
|
||||
PickupBinding.UnbindByEntityId(entityId);
|
||||
return true;
|
||||
return _pickups.RemoveByEntityId(entityId);
|
||||
}
|
||||
|
||||
private void RegisterPickupLifecycle(EntityBase pickupEntity)
|
||||
|
||||
Reference in New Issue
Block a user