GFramework/GFramework.Core.Tests/ecs/EcsAdvancedTests.cs
GeWuYou 43dc5a4d11 refactor(ecs): 将 ECS 系统重构为基于 Arch 的原生实现
- 将 MovementSystem 从继承 EcsSystemBase 改为继承 ArchSystemAdapter
- 更新 MovementSystem 的初始化和更新方法以适配 Arch 架构
- 移除测试代码中的 ECS 相关接口实现和抽象层
- 将测试用例从 GFramework ECS API 迁移到 Arch 原生 API
- 更新 ECS 测试类以使用 Arch World 和实体操作方法
- 重构 ECS 模块初始化流程以支持 Arch 系统注册和管理
2026-03-02 21:20:50 +08:00

216 lines
5.8 KiB
C#

using System.Diagnostics.CodeAnalysis;
using Arch.Core;
using GFramework.Core.Abstractions.rule;
using GFramework.Core.architecture;
using GFramework.Core.ecs;
using GFramework.Core.ecs.components;
using GFramework.Core.ecs.systems;
using GFramework.Core.ioc;
using NUnit.Framework;
namespace GFramework.Core.Tests.ecs;
/// <summary>
/// ECS 高级功能测试类 - 使用 Arch 原生 API
/// </summary>
[TestFixture]
[Experimental("GFrameworkECS")]
public class EcsAdvancedTests
{
[SetUp]
public void Setup()
{
_container = new MicrosoftDiContainer();
_context = new ArchitectureContext(_container);
}
[TearDown]
public void TearDown()
{
if (_world != null)
{
World.Destroy(_world);
_world = null;
}
_container?.Clear();
_context = null;
_ecsModule = null;
}
private MicrosoftDiContainer? _container;
private ArchitectureContext? _context;
private World? _world;
private ArchEcsModule? _ecsModule;
private void InitializeEcsModule()
{
var movementSystem = new MovementSystem();
((IContextAware)movementSystem).SetContext(_context!);
_container!.RegisterPlurality(movementSystem);
_ecsModule = new ArchEcsModule(enabled: true);
_ecsModule.Register(_container);
_ecsModule.Initialize();
_world = _container.Get<World>();
}
[Test]
public void World_Destroy_Should_Be_Safe()
{
InitializeEcsModule();
_world!.Create(new Position(0, 0));
Assert.DoesNotThrow(() =>
{
World.Destroy(_world);
_world = null;
});
}
[Test]
public void World_CreateEntity_WithNoComponents_Should_Work()
{
InitializeEcsModule();
var entity = _world!.Create();
Assert.That(_world.Size, Is.EqualTo(1));
Assert.That(_world.IsAlive(entity), Is.True);
}
[Test]
public void World_CreateEntity_WithMultipleComponents_Should_Work()
{
InitializeEcsModule();
var entity = _world!.Create(new Position(0, 0), new Velocity(1, 1));
Assert.That(_world.Has<Position>(entity), Is.True);
Assert.That(_world.Has<Velocity>(entity), Is.True);
}
[Test]
public void World_IsAlive_AfterDestroy_Should_ReturnFalse()
{
InitializeEcsModule();
var entity = _world!.Create(new Position(0, 0));
Assert.That(_world.IsAlive(entity), Is.True);
_world.Destroy(entity);
Assert.That(_world.IsAlive(entity), Is.False);
}
[Test]
public void ArchEcsModule_Update_Should_UpdateSystems()
{
InitializeEcsModule();
var entity = _world!.Create(new Position(0, 0), new Velocity(10, 5));
_ecsModule!.Update(1.0f);
ref var pos = ref _world.Get<Position>(entity);
Assert.That(pos.X, Is.EqualTo(10).Within(0.001f));
Assert.That(pos.Y, Is.EqualTo(5).Within(0.001f));
}
[Test]
public void ArchEcsModule_WithNoSystems_Should_NotThrow()
{
// 不注册任何系统
_ecsModule = new ArchEcsModule(enabled: true);
_ecsModule.Register(_container!);
_ecsModule.Initialize();
_world = _container!.Get<World>();
Assert.DoesNotThrow(() => { _ecsModule.Update(1.0f); });
}
[Test]
public void ChainedUpdates_Should_AccumulateChanges()
{
InitializeEcsModule();
var entity = _world!.Create(new Position(0, 0), new Velocity(10, 0));
_ecsModule!.Update(1.0f);
_ecsModule.Update(1.0f);
ref var pos = ref _world.Get<Position>(entity);
Assert.That(pos.X, Is.EqualTo(20).Within(0.001f), "Position should accumulate over multiple updates");
}
[Test]
public void Component_AddAfterCreation_Should_Work()
{
InitializeEcsModule();
var entity = _world!.Create();
_world.Add(entity, new Position(5, 10));
Assert.That(_world.Has<Position>(entity), Is.True);
ref var pos = ref _world.Get<Position>(entity);
Assert.That(pos.X, Is.EqualTo(5));
Assert.That(pos.Y, Is.EqualTo(10));
}
[Test]
public void Component_Remove_Should_Work()
{
InitializeEcsModule();
var entity = _world!.Create(new Position(0, 0), new Velocity(1, 1));
_world.Remove<Velocity>(entity);
Assert.That(_world.Has<Position>(entity), Is.True);
Assert.That(_world.Has<Velocity>(entity), Is.False);
}
[Test]
public void Component_Replace_Should_Work()
{
InitializeEcsModule();
var entity = _world!.Create(new Position(1, 1));
_world.Set(entity, new Position(100, 200));
ref var pos = ref _world.Get<Position>(entity);
Assert.That(pos.X, Is.EqualTo(100));
Assert.That(pos.Y, Is.EqualTo(200));
}
[Test]
public async Task ArchEcsModule_DestroyAsync_Should_CleanupResources()
{
InitializeEcsModule();
_world!.Create(new Position(0, 0));
Assert.That(_world.Size, Is.EqualTo(1));
await _ecsModule!.DestroyAsync();
// World 应该已经被销毁
_world = null;
}
[Test]
public void MultipleEntities_WithDifferentComponents_Should_CoExist()
{
InitializeEcsModule();
var entity1 = _world!.Create(new Position(0, 0), new Velocity(1, 1));
var entity2 = _world.Create(new Position(10, 10));
var entity3 = _world.Create(new Velocity(5, 5));
Assert.That(_world.Size, Is.EqualTo(3));
Assert.That(_world.Has<Position>(entity1), Is.True);
Assert.That(_world.Has<Velocity>(entity1), Is.True);
Assert.That(_world.Has<Position>(entity2), Is.True);
Assert.That(_world.Has<Velocity>(entity2), Is.False);
Assert.That(_world.Has<Position>(entity3), Is.False);
Assert.That(_world.Has<Velocity>(entity3), Is.True);
}
}