Files
riversong-code-showcase/Source/Engine/Core/GameSystemGroup.cs
2026-05-21 16:04:49 +02:00

84 lines
2.7 KiB
C#

using System;
using System.Collections.Generic;
using Cysharp.Threading.Tasks;
using UnityEngine;
using Debug = UnityEngine.Debug;
namespace DanieleMarotta.RiversongCodeShowcase
{
public abstract class GameSystemGroup : IGameSystem, IInitializable, IUpdatable, IDisposable
{
private List<IInitializable> _initializables = new();
private List<IUpdatable> _updatables = new();
private List<IDisposable> _disposables = new();
public virtual string Name => GetType().Name;
public List<IGameSystem> Systems { get; } = new();
public IUpdateFilter UpdateFilter { get; set; }
public void Add(IGameSystem system)
{
Systems.Add(system);
if (system is IInitializable initializable) _initializables.Add(initializable);
if (system is IUpdatable updatable) _updatables.Add(updatable);
if (system is IDisposable disposable) _disposables.Add(disposable);
}
public virtual async UniTask InitializeAsync()
{
SystemSorter.InitializableSorter.Sort(_initializables);
SystemSorter.UpdatableSorter.Sort(_updatables);
SystemSorter.DisposableSorter.Sort(_disposables);
var batches = SystemSorter.InitializableSorter.CreateExecutionBatches(_initializables);
foreach (var batch in batches)
{
var tasks = new UniTask[batch.Count];
for (var i = 0; i < batch.Count; i++) tasks[i] = InitializeAndLogAsync(batch[i]);
await UniTask.WhenAll(tasks);
}
}
private static async UniTask InitializeAndLogAsync(IInitializable initializable)
{
var startTime = Time.unscaledTime;
await initializable.InitializeAsync();
LogInitializationTime(initializable, startTime);
}
private static void LogInitializationTime(IInitializable initializable, float startTime)
{
if (initializable is GameSystemGroup) return;
var elapsed = Time.unscaledTime - startTime;
var log = $"Initialized {((IGameSystem)initializable).Name} in {(int)(elapsed * 1000)} ms";
if (elapsed > 0.3f) log = $"<color=yellow>{log}</color>";
Debug.Log(log);
}
public virtual void Update()
{
foreach (var updatable in _updatables)
{
if (UpdateFilter != null && !UpdateFilter.CanUpdate(updatable)) continue;
updatable.Update();
}
}
public virtual void Dispose()
{
foreach (var disposable in _disposables) disposable.Dispose();
}
}
}