Checkpoint 1:
- 新增三类 SimData:
- EnemySimData
- ProjectileSimData
- PickupSimData
- 新增 Tick 上下文:SimulationTickContext
- 新增双向索引绑定:EntityBinding
- 新增纯数据容器世界:SimulationWorld
This commit is contained in:
parent
ed3b37d0f7
commit
3b8e0731f0
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 7f519a6e4d7b4cb4ab5eabf95fb55e1b
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
using UnityEngine;
|
||||
|
||||
namespace Simulation
|
||||
{
|
||||
public struct EnemySimData
|
||||
{
|
||||
public int EntityId;
|
||||
public Vector3 Position;
|
||||
public Vector3 Forward;
|
||||
public float Speed;
|
||||
public float AttackRange;
|
||||
public int TargetType;
|
||||
public int State;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: ef2eea85685544189eef2d9f2cece080
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace Simulation
|
||||
{
|
||||
public sealed class EntityBinding
|
||||
{
|
||||
private readonly Dictionary<int, int> _entityIdToSimulationIndex = new Dictionary<int, int>();
|
||||
private readonly Dictionary<int, int> _simulationIndexToEntityId = new Dictionary<int, int>();
|
||||
|
||||
public int Count => _entityIdToSimulationIndex.Count;
|
||||
|
||||
public void Bind(int entityId, int simulationIndex)
|
||||
{
|
||||
if (_entityIdToSimulationIndex.TryGetValue(entityId, out int oldSimulationIndex))
|
||||
{
|
||||
_simulationIndexToEntityId.Remove(oldSimulationIndex);
|
||||
}
|
||||
|
||||
if (_simulationIndexToEntityId.TryGetValue(simulationIndex, out int oldEntityId))
|
||||
{
|
||||
_entityIdToSimulationIndex.Remove(oldEntityId);
|
||||
}
|
||||
|
||||
_entityIdToSimulationIndex[entityId] = simulationIndex;
|
||||
_simulationIndexToEntityId[simulationIndex] = entityId;
|
||||
}
|
||||
|
||||
public void RemapIndex(int entityId, int newSimulationIndex)
|
||||
{
|
||||
if (!_entityIdToSimulationIndex.TryGetValue(entityId, out int oldSimulationIndex))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_simulationIndexToEntityId.Remove(oldSimulationIndex);
|
||||
_entityIdToSimulationIndex[entityId] = newSimulationIndex;
|
||||
_simulationIndexToEntityId[newSimulationIndex] = entityId;
|
||||
}
|
||||
|
||||
public bool TryGetSimulationIndex(int entityId, out int simulationIndex)
|
||||
{
|
||||
return _entityIdToSimulationIndex.TryGetValue(entityId, out simulationIndex);
|
||||
}
|
||||
|
||||
public bool TryGetEntityId(int simulationIndex, out int entityId)
|
||||
{
|
||||
return _simulationIndexToEntityId.TryGetValue(simulationIndex, out entityId);
|
||||
}
|
||||
|
||||
public bool UnbindByEntityId(int entityId)
|
||||
{
|
||||
if (!_entityIdToSimulationIndex.TryGetValue(entityId, out int simulationIndex))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
_entityIdToSimulationIndex.Remove(entityId);
|
||||
_simulationIndexToEntityId.Remove(simulationIndex);
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool UnbindBySimulationIndex(int simulationIndex)
|
||||
{
|
||||
if (!_simulationIndexToEntityId.TryGetValue(simulationIndex, out int entityId))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
_simulationIndexToEntityId.Remove(simulationIndex);
|
||||
_entityIdToSimulationIndex.Remove(entityId);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
_entityIdToSimulationIndex.Clear();
|
||||
_simulationIndexToEntityId.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: c4f6d93561db4b9092ab61182f2983d7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
using UnityEngine;
|
||||
|
||||
namespace Simulation
|
||||
{
|
||||
public struct PickupSimData
|
||||
{
|
||||
public int EntityId;
|
||||
public Vector3 Position;
|
||||
public float PickupRadius;
|
||||
public int State;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: ff6e8b75e4af4c3ca9e3b732b1383f95
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
using UnityEngine;
|
||||
|
||||
namespace Simulation
|
||||
{
|
||||
public struct ProjectileSimData
|
||||
{
|
||||
public int EntityId;
|
||||
public int OwnerEntityId;
|
||||
public Vector3 Position;
|
||||
public Vector3 Forward;
|
||||
public float Speed;
|
||||
public float RemainingLifetime;
|
||||
public int State;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 2eec1f4389004d69bdce8c4dd95d255e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
using UnityEngine;
|
||||
|
||||
namespace Simulation
|
||||
{
|
||||
public readonly struct SimulationTickContext
|
||||
{
|
||||
public SimulationTickContext(float deltaTime, float realDeltaTime, Vector3 playerPosition)
|
||||
{
|
||||
DeltaTime = deltaTime;
|
||||
RealDeltaTime = realDeltaTime;
|
||||
PlayerPosition = playerPosition;
|
||||
}
|
||||
|
||||
public float DeltaTime { get; }
|
||||
public float RealDeltaTime { get; }
|
||||
public Vector3 PlayerPosition { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: c4c57fcf285f488b821c9141a6d0ad09
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,119 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace Simulation
|
||||
{
|
||||
public sealed class SimulationWorld
|
||||
{
|
||||
private readonly List<EnemySimData> _enemies = new List<EnemySimData>();
|
||||
private readonly List<ProjectileSimData> _projectiles = new List<ProjectileSimData>();
|
||||
private readonly List<PickupSimData> _pickups = new List<PickupSimData>();
|
||||
|
||||
public EntityBinding EnemyBinding { get; } = new EntityBinding();
|
||||
public EntityBinding ProjectileBinding { get; } = new EntityBinding();
|
||||
public EntityBinding PickupBinding { get; } = new EntityBinding();
|
||||
|
||||
public IReadOnlyList<EnemySimData> Enemies => _enemies;
|
||||
public IReadOnlyList<ProjectileSimData> Projectiles => _projectiles;
|
||||
public IReadOnlyList<PickupSimData> Pickups => _pickups;
|
||||
|
||||
public int AddEnemy(in EnemySimData simData)
|
||||
{
|
||||
int simulationIndex = _enemies.Count;
|
||||
_enemies.Add(simData);
|
||||
EnemyBinding.Bind(simData.EntityId, simulationIndex);
|
||||
return simulationIndex;
|
||||
}
|
||||
|
||||
public bool RemoveEnemyByEntityId(int entityId)
|
||||
{
|
||||
if (!EnemyBinding.TryGetSimulationIndex(entityId, out int simulationIndex))
|
||||
{
|
||||
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);
|
||||
EnemyBinding.UnbindByEntityId(entityId);
|
||||
return true;
|
||||
}
|
||||
|
||||
public int AddProjectile(in ProjectileSimData simData)
|
||||
{
|
||||
int simulationIndex = _projectiles.Count;
|
||||
_projectiles.Add(simData);
|
||||
ProjectileBinding.Bind(simData.EntityId, simulationIndex);
|
||||
return simulationIndex;
|
||||
}
|
||||
|
||||
public 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;
|
||||
}
|
||||
|
||||
public int AddPickup(in PickupSimData simData)
|
||||
{
|
||||
int simulationIndex = _pickups.Count;
|
||||
_pickups.Add(simData);
|
||||
PickupBinding.Bind(simData.EntityId, simulationIndex);
|
||||
return simulationIndex;
|
||||
}
|
||||
|
||||
public 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;
|
||||
}
|
||||
|
||||
public void Tick(in SimulationTickContext context)
|
||||
{
|
||||
_ = context;
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
_enemies.Clear();
|
||||
_projectiles.Clear();
|
||||
_pickups.Clear();
|
||||
|
||||
EnemyBinding.Clear();
|
||||
ProjectileBinding.Clear();
|
||||
PickupBinding.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 8a558ebbc9cb4d94946ac9f4f27914d8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -25,7 +25,7 @@
|
|||
- 以上问题修正后,核心流程可稳定连续跑 10 分钟无异常日志。
|
||||
|
||||
## 2. P1 Simulation 分层(为 Job/Burst 做结构准备)
|
||||
- [ ] Checkpoint 1:搭建 Simulation 基础骨架(仅新增,不改行为)
|
||||
- [x] Checkpoint 1:搭建 Simulation 基础骨架(仅新增,不改行为)
|
||||
- 新建目录:`Assets/GameMain/Scripts/Simulation`。
|
||||
- 新建 `SimulationWorld`,统一持有 `EnemySimData / ProjectileSimData / PickupSimData` 容器。
|
||||
- 新建 `EntityBinding`,维护 `EntityId <-> SimulationIndex` 双向映射。
|
||||
|
|
|
|||
Loading…
Reference in New Issue