From 86b8cd9b5545f06b35573c6a1305cf60ff607942 Mon Sep 17 00:00:00 2001 From: Syntriax Date: Sun, 13 Apr 2025 12:52:27 +0300 Subject: [PATCH] feat!: GetRequiredBehaviour/HierarchyObject methods added for cleaner null handling --- Engine.Core/Behaviour.cs | 7 ++++ Engine.Core/Behaviour2D.cs | 2 +- Engine.Core/BehaviourBase.cs | 6 ++-- Engine.Core/BehaviourController.cs | 4 +-- Engine.Core/Exceptions/AssignException.cs | 12 ------- .../Exceptions/AssignFailedException.cs | 9 +++++ .../Exceptions/BehaviourNotFoundException.cs | 9 +++++ .../HierarchyObjectNotFoundException.cs | 9 +++++ .../Exceptions/NotAssignedException.cs | 14 +------- .../BehaviourControllerExtensions.cs | 36 ++++++++++++++++--- .../Extensions/GameManagerExtensions.cs | 10 ++++++ .../Extensions/HierarchyObjectExtensions.cs | 8 ++--- .../Factory/BehaviourControllerFactory.cs | 4 +-- Engine.Core/Factory/BehaviourFactory.cs | 6 ++-- Engine.Core/Factory/HierarchyObjectFactory.cs | 8 ++--- Engine.Core/Factory/StateEnableFactory.cs | 4 +-- Engine.Core/GameManager.cs | 24 +++---------- Engine.Core/Helpers/AssertHelpers.cs | 33 +++++++++++++++++ Engine.Core/HierarchyObject.cs | 2 +- Engine.Physics2D/PhysicsCoroutineManager.cs | 4 +-- Engine.Systems/Tween/TweenManager.cs | 2 +- 21 files changed, 140 insertions(+), 73 deletions(-) delete mode 100644 Engine.Core/Exceptions/AssignException.cs create mode 100644 Engine.Core/Exceptions/AssignFailedException.cs create mode 100644 Engine.Core/Exceptions/BehaviourNotFoundException.cs create mode 100644 Engine.Core/Exceptions/HierarchyObjectNotFoundException.cs create mode 100644 Engine.Core/Helpers/AssertHelpers.cs diff --git a/Engine.Core/Behaviour.cs b/Engine.Core/Behaviour.cs index ab1c651..a93e240 100644 --- a/Engine.Core/Behaviour.cs +++ b/Engine.Core/Behaviour.cs @@ -1,4 +1,5 @@ using Syntriax.Engine.Core.Abstract; +using Syntriax.Engine.Core.Helpers; namespace Syntriax.Engine.Core; @@ -55,6 +56,8 @@ public abstract class Behaviour : BehaviourBase protected virtual void OnPreUpdate() { } protected virtual void PreUpdate(IBehaviourController _) { + AssertHelpers.AssertInitialized(this); + OnPreUpdatePreActiveCheck(); if (!IsActive) @@ -77,6 +80,8 @@ public abstract class Behaviour : BehaviourBase protected virtual void OnUpdate() { } protected virtual void Update(IBehaviourController _) { + AssertHelpers.AssertInitialized(this); + OnUpdatePreActiveCheck(); if (!IsActive) @@ -89,6 +94,8 @@ public abstract class Behaviour : BehaviourBase protected virtual void OnPreDraw() { } protected virtual void PreDraw(IBehaviourController _) { + AssertHelpers.AssertInitialized(this); + OnPreDrawPreActiveCheck(); if (!StateEnable.Enabled) diff --git a/Engine.Core/Behaviour2D.cs b/Engine.Core/Behaviour2D.cs index 4225e24..deadeee 100644 --- a/Engine.Core/Behaviour2D.cs +++ b/Engine.Core/Behaviour2D.cs @@ -8,7 +8,7 @@ public abstract class Behaviour2D : Behaviour, IBehaviour2D protected sealed override void OnInitialize(IInitializable _) { - Transform = BehaviourController.GetBehaviourInChildren() ?? throw new($"{HierarchyObject.Name} does not contain any {nameof(ITransform2D)}"); + Transform = BehaviourController.GetRequiredBehaviour(); base.OnInitialize(_); } diff --git a/Engine.Core/BehaviourBase.cs b/Engine.Core/BehaviourBase.cs index c385ef6..72d0fe0 100644 --- a/Engine.Core/BehaviourBase.cs +++ b/Engine.Core/BehaviourBase.cs @@ -1,5 +1,6 @@ using Syntriax.Engine.Core.Abstract; using Syntriax.Engine.Core.Exceptions; +using Syntriax.Engine.Core.Helpers; namespace Syntriax.Engine.Core; @@ -69,9 +70,8 @@ public abstract class BehaviourBase : BaseEntity, IBehaviour protected override void InitializeInternal() { - base.InitializeInternal(); - NotAssignedException.Check(this, _behaviourController); - NotAssignedException.Check(this, StateEnable); + AssertHelpers.AssertBehaviourControllerAssigned(this); + AssertHelpers.AssertStateEnableAssigned(this); } private void OnStateEnabledChanged(IStateEnable sender, bool previousState) => UpdateActive(); diff --git a/Engine.Core/BehaviourController.cs b/Engine.Core/BehaviourController.cs index 341262d..3a9615e 100644 --- a/Engine.Core/BehaviourController.cs +++ b/Engine.Core/BehaviourController.cs @@ -4,7 +4,7 @@ using System.Collections.Generic; using System.Linq; using Syntriax.Engine.Core.Abstract; -using Syntriax.Engine.Core.Exceptions; +using Syntriax.Engine.Core.Helpers; namespace Syntriax.Engine.Core; @@ -141,7 +141,7 @@ public class BehaviourController : IBehaviourController if (IsInitialized) return false; - NotAssignedException.Check(this, _hierarchyObject); + AssertHelpers.AssertHierarchyObjectAssigned(this); foreach (IBehaviour behaviour in behaviours) behaviour.Initialize(); diff --git a/Engine.Core/Exceptions/AssignException.cs b/Engine.Core/Exceptions/AssignException.cs deleted file mode 100644 index ec4f234..0000000 --- a/Engine.Core/Exceptions/AssignException.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; - -namespace Syntriax.Engine.Core.Exceptions; - -public class AssignException : Exception -{ - public AssignException() : base("Assign operation has failed.") { } - public AssignException(string? message) : base(message) { } - - public static AssignException From(T to, T2? value) - => new($"Assign operation has failed on T: {to?.GetType().FullName ?? "\"null\""}, value: {value?.GetType().ToString() ?? "\"null\""}"); -} diff --git a/Engine.Core/Exceptions/AssignFailedException.cs b/Engine.Core/Exceptions/AssignFailedException.cs new file mode 100644 index 0000000..2cc474c --- /dev/null +++ b/Engine.Core/Exceptions/AssignFailedException.cs @@ -0,0 +1,9 @@ +using System; + +namespace Syntriax.Engine.Core.Exceptions; + +public class AssignFailedException(string? message) : Exception(message) +{ + public static AssignFailedException From(T to, T2? value) + => new($"Assign operation has failed on T: {to?.GetType().FullName ?? "\"null\""}, value: {value?.GetType().ToString() ?? "\"null\""}"); +} diff --git a/Engine.Core/Exceptions/BehaviourNotFoundException.cs b/Engine.Core/Exceptions/BehaviourNotFoundException.cs new file mode 100644 index 0000000..034d40e --- /dev/null +++ b/Engine.Core/Exceptions/BehaviourNotFoundException.cs @@ -0,0 +1,9 @@ +using System; + +namespace Syntriax.Engine.Core.Exceptions; + +public class BehaviourNotFoundException(string? message) : Exception(message) +{ + public static NotAssignedException FromType() + => new($"{typeof(TBehaviour).FullName} was not found"); +} diff --git a/Engine.Core/Exceptions/HierarchyObjectNotFoundException.cs b/Engine.Core/Exceptions/HierarchyObjectNotFoundException.cs new file mode 100644 index 0000000..c7161bd --- /dev/null +++ b/Engine.Core/Exceptions/HierarchyObjectNotFoundException.cs @@ -0,0 +1,9 @@ +using System; + +namespace Syntriax.Engine.Core.Exceptions; + +public class HierarchyObjectNotFoundException(string? message) : Exception(message) +{ + public static NotAssignedException FromType() + => new($"{typeof(THierarchyObject).FullName} was not found"); +} diff --git a/Engine.Core/Exceptions/NotAssignedException.cs b/Engine.Core/Exceptions/NotAssignedException.cs index ef2993c..bd1923a 100644 --- a/Engine.Core/Exceptions/NotAssignedException.cs +++ b/Engine.Core/Exceptions/NotAssignedException.cs @@ -1,21 +1,9 @@ using System; -using Syntriax.Engine.Core.Abstract; namespace Syntriax.Engine.Core.Exceptions; -public class NotAssignedException : Exception +public class NotAssignedException(string? message) : Exception(message) { - public NotAssignedException() : base("The object has not been assigned.") { } - public NotAssignedException(string? message) : base(message) { } - public static NotAssignedException From(T1 to, T2? value) => new($"{value?.GetType().FullName ?? "\"null\""} has not been assigned to {to?.GetType().FullName ?? "\"null\""}"); - - public static void Check(T1 to, T2? value) - { - if (value is not null) - return; - - throw From(to, value); - } } diff --git a/Engine.Core/Extensions/BehaviourControllerExtensions.cs b/Engine.Core/Extensions/BehaviourControllerExtensions.cs index df1b113..58014b1 100644 --- a/Engine.Core/Extensions/BehaviourControllerExtensions.cs +++ b/Engine.Core/Extensions/BehaviourControllerExtensions.cs @@ -1,6 +1,7 @@ using System.Diagnostics.CodeAnalysis; using Syntriax.Engine.Core.Abstract; +using Syntriax.Engine.Core.Exceptions; namespace Syntriax.Engine.Core; @@ -19,6 +20,15 @@ public static class BehaviourControllerExtensions return behaviour is not null; } + /// + /// Gets a of the specified type in the provided . Throws an error if not found. + /// + /// The type of to get. + /// The to start searching from. + /// The of the specified type if found; otherwise, throws . + public static T GetRequiredBehaviour(this IBehaviourController behaviourController) where T : class + => behaviourController.GetBehaviour() ?? throw new BehaviourNotFoundException($"{behaviourController.HierarchyObject.Name}'s {nameof(IBehaviourController)} does not contain any {typeof(T).FullName}"); + /// /// Gets an existing of the specified type, or adds and returns a new one if it doesn't exist. /// @@ -30,7 +40,7 @@ public static class BehaviourControllerExtensions => behaviourController.GetBehaviour() ?? behaviourController.AddBehaviour(args); /// - /// Tries to get a of the specified type in the parent hierarchy. + /// Tries to get a of the specified type in it's 's parents recursively. /// /// The type of to get. /// The to start searching from. @@ -43,7 +53,7 @@ public static class BehaviourControllerExtensions } /// - /// Gets a of the specified type in the parent hierarchy. + /// Gets a of the specified type in it's 's parents recursively. /// /// The type of to get. /// The to start searching from. @@ -64,7 +74,16 @@ public static class BehaviourControllerExtensions } /// - /// Tries to get a of the specified type in the child hierarchy. + /// Gets a of the specified type in it's 's parents recursively. Throws an error if not found. + /// + /// The type of to get. + /// The to start searching from. + /// The of the specified type if found; otherwise, throws . + public static T GetRequiredBehaviourInParent(this IBehaviourController behaviourController) where T : class + => behaviourController.GetBehaviourInParent() ?? throw new BehaviourNotFoundException($"{behaviourController.HierarchyObject.Name}'s {nameof(IBehaviourController)} does not contain any {typeof(T).FullName} on any parent"); + + /// + /// Tries to get a of the specified type in it's 's children recursively. /// /// The type of to get. /// The to start searching from. @@ -77,7 +96,7 @@ public static class BehaviourControllerExtensions } /// - /// Gets a of the specified type in the child hierarchy. + /// Gets a of the specified type in it's 's children recursively. /// /// The type of to get. /// The to start searching from. @@ -93,4 +112,13 @@ public static class BehaviourControllerExtensions return default; } + + /// + /// Gets a of the specified type in the children recursively. Throws an error if not found. + /// + /// The type of to get. + /// The to start searching from. + /// The of the specified type if found; otherwise, throws . + public static T GetRequiredBehaviourInChildren(this IBehaviourController behaviourController) where T : class + => behaviourController.GetBehaviourInChildren() ?? throw new BehaviourNotFoundException($"{behaviourController.HierarchyObject.Name}'s {nameof(IBehaviourController)} does not contain any {typeof(T).FullName} on any children "); } diff --git a/Engine.Core/Extensions/GameManagerExtensions.cs b/Engine.Core/Extensions/GameManagerExtensions.cs index fe6949a..577e80d 100644 --- a/Engine.Core/Extensions/GameManagerExtensions.cs +++ b/Engine.Core/Extensions/GameManagerExtensions.cs @@ -1,4 +1,5 @@ using Syntriax.Engine.Core.Abstract; +using Syntriax.Engine.Core.Exceptions; namespace Syntriax.Engine.Core; @@ -6,4 +7,13 @@ public static class GameManagerExtensions { public static IHierarchyObject InstantiateHierarchyObject(this IGameManager gameManager, params object?[]? args) => gameManager.InstantiateHierarchyObject(args); + + public static T GetRequiredHierarchyObject(this IGameManager gameManager) where T : class + { + foreach (IHierarchyObject hierarchyObject in gameManager) + if (hierarchyObject is T @object) + return @object; + + throw new HierarchyObjectNotFoundException($"{gameManager.GetType().FullName}({gameManager.Id}) does not contain any {typeof(T).FullName}"); + } } diff --git a/Engine.Core/Extensions/HierarchyObjectExtensions.cs b/Engine.Core/Extensions/HierarchyObjectExtensions.cs index bd012ae..1f2a73e 100644 --- a/Engine.Core/Extensions/HierarchyObjectExtensions.cs +++ b/Engine.Core/Extensions/HierarchyObjectExtensions.cs @@ -16,7 +16,7 @@ public static class HierarchyObjectExtensions return hierarchyObject; } - public static T? FindHierarchyObject(this IEnumerable hierarchyObjects) where T : class + public static T? GetHierarchyObject(this IEnumerable hierarchyObjects) where T : class { foreach (IHierarchyObject hierarchyObject in hierarchyObjects) if (hierarchyObject is T @object) @@ -25,13 +25,13 @@ public static class HierarchyObjectExtensions return default; } - public static bool TryFindHierarchyObject(this IEnumerable hierarchyObjects, [NotNullWhen(returnValue: true)] out T? behaviour) where T : class + public static bool TryGetHierarchyObject(this IEnumerable hierarchyObjects, [NotNullWhen(returnValue: true)] out T? behaviour) where T : class { - behaviour = FindHierarchyObject(hierarchyObjects); + behaviour = GetHierarchyObject(hierarchyObjects); return behaviour is not null; } - public static void FindHierarchyObjects(this IEnumerable hierarchyObjects, List behaviours) where T : class + public static void GetHierarchyObjects(this IEnumerable hierarchyObjects, List behaviours) where T : class { behaviours.Clear(); foreach (IHierarchyObject hierarchyObject in hierarchyObjects) diff --git a/Engine.Core/Factory/BehaviourControllerFactory.cs b/Engine.Core/Factory/BehaviourControllerFactory.cs index 08804b3..587a96d 100644 --- a/Engine.Core/Factory/BehaviourControllerFactory.cs +++ b/Engine.Core/Factory/BehaviourControllerFactory.cs @@ -14,10 +14,10 @@ public class BehaviourControllerFactory T behaviourController = TypeFactory.Get(args); if (!hierarchyObject.Assign(behaviourController)) - throw AssignException.From(hierarchyObject, behaviourController); + throw AssignFailedException.From(hierarchyObject, behaviourController); if (!behaviourController.Assign(hierarchyObject)) - throw AssignException.From(behaviourController, hierarchyObject); + throw AssignFailedException.From(behaviourController, hierarchyObject); return behaviourController; } diff --git a/Engine.Core/Factory/BehaviourFactory.cs b/Engine.Core/Factory/BehaviourFactory.cs index 23bf214..6a832e9 100644 --- a/Engine.Core/Factory/BehaviourFactory.cs +++ b/Engine.Core/Factory/BehaviourFactory.cs @@ -15,12 +15,12 @@ public class BehaviourFactory stateEnable ??= TypeFactory.Get(); if (!stateEnable.Assign(behaviour)) - throw AssignException.From(stateEnable, behaviour); + throw AssignFailedException.From(stateEnable, behaviour); if (!behaviour.Assign(stateEnable)) - throw AssignException.From(behaviour, stateEnable); + throw AssignFailedException.From(behaviour, stateEnable); if (!behaviour.Assign(hierarchyObject.BehaviourController)) - throw AssignException.From(behaviour, hierarchyObject.BehaviourController); + throw AssignFailedException.From(behaviour, hierarchyObject.BehaviourController); return behaviour; } diff --git a/Engine.Core/Factory/HierarchyObjectFactory.cs b/Engine.Core/Factory/HierarchyObjectFactory.cs index 099a890..23ec301 100644 --- a/Engine.Core/Factory/HierarchyObjectFactory.cs +++ b/Engine.Core/Factory/HierarchyObjectFactory.cs @@ -23,14 +23,14 @@ public class HierarchyObjectFactory stateEnable ??= TypeFactory.Get(); if (!behaviourController.Assign(hierarchyObject)) - throw AssignException.From(behaviourController, hierarchyObject); + throw AssignFailedException.From(behaviourController, hierarchyObject); if (!stateEnable.Assign(hierarchyObject)) - throw AssignException.From(stateEnable, hierarchyObject); + throw AssignFailedException.From(stateEnable, hierarchyObject); if (!hierarchyObject.Assign(behaviourController)) - throw AssignException.From(hierarchyObject, behaviourController); + throw AssignFailedException.From(hierarchyObject, behaviourController); if (!hierarchyObject.Assign(stateEnable)) - throw AssignException.From(hierarchyObject, stateEnable); + throw AssignFailedException.From(hierarchyObject, stateEnable); return hierarchyObject; } diff --git a/Engine.Core/Factory/StateEnableFactory.cs b/Engine.Core/Factory/StateEnableFactory.cs index aa705af..11cd2ff 100644 --- a/Engine.Core/Factory/StateEnableFactory.cs +++ b/Engine.Core/Factory/StateEnableFactory.cs @@ -12,10 +12,10 @@ public class StateEnableFactory T stateEnable = TypeFactory.Get(args); if (!entity.Assign(stateEnable)) - throw AssignException.From(entity, stateEnable); + throw AssignFailedException.From(entity, stateEnable); if (!stateEnable.Assign(entity)) - throw AssignException.From(stateEnable, entity); + throw AssignFailedException.From(stateEnable, entity); return stateEnable; } diff --git a/Engine.Core/GameManager.cs b/Engine.Core/GameManager.cs index bc7dc84..f90ba75 100644 --- a/Engine.Core/GameManager.cs +++ b/Engine.Core/GameManager.cs @@ -3,7 +3,7 @@ using System.Collections; using System.Collections.Generic; using Syntriax.Engine.Core.Abstract; -using Syntriax.Engine.Core.Exceptions; +using Syntriax.Engine.Core.Helpers; namespace Syntriax.Engine.Core; @@ -22,21 +22,6 @@ public class GameManager : BaseEntity, IGameManager public IReadOnlyList HierarchyObjects => _hierarchyObjects; - public override IStateEnable StateEnable - { - get - { - if (base.StateEnable is null) - { - Assign(Factory.StateEnableFactory.Instantiate(this)); - if (base.StateEnable is null) - throw NotAssignedException.From(this, base.StateEnable); - } - - return base.StateEnable; - } - } - public EngineTime Time { get; private set; } = new(); public EngineTime UnscaledTime { get; private set; } = new(); public float TimeScale @@ -104,9 +89,6 @@ public class GameManager : BaseEntity, IGameManager protected override void InitializeInternal() { - base.InitializeInternal(); - NotAssignedException.Check(this, StateEnable); - foreach (IHierarchyObject hierarchyObject in HierarchyObjects) hierarchyObject.Initialize(); } @@ -120,6 +102,8 @@ public class GameManager : BaseEntity, IGameManager public void Update(EngineTime engineTime) { + AssertHelpers.AssertInitialized(this); + UnscaledTime = engineTime; Time = new(TimeSpan.FromTicks((long)(Time.TimeSinceStart.Ticks + engineTime.DeltaSpan.Ticks * TimeScale)), TimeSpan.FromTicks((long)(engineTime.DeltaSpan.Ticks * TimeScale))); @@ -133,6 +117,8 @@ public class GameManager : BaseEntity, IGameManager public void PreDraw() { + AssertHelpers.AssertInitialized(this); + for (int i = 0; i < HierarchyObjects.Count; i++) HierarchyObjects[i].BehaviourController.UpdatePreDraw(); diff --git a/Engine.Core/Helpers/AssertHelpers.cs b/Engine.Core/Helpers/AssertHelpers.cs new file mode 100644 index 0000000..c4e2e97 --- /dev/null +++ b/Engine.Core/Helpers/AssertHelpers.cs @@ -0,0 +1,33 @@ +using System.Diagnostics; +using System.Runtime.CompilerServices; + +using Syntriax.Engine.Core.Abstract; + +namespace Syntriax.Engine.Core.Helpers; + +public class AssertHelpers +{ + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void AssertInitialized(IInitializable initializable) + => Debug.Assert(initializable.IsInitialized, $"{initializable.GetType().Name} must be initialized"); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void AssertBehaviourControllerAssigned(IHasBehaviourController assignable) + => Debug.Assert(assignable.BehaviourController is not null, $"{assignable.GetType().Name} must be initialized"); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void AssertEntityAssigned(IHasEntity assignable) + => Debug.Assert(assignable.Entity is not null, $"{assignable.GetType().Name} must be initialized"); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void AssertGameManagerAssigned(IHasGameManager assignable) + => Debug.Assert(assignable.GameManager is not null, $"{assignable.GetType().Name} must be initialized"); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void AssertHierarchyObjectAssigned(IHasHierarchyObject assignable) + => Debug.Assert(assignable.HierarchyObject is not null, $"{assignable.GetType().Name} must be initialized"); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void AssertStateEnableAssigned(IHasStateEnable assignable) + => Debug.Assert(assignable.StateEnable is not null, $"{assignable.GetType().Name} must be initialized"); +} diff --git a/Engine.Core/HierarchyObject.cs b/Engine.Core/HierarchyObject.cs index e617ede..8f32f58 100644 --- a/Engine.Core/HierarchyObject.cs +++ b/Engine.Core/HierarchyObject.cs @@ -71,7 +71,7 @@ public class HierarchyObject : BaseEntity, IHierarchyObject public void SetParent(IHierarchyObject? parent) { if (parent == this) - throw new Exceptions.AssignException($"{Name} can not parent itself"); + throw new Exceptions.AssignFailedException($"{Name} can not parent itself"); if (Parent == parent) return; diff --git a/Engine.Physics2D/PhysicsCoroutineManager.cs b/Engine.Physics2D/PhysicsCoroutineManager.cs index 81173c3..62feb2f 100644 --- a/Engine.Physics2D/PhysicsCoroutineManager.cs +++ b/Engine.Physics2D/PhysicsCoroutineManager.cs @@ -25,7 +25,7 @@ public class PhysicsCoroutineManager : HierarchyObject protected override void OnEnteringHierarchy(IGameManager gameManager) { - physicsEngine = gameManager.FindHierarchyObject(); + physicsEngine = gameManager.GetHierarchyObject(); if (physicsEngine is IPhysicsEngine2D foundPhysicsEngine) foundPhysicsEngine.OnPhysicsStep += OnPhysicsStep; else @@ -56,7 +56,7 @@ public class PhysicsCoroutineManager : HierarchyObject if (GameManager is not IGameManager gameManager) return; - physicsEngine = gameManager.FindHierarchyObject(); + physicsEngine = gameManager.GetHierarchyObject(); if (physicsEngine is IPhysicsEngine2D foundPhysicsEngine) { foundPhysicsEngine.OnPhysicsStep += OnPhysicsStep; diff --git a/Engine.Systems/Tween/TweenManager.cs b/Engine.Systems/Tween/TweenManager.cs index d045cef..e6df866 100644 --- a/Engine.Systems/Tween/TweenManager.cs +++ b/Engine.Systems/Tween/TweenManager.cs @@ -54,7 +54,7 @@ public class TweenManager : HierarchyObject protected override void OnEnteringHierarchy(IGameManager gameManager) { - coroutineManager = gameManager.FindHierarchyObject() ?? throw new($"No {nameof(CoroutineManager)} was found in the game manager"); + coroutineManager = gameManager.GetRequiredHierarchyObject(); } protected override void OnExitingHierarchy(IGameManager gameManager)