Added SystemBase

This commit is contained in:
2025-12-16 15:05:42 +09:00
parent 7613b5087e
commit 756727dc06
8 changed files with 203 additions and 47 deletions

View File

@@ -55,7 +55,20 @@ public readonly struct Result<T>
private readonly string? _message; private readonly string? _message;
private readonly bool _isSuccess; private readonly bool _isSuccess;
public readonly T Value => _value; public T Value
{
get
{
#if DEBUG || GHOST_EDITOR
if (!_isSuccess)
{
throw new InvalidOperationException($"Cannot access Value when Result is a failure. {_message}");
}
#endif
return _value;
}
}
public readonly string? Message => _message; public readonly string? Message => _message;
public readonly bool IsSuccess => _isSuccess; public readonly bool IsSuccess => _isSuccess;
public readonly bool IsFailure => !_isSuccess; public readonly bool IsFailure => !_isSuccess;
@@ -113,7 +126,20 @@ public readonly struct Result<T, E>
private readonly E _error; private readonly E _error;
private readonly bool _isSuccess; private readonly bool _isSuccess;
public T Value => _value; public T Value
{
get
{
#if DEBUG || GHOST_EDITOR
if (!_isSuccess)
{
throw new InvalidOperationException($"Cannot access Value when Result is a failure. Error: {_error}");
}
#endif
return _value;
}
}
public E Error => _error; public E Error => _error;
public bool IsSuccess => _isSuccess; public bool IsSuccess => _isSuccess;
public bool IsFailure => !_isSuccess; public bool IsFailure => !_isSuccess;
@@ -156,7 +182,20 @@ public readonly ref struct RefResult<T, E>
private readonly E _error; private readonly E _error;
private readonly bool _isSuccess; private readonly bool _isSuccess;
public ref T Value => ref _value; public ref T Value
{
get
{
#if DEBUG || GHOST_EDITOR
if (!_isSuccess)
{
throw new InvalidOperationException($"Cannot access Value when Result is a failure. Error: {_error}");
}
#endif
return ref _value;
}
}
public E Error => _error; public E Error => _error;
public bool IsSuccess => _isSuccess; public bool IsSuccess => _isSuccess;
public bool IsFailure => !_isSuccess; public bool IsFailure => !_isSuccess;

View File

@@ -34,35 +34,19 @@ internal class SystemTest : ITest
} }
} }
internal class TestSystemA : ISystem internal class TestSystemA : SystemBase
{ {
public void Initialize(ref readonly SystemAPI systemAPI) protected override void OnInitialize(ref readonly SystemAPI systemAPI)
{ {
Console.WriteLine("TestSystemA Initialized"); Console.WriteLine("TestSystemA Initialized");
} }
public void Update(ref readonly SystemAPI systemAPI)
{
}
public void Cleanup(ref readonly SystemAPI systemAPI)
{
}
} }
[UpdateAfter(typeof(TestSystemA))] [UpdateAfter(typeof(TestSystemA))]
internal class TestSystemB : ISystem internal class TestSystemB : SystemBase
{ {
public void Initialize(ref readonly SystemAPI systemAPI) protected override void OnInitialize(ref readonly SystemAPI systemAPI)
{ {
Console.WriteLine("TestSystemB Initialized"); Console.WriteLine("TestSystemB Initialized");
} }
public void Update(ref readonly SystemAPI systemAPI)
{
}
public void Cleanup(ref readonly SystemAPI systemAPI)
{
}
} }

View File

@@ -153,7 +153,7 @@ internal unsafe struct Chunk : IDisposable
} }
} }
internal unsafe struct Archetype : IIdentifierType, IDisposable internal unsafe struct Archetype : IDisposable
{ {
internal struct ComponentMemoryLayout internal struct ComponentMemoryLayout
{ {

View File

@@ -1,6 +1,6 @@
namespace Ghost.Entities; namespace Ghost.Entities;
public readonly struct Time public readonly struct TimeData
{ {
public int FrameCount public int FrameCount
{ {

View File

@@ -5,7 +5,7 @@ using System.Runtime.CompilerServices;
namespace Ghost.Entities; namespace Ghost.Entities;
public interface IComponent : IIdentifierType public interface IComponent
{ {
} }

View File

@@ -261,7 +261,7 @@ public readonly unsafe ref struct ChunkView
} }
} }
public unsafe partial struct EntityQuery : IIdentifierType, IDisposable public unsafe partial struct EntityQuery : IDisposable
{ {
/// <summary> /// <summary>
/// Provides an enumerator for iterating over chunks of entities and their component data that match a set of archetypes within a world. /// Provides an enumerator for iterating over chunks of entities and their component data that match a set of archetypes within a world.
@@ -438,6 +438,31 @@ public unsafe partial struct EntityQuery : IIdentifierType, IDisposable
return new ChunkIterator(_matchingArchetypes.AsReadOnly(), world); return new ChunkIterator(_matchingArchetypes.AsReadOnly(), world);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public readonly int GetEntityCount()
{
var total = 0;
var r = World.GetWorld(_worldID);
if (r.IsFailure)
{
return 0;
}
var world = r.Value;
for(var i = 0; i < _matchingArchetypes.Count; i++)
{
var archetypeID = _matchingArchetypes[i];
ref var archetype = ref world.GetArchetypeReference(archetypeID);
for (var j = 0; j < archetype.ChunkCount; j++)
{
ref var chunk = ref archetype.GetChunkReference(j);
total += chunk._count;
}
}
return total;
}
public void Dispose() public void Dispose()
{ {
_mask.Dispose(); _mask.Dispose();

View File

@@ -1,13 +1,10 @@
using Ghost.Core;
namespace Ghost.Entities; namespace Ghost.Entities;
public readonly ref struct SystemAPI public readonly ref struct SystemAPI
{ {
public World World public TimeData Time
{
get; init;
}
public Time Time
{ {
get; init; get; init;
} }
@@ -15,11 +12,107 @@ public readonly ref struct SystemAPI
public interface ISystem public interface ISystem
{ {
World World
{
get; init;
}
void Initialize(ref readonly SystemAPI systemAPI); void Initialize(ref readonly SystemAPI systemAPI);
void Update(ref readonly SystemAPI systemAPI); void Update(ref readonly SystemAPI systemAPI);
void Cleanup(ref readonly SystemAPI systemAPI); void Cleanup(ref readonly SystemAPI systemAPI);
} }
public abstract class SystemBase : ISystem
{
private List<int>? _requiredQueries;
public World World
{
get; init;
} = null!;
public int LastSystemVersion
{
get; internal set;
} = -2;
private bool ShouldUpdate()
{
if (_requiredQueries == null || _requiredQueries.Count == 0)
{
return true;
}
foreach (var queryID in _requiredQueries)
{
ref var query = ref World.GetEntityQueryReference(new Identifier<EntityQuery>(queryID));
if (query.GetEntityCount() == 0)
{
return false;
}
}
return true;
}
protected void RequireQueryForUpdate(Identifier<EntityQuery> queryID)
{
_requiredQueries ??= new List<int>(4);
_requiredQueries.Add(queryID.value);
}
public void Initialize(ref readonly SystemAPI systemAPI)
{
OnInitialize(in systemAPI);
}
public void Update(ref readonly SystemAPI systemAPI)
{
if (ShouldUpdate())
{
if (World.Version - LastSystemVersion > 1)
{
OnStartRunning();
}
OnUpdate(in systemAPI);
LastSystemVersion = World.Version;
}
else
{
if (World.Version - LastSystemVersion <= 1)
{
OnStopRunning();
}
}
}
public void Cleanup(ref readonly SystemAPI systemAPI)
{
OnCleanup(in systemAPI);
}
protected virtual void OnInitialize(ref readonly SystemAPI systemAPI)
{
}
protected virtual void OnUpdate(ref readonly SystemAPI systemAPI)
{
}
protected virtual void OnCleanup(ref readonly SystemAPI systemAPI)
{
}
protected virtual void OnStopRunning()
{
}
protected virtual void OnStartRunning()
{
}
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = true)] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = true)]
public class UpdateAfterAttribute : Attribute public class UpdateAfterAttribute : Attribute
{ {
@@ -85,12 +178,17 @@ internal static partial class SystemGroupRegistry
public abstract class SystemGroup : ISystem public abstract class SystemGroup : ISystem
{ {
private readonly List<ISystem> _systems = new (); private readonly List<ISystem> _systems = [];
private List<ISystem>? _sortedSystems; private List<ISystem>? _sortedSystems;
private uint _version = 0; private uint _version = 0;
private uint _sortedVersion = 0; private uint _sortedVersion = 0;
public World World
{
get; init;
} = null!;
// public SystemGroup() // public SystemGroup()
// { // {
// _systems = SystemGroupRegistry.GetSystemsForGroup(GetType()); // _systems = SystemGroupRegistry.GetSystemsForGroup(GetType());
@@ -106,13 +204,17 @@ public abstract class SystemGroup : ISystem
foreach (var sys in systems) foreach (var sys in systems)
{ {
var type = sys.GetType(); var type = sys.GetType();
if (!dependencies.ContainsKey(type)) dependencies[type] = new HashSet<Type>(); if (!dependencies.TryGetValue(type, out HashSet<Type>? value))
{
value = [];
dependencies[type] = value;
}
// Handle [UpdateAfter(typeof(Other))] -> Other comes before This // Handle [UpdateAfter(typeof(Other))] -> Other comes before This
foreach (var attr in type.GetCustomAttributes(typeof(UpdateAfterAttribute), true)) foreach (var attr in type.GetCustomAttributes(typeof(UpdateAfterAttribute), true))
{ {
var depType = ((UpdateAfterAttribute)attr).SystemType; var depType = ((UpdateAfterAttribute)attr).SystemType;
dependencies[type].Add(depType); value.Add(depType);
} }
// Handle [UpdateBefore(typeof(Other))] -> This comes before Other // Handle [UpdateBefore(typeof(Other))] -> This comes before Other
@@ -120,7 +222,7 @@ public abstract class SystemGroup : ISystem
foreach (var attr in type.GetCustomAttributes(typeof(UpdateBeforeAttribute), true)) foreach (var attr in type.GetCustomAttributes(typeof(UpdateBeforeAttribute), true))
{ {
var targetType = ((UpdateBeforeAttribute)attr).SystemType; var targetType = ((UpdateBeforeAttribute)attr).SystemType;
if (!dependencies.ContainsKey(targetType)) dependencies[targetType] = new HashSet<Type>(); if (!dependencies.ContainsKey(targetType)) dependencies[targetType] = [];
dependencies[targetType].Add(type); dependencies[targetType].Add(type);
} }
} }
@@ -175,7 +277,11 @@ public abstract class SystemGroup : ISystem
public void AddSystem<T>() public void AddSystem<T>()
where T : ISystem, new() where T : ISystem, new()
{ {
_systems.Add(new T()); _systems.Add(new T()
{
World = World
});
_version++; _version++;
} }
@@ -188,7 +294,7 @@ public abstract class SystemGroup : ISystem
if (_systems.Count == 0) if (_systems.Count == 0)
{ {
_sortedSystems = new List<ISystem>(); _sortedSystems = [];
_sortedVersion = _version; _sortedVersion = _version;
return; return;
} }
@@ -244,7 +350,7 @@ public class SystemManager
{ {
private readonly World _world; private readonly World _world;
private readonly List<ISystem> _systems = new (); private readonly List<ISystem> _systems = [];
internal SystemManager(World world) internal SystemManager(World world)
{ {
@@ -255,8 +361,10 @@ public class SystemManager
public void AddSystem<T>() public void AddSystem<T>()
where T : ISystem, new() where T : ISystem, new()
{ {
var system = new T(); _systems.Add(new T()
_systems.Add(system); {
World = _world
});
} }
public T GetSystem<T>() public T GetSystem<T>()

View File

@@ -76,7 +76,7 @@ public partial class World
} }
} }
public partial class World : IIdentifierType, IDisposable, IEquatable<World> public partial class World : IDisposable, IEquatable<World>
{ {
private readonly Identifier<World> _id; private readonly Identifier<World> _id;
private readonly JobScheduler _jobScheduler; private readonly JobScheduler _jobScheduler;
@@ -289,21 +289,21 @@ public partial class World : IIdentifierType, IDisposable, IEquatable<World>
return; return;
} }
foreach (var archetype in _archetypes) foreach (ref var archetype in _archetypes)
{ {
archetype.Dispose(); archetype.Dispose();
} }
foreach (var query in _entityQueries) foreach (ref var query in _entityQueries)
{ {
query.Dispose(); query.Dispose();
} }
_entityManager.Dispose(); _entityManager.Dispose();
_entityCommandBuffer.Dispose(); _entityCommandBuffer.Dispose();
for (var i = 0; i < _threadLocalECBs.Length; i++) foreach (var v in _threadLocalECBs)
{ {
_threadLocalECBs[i].Dispose(); v.Dispose();
} }
_archetypes.Dispose(); _archetypes.Dispose();