Files
vampire-like/Assets/GameMain/Scripts/Runtime/CustomComponent/Simulation/SimulationWorld.cs
T

110 lines
4.5 KiB
C#

using SepCore.Debugger;
using UnityEngine;
using UnityGameFramework.Runtime;
namespace SepCore.Simulation
{
public sealed partial class SimulationWorld : GameFrameworkComponent, ISimulationWorld
{
// Partial layout:
// - SimulationWorld.cs: 核心状态、常量和 Unity 生命周期入口点。
// - SimulationWorld.RuntimeModules.cs: 运行时域对象、配置和状态代理。
// - SimulationWorld.SimEntityState.cs: 模拟状态的增删改查和生命周期注册。
// - SimulationWorld.EntityToSimData.cs: Unity 实体与组件列/快照之间的边界转换。
// - SimulationWorld.EntitySync.cs: GameFramework 实体 show/hide 事件桥。
// - SimulationWorld.TargetSelectionSpatialIndex.cs: 最近敌空间索引查询。
// - SimulationWorld.PlayerMovement.cs: 玩家模拟移动输入与步进。
// - Components/*: 敌人/投射物/掉落物 SoA 组件列与存储。
// - Presentation/SimulationWorld.TransformSync.cs: late-update transform 同步桥。
// - Presentation/SimulationWorld.HitPresentation.cs: 投射物命中事件表现桥。
// - DataChannel/*: Job 通道与帧间临时状态。
// - Systems/*: 独立数据并行系统(移动/分离/碰撞查询)。
// - Jobs/*: 模拟管线编排、碰撞调度与结算。
// - JobStruct/*: 面向 job 的瞬时数据结构。
// 模拟数据以组件列(SoA)为唯一存储,XxxSimData 只作为生成/查询边界的快照结构。
private const float MinFixedStepSeconds = 0.0001f;
private const double FixedStepEpsilonScale = 1e-4;
[Header("固定步长模拟")]
[Tooltip("开启后按固定步长累积时间,一帧内可能执行多次模拟步进。")]
[SerializeField]
private bool _fixedStepEnabled = true;
[Tooltip("固定步长(秒)。")]
[SerializeField]
private float _fixedStepSeconds = 1f / 60f;
private double _fixedStepAccumulator;
private EntitySync _entitySync;
private TransformSync _transformSync;
private HitPresentation _hitPresentation;
#region Lifecycle
protected override void Awake()
{
base.Awake();
_entitySync = new EntitySync(this);
_transformSync = new TransformSync(this);
_hitPresentation = new HitPresentation(this);
InitializeJobDataChannels();
}
private void Start()
{
_entitySync?.OnStart();
_hitPresentation?.OnStart();
}
public void Tick(in SimulationTickContext context)
{
if (!_fixedStepEnabled)
{
TickSimulationStep(context.PlayerPosition, context.DeltaTime);
return;
}
double fixedStep = Mathf.Max(MinFixedStepSeconds, _fixedStepSeconds);
double stepEpsilon = fixedStep * FixedStepEpsilonScale;
_fixedStepAccumulator += context.DeltaTime;
while (_fixedStepAccumulator + stepEpsilon >= fixedStep)
{
TickSimulationStep(context.PlayerPosition, (float)fixedStep);
_fixedStepAccumulator -= fixedStep;
if (_fixedStepAccumulator < 0d)
{
_fixedStepAccumulator = 0d;
}
}
}
private void TickSimulationStep(Vector3 fallbackPlayerPosition, float deltaTime)
{
Vector3 playerPosition = ResolvePlayerPositionForTick(fallbackPlayerPosition, deltaTime);
SimulationTickContext resolvedContext = new SimulationTickContext(deltaTime, playerPosition);
using (CustomProfilerMarker.TickEnemies.Auto())
{
TickSimulationPipeline(in resolvedContext);
}
}
private void OnDestroy()
{
_hitPresentation?.OnDestroy();
_entitySync?.OnDestroy();
_entitySync = null;
_transformSync = null;
_hitPresentation = null;
DisposeJobDataChannels();
}
private void LateUpdate()
{
_transformSync?.OnLateUpdate();
}
#endregion
}
}