diff --git a/GFramework.Core.Abstractions/GFramework.Core.Abstractions.csproj b/GFramework.Core.Abstractions/GFramework.Core.Abstractions.csproj index 6a6884d..cda09d4 100644 --- a/GFramework.Core.Abstractions/GFramework.Core.Abstractions.csproj +++ b/GFramework.Core.Abstractions/GFramework.Core.Abstractions.csproj @@ -25,7 +25,6 @@ all runtime; build; native; contentfiles; analyzers - diff --git a/GFramework.Core.Abstractions/architecture/IArchitectureContext.cs b/GFramework.Core.Abstractions/architecture/IArchitectureContext.cs index 38f5a43..496d228 100644 --- a/GFramework.Core.Abstractions/architecture/IArchitectureContext.cs +++ b/GFramework.Core.Abstractions/architecture/IArchitectureContext.cs @@ -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 /// /// 环境对象实例 IEnvironment GetEnvironment(); - - // === ECS 支持 === - - /// - /// 获取ECS世界实例 - /// - /// ECS世界实例 - IEcsWorld GetEcsWorld(); - - /// - /// 注册ECS系统 - /// - /// ECS系统类型 - void RegisterEcsSystem() where T : class, IEcsSystem; } \ No newline at end of file diff --git a/GFramework.Core.Abstractions/ecs/IEcsSystem.cs b/GFramework.Core.Abstractions/ecs/IEcsSystem.cs deleted file mode 100644 index ca94bff..0000000 --- a/GFramework.Core.Abstractions/ecs/IEcsSystem.cs +++ /dev/null @@ -1,20 +0,0 @@ -using GFramework.Core.Abstractions.system; - -namespace GFramework.Core.Abstractions.ecs; - -/// -/// ECS系统接口,继承自ISystem以集成到现有架构 -/// -public interface IEcsSystem : ISystem -{ - /// - /// 系统优先级,数值越小越先执行 - /// - int Priority { get; } - - /// - /// 每帧更新 - /// - /// 帧间隔时间(秒) - void Update(float deltaTime); -} \ No newline at end of file diff --git a/GFramework.Core.Abstractions/ecs/IEcsWorld.cs b/GFramework.Core.Abstractions/ecs/IEcsWorld.cs deleted file mode 100644 index e271ed6..0000000 --- a/GFramework.Core.Abstractions/ecs/IEcsWorld.cs +++ /dev/null @@ -1,44 +0,0 @@ -using Arch.Core; - -namespace GFramework.Core.Abstractions.ecs; - -/// -/// ECS世界接口,封装Arch的World实例 -/// -public interface IEcsWorld : IDisposable -{ - /// - /// 当前实体数量 - /// - int EntityCount { get; } - - /// - /// 获取内部的Arch World实例(用于高级操作) - /// - World InternalWorld { get; } - - /// - /// 创建一个新实体 - /// - /// 组件类型数组 - /// 创建的实体 - Entity CreateEntity(params ComponentType[] types); - - /// - /// 销毁指定实体 - /// - /// 要销毁的实体 - void DestroyEntity(Entity entity); - - /// - /// 检查实体是否存活 - /// - /// 要检查的实体 - /// 实体是否存活 - bool IsAlive(Entity entity); - - /// - /// 清空所有实体 - /// - void Clear(); -} \ No newline at end of file diff --git a/GFramework.Core/architecture/ArchitectureContext.cs b/GFramework.Core/architecture/ArchitectureContext.cs index 8c81368..00c36b1 100644 --- a/GFramework.Core/architecture/ArchitectureContext.cs +++ b/GFramework.Core/architecture/ArchitectureContext.cs @@ -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 - - /// - /// 获取ECS世界实例 - /// - /// ECS世界实例 - public IEcsWorld GetEcsWorld() - { - var ecsWorld = GetOrCache(); - return ecsWorld ?? - throw new InvalidOperationException("ECS World not initialized. Enable ECS in configuration."); - } - - /// - /// 注册ECS系统 - /// - /// ECS系统类型 - public void RegisterEcsSystem() where T : class, IEcsSystem - { - // 使用RegisterPlurality注册到所有接口 - _container.RegisterPlurality(); - } - - #endregion } \ No newline at end of file diff --git a/GFramework.Core/ecs/ArchEcsModule.cs b/GFramework.Core/ecs/ArchEcsModule.cs new file mode 100644 index 0000000..549b234 --- /dev/null +++ b/GFramework.Core/ecs/ArchEcsModule.cs @@ -0,0 +1,114 @@ +using Arch.Core; +using GFramework.Core.Abstractions.architecture; +using GFramework.Core.Abstractions.ioc; + +namespace GFramework.Core.ecs; + +/// +/// Arch ECS 模块 - 核心适配器,桥接 Arch 到框架生命周期 +/// +public sealed class ArchEcsModule : IServiceModule +{ + private readonly List> _systems = []; + private IIocContainer? _container; + private World? _world; + + /// + /// 构造函数 + /// + /// 是否启用模块 + public ArchEcsModule(bool enabled = true) + { + IsEnabled = enabled; + } + + /// + /// 模块名称 + /// + public string ModuleName => nameof(ArchEcsModule); + + /// + /// 模块优先级 + /// + public int Priority => 50; + + /// + /// 是否启用 + /// + public bool IsEnabled { get; } + + /// + /// 注册服务 - 创建并注册 World + /// + public void Register(IIocContainer container) + { + if (!IsEnabled) return; + + _container = container; + + // 创建并注册 World + _world = World.Create(); + container.Register(_world); + } + + /// + /// 初始化 - 从容器获取所有适配器并初始化 + /// + public void Initialize() + { + if (!IsEnabled || _world == null || _container == null) return; + + // 从容器获取所有适配器 + var adapters = _container.GetAll>(); + if (adapters.Count > 0) + { + _systems.AddRange(adapters); + + // 初始化所有系统(会调用 Arch 系统的 Initialize) + foreach (var system in _systems) + { + system.Initialize(); + } + } + } + + /// + /// 异步销毁 + /// + 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; + } + + /// + /// 更新所有 ECS 系统 + /// + /// 帧间隔时间 + public void Update(float deltaTime) + { + if (!IsEnabled) return; + + // 调用所有系统的更新 + foreach (var system in _systems) + { + system.Update(deltaTime); + } + } +} \ No newline at end of file diff --git a/GFramework.Core/ecs/ArchSystemAdapter.cs b/GFramework.Core/ecs/ArchSystemAdapter.cs new file mode 100644 index 0000000..47b9346 --- /dev/null +++ b/GFramework.Core/ecs/ArchSystemAdapter.cs @@ -0,0 +1,136 @@ +using Arch.Core; +using GFramework.Core.extensions; +using GFramework.Core.system; +using ArchSys = Arch.System; + +namespace GFramework.Core.ecs; + +/// +/// Arch 系统适配器 - 桥接 Arch.System.ISystem<T> 到框架上下文 +/// +/// 系统数据类型(通常是 float 表示 deltaTime) +public abstract class ArchSystemAdapter : AbstractSystem, ArchSys.ISystem +{ + /// + /// 获取或设置 Arch ECS 世界的实例 + /// + public World World { get; private set; } = null!; + + // ===== Arch 显式接口实现 ===== + + /// + /// 显式实现 Arch.System.ISystem<T> 的初始化方法 + /// 调用受保护的虚方法 OnArchInitialize 以允许子类自定义初始化逻辑 + /// + void ArchSys.ISystem.Initialize() + { + OnArchInitialize(); + } + + /// + /// 显式实现 Arch.System.ISystem<T> 的更新前回调方法 + /// 调用受保护的虚方法 OnBeforeUpdate 以允许子类自定义预处理逻辑 + /// + /// 系统数据参数(通常是 deltaTime) + void ArchSys.ISystem.BeforeUpdate(in T t) + { + OnBeforeUpdate(in t); + } + + /// + /// 显式实现 Arch.System.ISystem<T> 的主更新方法 + /// 调用受保护的抽象方法 OnUpdate 以强制子类实现核心更新逻辑 + /// + /// 系统数据参数(通常是 deltaTime) + public void Update(in T t) + { + OnUpdate(in t); + } + + /// + /// 显式实现 Arch.System.ISystem<T> 的更新后回调方法 + /// 调用受保护的虚方法 OnAfterUpdate 以允许子类自定义后处理逻辑 + /// + /// 系统数据参数(通常是 deltaTime) + void ArchSys.ISystem.AfterUpdate(in T t) + { + OnAfterUpdate(in t); + } + + /// + /// 显式实现 IDisposable 的资源释放方法 + /// 调用受保护的虚方法 OnArchDispose 以允许子类自定义资源清理逻辑 + /// + void IDisposable.Dispose() + { + OnArchDispose(); + } + + // ===== GFramework 生命周期 ===== + + /// + /// 系统初始化方法 + /// 在此方法中获取 Arch World 实例并调用 Arch 系统的初始化逻辑 + /// + protected override void OnInit() + { + World = this.GetService()!; + + // 调用 Arch 初始化 + ((ArchSys.ISystem)this).Initialize(); + } + + /// + /// 系统销毁方法 + /// 在此方法中调用 Arch 系统的资源释放逻辑 + /// + protected override void OnDestroy() + { + ((ArchSys.ISystem)this).Dispose(); + } + + // ===== 子类可重写 Hook ===== + + /// + /// Arch 系统初始化的受保护虚方法 + /// 子类可重写此方法以实现自定义的 Arch 系统初始化逻辑 + /// + protected virtual void OnArchInitialize() + { + } + + /// + /// 更新前处理的受保护虚方法 + /// 子类可重写此方法以实现自定义的预处理逻辑 + /// + /// 系统数据参数(通常是 deltaTime) + protected virtual void OnBeforeUpdate(in T t) + { + } + + /// + /// 核心更新逻辑的受保护抽象方法 + /// 子类必须重写此方法以实现具体的系统更新功能 + /// + /// 系统数据参数(通常是 deltaTime) + protected virtual void OnUpdate(in T t) + { + } + + /// + /// 更新后处理的受保护虚方法 + /// 子类可重写此方法以实现自定义的后处理逻辑 + /// + /// 系统数据参数(通常是 deltaTime) + protected virtual void OnAfterUpdate(in T t) + { + } + + /// + /// Arch 系统资源释放的受保护虚方法 + /// 子类可重写此方法以实现自定义的资源清理逻辑 + /// + protected virtual void OnArchDispose() + { + } +} \ No newline at end of file diff --git a/GFramework.Core/ecs/EcsSystemBase.cs b/GFramework.Core/ecs/EcsSystemBase.cs deleted file mode 100644 index 07784bb..0000000 --- a/GFramework.Core/ecs/EcsSystemBase.cs +++ /dev/null @@ -1,63 +0,0 @@ -using Arch.Core; -using GFramework.Core.Abstractions.ecs; -using GFramework.Core.extensions; -using GFramework.Core.system; - -namespace GFramework.Core.ecs; - -/// -/// ECS系统基类,继承自AbstractSystem以集成到现有架构 -/// -public abstract class EcsSystemBase : AbstractSystem, IEcsSystem -{ - /// - /// ECS世界实例 - /// - protected IEcsWorld EcsWorld { get; private set; } = null!; - - /// - /// 快捷访问内部World - /// - protected World World => EcsWorld.InternalWorld; - - /// - /// 系统优先级,默认为0 - /// - public virtual int Priority => 0; - - /// - /// 每帧更新(子类实现) - /// - public abstract void Update(float deltaTime); - - /// - /// 系统初始化 - /// - protected override void OnInit() - { - EcsWorld = this.GetService() ?? throw new InvalidOperationException( - "EcsWorld not found in context. Make sure ECS is properly initialized."); - - OnEcsInit(); - } - - /// - /// 系统销毁 - /// - protected override void OnDestroy() - { - OnEcsDestroy(); - } - - /// - /// ECS系统初始化(子类实现) - /// - protected abstract void OnEcsInit(); - - /// - /// ECS系统销毁(子类可选实现) - /// - protected virtual void OnEcsDestroy() - { - } -} \ No newline at end of file diff --git a/GFramework.Core/ecs/EcsSystemRunner.cs b/GFramework.Core/ecs/EcsSystemRunner.cs deleted file mode 100644 index 3820a09..0000000 --- a/GFramework.Core/ecs/EcsSystemRunner.cs +++ /dev/null @@ -1,67 +0,0 @@ -using GFramework.Core.Abstractions.ecs; -using GFramework.Core.extensions; -using GFramework.Core.system; - -namespace GFramework.Core.ecs; - -/// -/// ECS系统调度器,负责管理和更新所有ECS系统 -/// -public sealed class EcsSystemRunner : AbstractSystem -{ - private readonly List _systems = new(); - private bool _isRunning; - - /// - /// 初始化调度器,从DI容器获取所有ECS系统 - /// - protected override void OnInit() - { - // 从容器获取所有已注册的ECS系统 - var systemsList = this.GetService>(); - if (systemsList is { Count: > 0 }) - { - // 按优先级排序 - _systems.AddRange(systemsList.OrderBy(s => s.Priority)); - } - } - - /// - /// 更新所有ECS系统 - /// - /// 帧间隔时间 - public void Update(float deltaTime) - { - if (!_isRunning) return; - - foreach (var system in _systems) - { - system.Update(deltaTime); - } - } - - /// - /// 启动调度器 - /// - public void Start() - { - _isRunning = true; - } - - /// - /// 停止调度器 - /// - public void Stop() - { - _isRunning = false; - } - - /// - /// 销毁调度器 - /// - protected override void OnDestroy() - { - Stop(); - _systems.Clear(); - } -} \ No newline at end of file diff --git a/GFramework.Core/ecs/EcsWorld.cs b/GFramework.Core/ecs/EcsWorld.cs deleted file mode 100644 index 92651b3..0000000 --- a/GFramework.Core/ecs/EcsWorld.cs +++ /dev/null @@ -1,65 +0,0 @@ -using Arch.Core; -using GFramework.Core.Abstractions.ecs; - -namespace GFramework.Core.ecs; - -/// -/// ECS世界实现,封装Arch的World实例 -/// -public sealed class EcsWorld : IEcsWorld -{ - private bool _disposed; - - /// - /// 获取内部的Arch World实例 - /// - public World InternalWorld { get; } = World.Create(); - - /// - /// 当前实体数量 - /// - public int EntityCount => InternalWorld.Size; - - /// - /// 创建一个新实体 - /// - public Entity CreateEntity(params ComponentType[] types) - { - return InternalWorld.Create(types); - } - - /// - /// 销毁指定实体 - /// - public void DestroyEntity(Entity entity) - { - InternalWorld.Destroy(entity); - } - - /// - /// 检查实体是否存活 - /// - public bool IsAlive(Entity entity) - { - return InternalWorld.IsAlive(entity); - } - - /// - /// 清空所有实体 - /// - public void Clear() - { - InternalWorld.Clear(); - } - - /// - /// 释放资源 - /// - public void Dispose() - { - if (_disposed) return; - - World.Destroy(InternalWorld); - _disposed = true; - } -} \ No newline at end of file diff --git a/GFramework.Core/ecs/systems/MovementSystem.cs b/GFramework.Core/ecs/systems/MovementSystem.cs index c0fe4cc..3c33b44 100644 --- a/GFramework.Core/ecs/systems/MovementSystem.cs +++ b/GFramework.Core/ecs/systems/MovementSystem.cs @@ -4,37 +4,33 @@ using GFramework.Core.ecs.components; namespace GFramework.Core.ecs.systems; /// -/// 移动系统,负责更新具有位置和速度组件的实体的位置。 -/// 根据速度和时间增量计算实体的新位置。 +/// 移动系统 - Arch 原生实现 +/// 负责更新具有位置和速度组件的实体的位置 /// -public class MovementSystem : EcsSystemBase +public sealed class MovementSystem : ArchSystemAdapter { private QueryDescription _query; /// - /// 获取系统的优先级,数值越小优先级越高。 + /// 初始化系统 /// - public override int Priority => 0; - - /// - /// ECS初始化回调方法,在系统初始化时调用。 - /// 创建查询描述符,用于查找同时拥有Position和Velocity组件的实体。 - /// - protected override void OnEcsInit() + public void Initialize(World world) { // 创建查询:查找所有同时拥有Position和Velocity组件的实体 _query = new QueryDescription() .WithAll(); } + /// - /// 系统更新方法,每帧调用一次。 + /// 系统更新方法,每帧调用一次 /// - /// 帧间隔时间,用于计算位置变化量 - public override void Update(float deltaTime) + /// ECS 世界 + /// 帧间隔时间 + 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; diff --git a/GFramework.Core/services/ServiceModuleManager.cs b/GFramework.Core/services/ServiceModuleManager.cs index 8620533..0f16073 100644 --- a/GFramework.Core/services/ServiceModuleManager.cs +++ b/GFramework.Core/services/ServiceModuleManager.cs @@ -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"); } diff --git a/GFramework.Core/services/modules/EcsServiceModule.cs b/GFramework.Core/services/modules/EcsServiceModule.cs deleted file mode 100644 index 41c2fdb..0000000 --- a/GFramework.Core/services/modules/EcsServiceModule.cs +++ /dev/null @@ -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; - -/// -/// ECS(Entity Component System)模块,用于注册、初始化和管理ECS相关服务。 -/// 该模块负责创建ECS世界和系统运行器,并将其注册到依赖注入容器中。 -/// -public sealed class EcsServiceModule : IServiceModule -{ - private EcsSystemRunner? _ecsRunner; - - private EcsWorld? _ecsWorld; - - /// - /// 构造函数,初始化ECS模块。 - /// - /// 指定模块是否启用,默认为 true。 - public EcsServiceModule(bool enabled = true) - { - IsEnabled = enabled; - } - - /// - /// 获取模块名称。 - /// - public string ModuleName => nameof(EcsServiceModule); - - /// - /// 获取模块优先级,数值越小优先级越高。 - /// - public int Priority => 100; - - /// - /// 获取模块启用状态。 - /// - public bool IsEnabled { get; } - - /// - /// 注册ECS相关服务到依赖注入容器中。 - /// 包括ECS世界实例和系统运行器实例的注册。 - /// - /// 依赖注入容器实例。 - public void Register(IIocContainer container) - { - if (!IsEnabled) return; - - _ecsWorld = new EcsWorld(); - container.Register(_ecsWorld); - container.Register(_ecsWorld); - - container.RegisterPlurality(); - _ecsRunner = container.Get(); - } - - /// - /// 初始化ECS模块。 - /// 如果系统运行器实现了IInitializable接口,则调用其初始化方法。 - /// - public void Initialize() - { - if (!IsEnabled || _ecsRunner == null) return; - - if (_ecsRunner is IInitializable initializable) - { - initializable.Initialize(); - } - } - - /// - /// 异步销毁ECS模块并释放相关资源。 - /// 包括销毁系统运行器和释放ECS世界资源。 - /// - /// 表示异步操作完成的任务。 - 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; - } - - /// - /// 获取ECS世界实例。 - /// - /// ECS世界实例,如果未启用则返回 null。 - public IEcsWorld? GetEcsWorld() => _ecsWorld; - - /// - /// 获取ECS系统运行器实例(内部使用)。 - /// - /// ECS系统运行器实例,如果未启用则返回 null。 - internal EcsSystemRunner? GetEcsRunner() => _ecsRunner; -} \ No newline at end of file