refactor(ecs): 将ECS系统重构为Arch适配器模式

- 移除原有的ECS基础实现和接口定义
- 添加ArchEcsModule作为新的ECS模块实现
- 创建ArchSystemAdapter基类用于桥接Arch系统
- 修改MovementSystem继承ArchSystemAdapter适配新架构
- 更新ServiceModuleManager使用新的ArchECS模块
- 移除ArchitectureContext中的ECS相关方法
- 从项目中移除对Arch包的直接依赖引用
This commit is contained in:
GeWuYou 2026-03-01 23:26:29 +08:00 committed by gewuyou
parent 3675666e13
commit d7bd9fc569
13 changed files with 263 additions and 427 deletions

View File

@ -25,7 +25,6 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="Arch" Version="2.1.0"/>
<PackageReference Include="Mediator.Abstractions" Version="3.0.1"/>
</ItemGroup>
</Project>

View File

@ -1,5 +1,4 @@
using GFramework.Core.Abstractions.command;
using GFramework.Core.Abstractions.ecs;
using GFramework.Core.Abstractions.environment;
using GFramework.Core.Abstractions.events;
using GFramework.Core.Abstractions.model;
@ -206,18 +205,4 @@ public interface IArchitectureContext
/// </summary>
/// <returns>环境对象实例</returns>
IEnvironment GetEnvironment();
// === ECS 支持 ===
/// <summary>
/// 获取ECS世界实例
/// </summary>
/// <returns>ECS世界实例</returns>
IEcsWorld GetEcsWorld();
/// <summary>
/// 注册ECS系统
/// </summary>
/// <typeparam name="T">ECS系统类型</typeparam>
void RegisterEcsSystem<T>() where T : class, IEcsSystem;
}

View File

@ -1,20 +0,0 @@
using GFramework.Core.Abstractions.system;
namespace GFramework.Core.Abstractions.ecs;
/// <summary>
/// ECS系统接口继承自ISystem以集成到现有架构
/// </summary>
public interface IEcsSystem : ISystem
{
/// <summary>
/// 系统优先级,数值越小越先执行
/// </summary>
int Priority { get; }
/// <summary>
/// 每帧更新
/// </summary>
/// <param name="deltaTime">帧间隔时间(秒)</param>
void Update(float deltaTime);
}

View File

@ -1,44 +0,0 @@
using Arch.Core;
namespace GFramework.Core.Abstractions.ecs;
/// <summary>
/// ECS世界接口封装Arch的World实例
/// </summary>
public interface IEcsWorld : IDisposable
{
/// <summary>
/// 当前实体数量
/// </summary>
int EntityCount { get; }
/// <summary>
/// 获取内部的Arch World实例用于高级操作
/// </summary>
World InternalWorld { get; }
/// <summary>
/// 创建一个新实体
/// </summary>
/// <param name="types">组件类型数组</param>
/// <returns>创建的实体</returns>
Entity CreateEntity(params ComponentType[] types);
/// <summary>
/// 销毁指定实体
/// </summary>
/// <param name="entity">要销毁的实体</param>
void DestroyEntity(Entity entity);
/// <summary>
/// 检查实体是否存活
/// </summary>
/// <param name="entity">要检查的实体</param>
/// <returns>实体是否存活</returns>
bool IsAlive(Entity entity);
/// <summary>
/// 清空所有实体
/// </summary>
void Clear();
}

View File

@ -1,6 +1,5 @@
using GFramework.Core.Abstractions.architecture;
using GFramework.Core.Abstractions.command;
using GFramework.Core.Abstractions.ecs;
using GFramework.Core.Abstractions.environment;
using GFramework.Core.Abstractions.events;
using GFramework.Core.Abstractions.ioc;
@ -413,29 +412,4 @@ public class ArchitectureContext(IIocContainer container) : IArchitectureContext
}
#endregion
#region ECS Support
/// <summary>
/// 获取ECS世界实例
/// </summary>
/// <returns>ECS世界实例</returns>
public IEcsWorld GetEcsWorld()
{
var ecsWorld = GetOrCache<IEcsWorld>();
return ecsWorld ??
throw new InvalidOperationException("ECS World not initialized. Enable ECS in configuration.");
}
/// <summary>
/// 注册ECS系统
/// </summary>
/// <typeparam name="T">ECS系统类型</typeparam>
public void RegisterEcsSystem<T>() where T : class, IEcsSystem
{
// 使用RegisterPlurality注册到所有接口
_container.RegisterPlurality<T>();
}
#endregion
}

View File

@ -0,0 +1,114 @@
using Arch.Core;
using GFramework.Core.Abstractions.architecture;
using GFramework.Core.Abstractions.ioc;
namespace GFramework.Core.ecs;
/// <summary>
/// Arch ECS 模块 - 核心适配器,桥接 Arch 到框架生命周期
/// </summary>
public sealed class ArchEcsModule : IServiceModule
{
private readonly List<ArchSystemAdapter<float>> _systems = [];
private IIocContainer? _container;
private World? _world;
/// <summary>
/// 构造函数
/// </summary>
/// <param name="enabled">是否启用模块</param>
public ArchEcsModule(bool enabled = true)
{
IsEnabled = enabled;
}
/// <summary>
/// 模块名称
/// </summary>
public string ModuleName => nameof(ArchEcsModule);
/// <summary>
/// 模块优先级
/// </summary>
public int Priority => 50;
/// <summary>
/// 是否启用
/// </summary>
public bool IsEnabled { get; }
/// <summary>
/// 注册服务 - 创建并注册 World
/// </summary>
public void Register(IIocContainer container)
{
if (!IsEnabled) return;
_container = container;
// 创建并注册 World
_world = World.Create();
container.Register(_world);
}
/// <summary>
/// 初始化 - 从容器获取所有适配器并初始化
/// </summary>
public void Initialize()
{
if (!IsEnabled || _world == null || _container == null) return;
// 从容器获取所有适配器
var adapters = _container.GetAll<ArchSystemAdapter<float>>();
if (adapters.Count > 0)
{
_systems.AddRange(adapters);
// 初始化所有系统(会调用 Arch 系统的 Initialize
foreach (var system in _systems)
{
system.Initialize();
}
}
}
/// <summary>
/// 异步销毁
/// </summary>
public async ValueTask DestroyAsync()
{
if (!IsEnabled) return;
// 销毁所有系统
foreach (var system in _systems)
{
system.Destroy();
}
_systems.Clear();
// 销毁 World
if (_world != null)
{
World.Destroy(_world);
_world = null;
}
await ValueTask.CompletedTask;
}
/// <summary>
/// 更新所有 ECS 系统
/// </summary>
/// <param name="deltaTime">帧间隔时间</param>
public void Update(float deltaTime)
{
if (!IsEnabled) return;
// 调用所有系统的更新
foreach (var system in _systems)
{
system.Update(deltaTime);
}
}
}

View File

@ -0,0 +1,136 @@
using Arch.Core;
using GFramework.Core.extensions;
using GFramework.Core.system;
using ArchSys = Arch.System;
namespace GFramework.Core.ecs;
/// <summary>
/// Arch 系统适配器 - 桥接 Arch.System.ISystem&lt;T&gt; 到框架上下文
/// </summary>
/// <typeparam name="T">系统数据类型(通常是 float 表示 deltaTime</typeparam>
public abstract class ArchSystemAdapter<T> : AbstractSystem, ArchSys.ISystem<T>
{
/// <summary>
/// 获取或设置 Arch ECS 世界的实例
/// </summary>
public World World { get; private set; } = null!;
// ===== Arch 显式接口实现 =====
/// <summary>
/// 显式实现 Arch.System.ISystem&lt;T&gt; 的初始化方法
/// 调用受保护的虚方法 OnArchInitialize 以允许子类自定义初始化逻辑
/// </summary>
void ArchSys.ISystem<T>.Initialize()
{
OnArchInitialize();
}
/// <summary>
/// 显式实现 Arch.System.ISystem&lt;T&gt; 的更新前回调方法
/// 调用受保护的虚方法 OnBeforeUpdate 以允许子类自定义预处理逻辑
/// </summary>
/// <param name="t">系统数据参数(通常是 deltaTime</param>
void ArchSys.ISystem<T>.BeforeUpdate(in T t)
{
OnBeforeUpdate(in t);
}
/// <summary>
/// 显式实现 Arch.System.ISystem&lt;T&gt; 的主更新方法
/// 调用受保护的抽象方法 OnUpdate 以强制子类实现核心更新逻辑
/// </summary>
/// <param name="t">系统数据参数(通常是 deltaTime</param>
public void Update(in T t)
{
OnUpdate(in t);
}
/// <summary>
/// 显式实现 Arch.System.ISystem&lt;T&gt; 的更新后回调方法
/// 调用受保护的虚方法 OnAfterUpdate 以允许子类自定义后处理逻辑
/// </summary>
/// <param name="t">系统数据参数(通常是 deltaTime</param>
void ArchSys.ISystem<T>.AfterUpdate(in T t)
{
OnAfterUpdate(in t);
}
/// <summary>
/// 显式实现 IDisposable 的资源释放方法
/// 调用受保护的虚方法 OnArchDispose 以允许子类自定义资源清理逻辑
/// </summary>
void IDisposable.Dispose()
{
OnArchDispose();
}
// ===== GFramework 生命周期 =====
/// <summary>
/// 系统初始化方法
/// 在此方法中获取 Arch World 实例并调用 Arch 系统的初始化逻辑
/// </summary>
protected override void OnInit()
{
World = this.GetService<World>()!;
// 调用 Arch 初始化
((ArchSys.ISystem<T>)this).Initialize();
}
/// <summary>
/// 系统销毁方法
/// 在此方法中调用 Arch 系统的资源释放逻辑
/// </summary>
protected override void OnDestroy()
{
((ArchSys.ISystem<T>)this).Dispose();
}
// ===== 子类可重写 Hook =====
/// <summary>
/// Arch 系统初始化的受保护虚方法
/// 子类可重写此方法以实现自定义的 Arch 系统初始化逻辑
/// </summary>
protected virtual void OnArchInitialize()
{
}
/// <summary>
/// 更新前处理的受保护虚方法
/// 子类可重写此方法以实现自定义的预处理逻辑
/// </summary>
/// <param name="t">系统数据参数(通常是 deltaTime</param>
protected virtual void OnBeforeUpdate(in T t)
{
}
/// <summary>
/// 核心更新逻辑的受保护抽象方法
/// 子类必须重写此方法以实现具体的系统更新功能
/// </summary>
/// <param name="t">系统数据参数(通常是 deltaTime</param>
protected virtual void OnUpdate(in T t)
{
}
/// <summary>
/// 更新后处理的受保护虚方法
/// 子类可重写此方法以实现自定义的后处理逻辑
/// </summary>
/// <param name="t">系统数据参数(通常是 deltaTime</param>
protected virtual void OnAfterUpdate(in T t)
{
}
/// <summary>
/// Arch 系统资源释放的受保护虚方法
/// 子类可重写此方法以实现自定义的资源清理逻辑
/// </summary>
protected virtual void OnArchDispose()
{
}
}

View File

@ -1,63 +0,0 @@
using Arch.Core;
using GFramework.Core.Abstractions.ecs;
using GFramework.Core.extensions;
using GFramework.Core.system;
namespace GFramework.Core.ecs;
/// <summary>
/// ECS系统基类继承自AbstractSystem以集成到现有架构
/// </summary>
public abstract class EcsSystemBase : AbstractSystem, IEcsSystem
{
/// <summary>
/// ECS世界实例
/// </summary>
protected IEcsWorld EcsWorld { get; private set; } = null!;
/// <summary>
/// 快捷访问内部World
/// </summary>
protected World World => EcsWorld.InternalWorld;
/// <summary>
/// 系统优先级默认为0
/// </summary>
public virtual int Priority => 0;
/// <summary>
/// 每帧更新(子类实现)
/// </summary>
public abstract void Update(float deltaTime);
/// <summary>
/// 系统初始化
/// </summary>
protected override void OnInit()
{
EcsWorld = this.GetService<IEcsWorld>() ?? throw new InvalidOperationException(
"EcsWorld not found in context. Make sure ECS is properly initialized.");
OnEcsInit();
}
/// <summary>
/// 系统销毁
/// </summary>
protected override void OnDestroy()
{
OnEcsDestroy();
}
/// <summary>
/// ECS系统初始化子类实现
/// </summary>
protected abstract void OnEcsInit();
/// <summary>
/// ECS系统销毁子类可选实现
/// </summary>
protected virtual void OnEcsDestroy()
{
}
}

View File

@ -1,67 +0,0 @@
using GFramework.Core.Abstractions.ecs;
using GFramework.Core.extensions;
using GFramework.Core.system;
namespace GFramework.Core.ecs;
/// <summary>
/// ECS系统调度器负责管理和更新所有ECS系统
/// </summary>
public sealed class EcsSystemRunner : AbstractSystem
{
private readonly List<IEcsSystem> _systems = new();
private bool _isRunning;
/// <summary>
/// 初始化调度器从DI容器获取所有ECS系统
/// </summary>
protected override void OnInit()
{
// 从容器获取所有已注册的ECS系统
var systemsList = this.GetService<IReadOnlyList<IEcsSystem>>();
if (systemsList is { Count: > 0 })
{
// 按优先级排序
_systems.AddRange(systemsList.OrderBy(s => s.Priority));
}
}
/// <summary>
/// 更新所有ECS系统
/// </summary>
/// <param name="deltaTime">帧间隔时间</param>
public void Update(float deltaTime)
{
if (!_isRunning) return;
foreach (var system in _systems)
{
system.Update(deltaTime);
}
}
/// <summary>
/// 启动调度器
/// </summary>
public void Start()
{
_isRunning = true;
}
/// <summary>
/// 停止调度器
/// </summary>
public void Stop()
{
_isRunning = false;
}
/// <summary>
/// 销毁调度器
/// </summary>
protected override void OnDestroy()
{
Stop();
_systems.Clear();
}
}

View File

@ -1,65 +0,0 @@
using Arch.Core;
using GFramework.Core.Abstractions.ecs;
namespace GFramework.Core.ecs;
/// <summary>
/// ECS世界实现封装Arch的World实例
/// </summary>
public sealed class EcsWorld : IEcsWorld
{
private bool _disposed;
/// <summary>
/// 获取内部的Arch World实例
/// </summary>
public World InternalWorld { get; } = World.Create();
/// <summary>
/// 当前实体数量
/// </summary>
public int EntityCount => InternalWorld.Size;
/// <summary>
/// 创建一个新实体
/// </summary>
public Entity CreateEntity(params ComponentType[] types)
{
return InternalWorld.Create(types);
}
/// <summary>
/// 销毁指定实体
/// </summary>
public void DestroyEntity(Entity entity)
{
InternalWorld.Destroy(entity);
}
/// <summary>
/// 检查实体是否存活
/// </summary>
public bool IsAlive(Entity entity)
{
return InternalWorld.IsAlive(entity);
}
/// <summary>
/// 清空所有实体
/// </summary>
public void Clear()
{
InternalWorld.Clear();
}
/// <summary>
/// 释放资源
/// </summary>
public void Dispose()
{
if (_disposed) return;
World.Destroy(InternalWorld);
_disposed = true;
}
}

View File

@ -4,37 +4,33 @@ using GFramework.Core.ecs.components;
namespace GFramework.Core.ecs.systems;
/// <summary>
/// 移动系统,负责更新具有位置和速度组件的实体的位置。
/// 根据速度和时间增量计算实体的新位置。
/// 移动系统 - Arch 原生实现
/// 负责更新具有位置和速度组件的实体的位置
/// </summary>
public class MovementSystem : EcsSystemBase
public sealed class MovementSystem : ArchSystemAdapter<float>
{
private QueryDescription _query;
/// <summary>
/// 获取系统的优先级,数值越小优先级越高。
/// 初始化系统
/// </summary>
public override int Priority => 0;
/// <summary>
/// ECS初始化回调方法在系统初始化时调用。
/// 创建查询描述符用于查找同时拥有Position和Velocity组件的实体。
/// </summary>
protected override void OnEcsInit()
public void Initialize(World world)
{
// 创建查询查找所有同时拥有Position和Velocity组件的实体
_query = new QueryDescription()
.WithAll<Position, Velocity>();
}
/// <summary>
/// 系统更新方法,每帧调用一次
/// 系统更新方法,每帧调用一次
/// </summary>
/// <param name="deltaTime">帧间隔时间,用于计算位置变化量</param>
public override void Update(float deltaTime)
/// <param name="world">ECS 世界</param>
/// <param name="deltaTime">帧间隔时间</param>
public void Update(World world, float deltaTime)
{
// 查询并更新所有符合条件的实体
World.Query(in _query, (ref Position pos, ref Velocity vel) =>
world.Query(in _query, (ref Position pos, ref Velocity vel) =>
{
pos.X += vel.X * deltaTime;
pos.Y += vel.Y * deltaTime;

View File

@ -3,6 +3,7 @@ using GFramework.Core.Abstractions.ioc;
using GFramework.Core.Abstractions.lifecycle;
using GFramework.Core.Abstractions.logging;
using GFramework.Core.Abstractions.properties;
using GFramework.Core.ecs;
using GFramework.Core.logging;
using GFramework.Core.services.modules;
@ -63,7 +64,7 @@ public sealed class ServiceModuleManager : IServiceModuleManager
if (properties.EnableEcs)
{
RegisterModule(new EcsServiceModule(enabled: true));
RegisterModule(new ArchEcsModule(enabled: true));
_logger.Info("ECS module enabled via configuration");
}

View File

@ -1,110 +0,0 @@
using GFramework.Core.Abstractions.architecture;
using GFramework.Core.Abstractions.ecs;
using GFramework.Core.Abstractions.ioc;
using GFramework.Core.Abstractions.lifecycle;
using GFramework.Core.ecs;
namespace GFramework.Core.services.modules;
/// <summary>
/// ECSEntity Component System模块用于注册、初始化和管理ECS相关服务。
/// 该模块负责创建ECS世界和系统运行器并将其注册到依赖注入容器中。
/// </summary>
public sealed class EcsServiceModule : IServiceModule
{
private EcsSystemRunner? _ecsRunner;
private EcsWorld? _ecsWorld;
/// <summary>
/// 构造函数初始化ECS模块。
/// </summary>
/// <param name="enabled">指定模块是否启用,默认为 true。</param>
public EcsServiceModule(bool enabled = true)
{
IsEnabled = enabled;
}
/// <summary>
/// 获取模块名称。
/// </summary>
public string ModuleName => nameof(EcsServiceModule);
/// <summary>
/// 获取模块优先级,数值越小优先级越高。
/// </summary>
public int Priority => 100;
/// <summary>
/// 获取模块启用状态。
/// </summary>
public bool IsEnabled { get; }
/// <summary>
/// 注册ECS相关服务到依赖注入容器中。
/// 包括ECS世界实例和系统运行器实例的注册。
/// </summary>
/// <param name="container">依赖注入容器实例。</param>
public void Register(IIocContainer container)
{
if (!IsEnabled) return;
_ecsWorld = new EcsWorld();
container.Register(_ecsWorld);
container.Register<IEcsWorld>(_ecsWorld);
container.RegisterPlurality<EcsSystemRunner>();
_ecsRunner = container.Get<EcsSystemRunner>();
}
/// <summary>
/// 初始化ECS模块。
/// 如果系统运行器实现了IInitializable接口则调用其初始化方法。
/// </summary>
public void Initialize()
{
if (!IsEnabled || _ecsRunner == null) return;
if (_ecsRunner is IInitializable initializable)
{
initializable.Initialize();
}
}
/// <summary>
/// 异步销毁ECS模块并释放相关资源。
/// 包括销毁系统运行器和释放ECS世界资源。
/// </summary>
/// <returns>表示异步操作完成的任务。</returns>
public async ValueTask DestroyAsync()
{
if (!IsEnabled) return;
if (_ecsRunner is IDestroyable destroyable)
{
destroyable.Destroy();
}
_ecsRunner = null;
if (_ecsWorld != null)
{
_ecsWorld.Dispose();
_ecsWorld = null;
}
await ValueTask.CompletedTask;
}
/// <summary>
/// 获取ECS世界实例。
/// </summary>
/// <returns>ECS世界实例如果未启用则返回 null。</returns>
public IEcsWorld? GetEcsWorld() => _ecsWorld;
/// <summary>
/// 获取ECS系统运行器实例内部使用
/// </summary>
/// <returns>ECS系统运行器实例如果未启用则返回 null。</returns>
internal EcsSystemRunner? GetEcsRunner() => _ecsRunner;
}