Created
October 5, 2023 02:59
-
-
Save mchamplain/ce6437da3b83cd877d604115b51db3ea to your computer and use it in GitHub Desktop.
Helper to find Entitas systems that we didn't add to the systems (Entitas v1.x)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System; | |
| using System.Collections.Generic; | |
| using System.Linq; | |
| using System.Reflection; | |
| using Entitas; | |
| using UnityEngine; | |
| namespace Common.Utilities | |
| { | |
| public static class SystemsVerificationTool | |
| { | |
| public static void EnsureAllSystemsAreAdded(Feature mainSystems, string namespaceFilter) | |
| { | |
| var allSystemsInNamespace = GetAllSystemsInNamespace(namespaceFilter); | |
| var addedSystems = GetAddedSystemsFromFeature(mainSystems); | |
| foreach (var systemType in allSystemsInNamespace) | |
| { | |
| if (!addedSystems.Contains(systemType)) | |
| { | |
| Debug.LogWarning($"System {systemType.Name} is not added to the main systems list."); | |
| } | |
| } | |
| } | |
| private static HashSet<Type> GetAllSystemsInNamespace(string namespaceFilter) | |
| { | |
| return new HashSet<Type>(Assembly.GetExecutingAssembly().GetTypes() | |
| .Where(type => type.Namespace != null && type.Namespace.StartsWith(namespaceFilter) && | |
| !typeof(Feature).IsAssignableFrom(type) && // Exclude Feature types | |
| (typeof(IExecuteSystem).IsAssignableFrom(type) || | |
| typeof(ICleanupSystem).IsAssignableFrom(type) || | |
| typeof(IInitializeSystem).IsAssignableFrom(type) || | |
| typeof(ITearDownSystem).IsAssignableFrom(type) || | |
| type.IsSubclassOf(typeof(ReactiveSystem<>)) | |
| ))); | |
| } | |
| private static HashSet<Type> GetAddedSystemsFromFeature(Feature feature) | |
| { | |
| var addedSystems = new HashSet<Type>(); | |
| // Extract all systems added to the Feature | |
| List<object> featureSystems = new List<object>(); | |
| featureSystems.AddRange(feature.GetSystems<IInitializeSystem>()); | |
| featureSystems.AddRange(feature.GetSystems<IExecuteSystem>()); | |
| featureSystems.AddRange(feature.GetSystems<ICleanupSystem>()); | |
| featureSystems.AddRange(feature.GetSystems<ITearDownSystem>()); | |
| foreach (var system in featureSystems) | |
| { | |
| if (system is Feature subFeature) | |
| { | |
| addedSystems.UnionWith(GetAddedSystemsFromFeature(subFeature)); // Recursion for nested Features | |
| } | |
| else | |
| { | |
| addedSystems.Add(system.GetType()); | |
| } | |
| } | |
| return addedSystems; | |
| } | |
| public static List<T> GetSystems<T>(this Feature feature) | |
| { | |
| // Get non-public fields using reflection based on type T | |
| string fieldName = ""; | |
| if (typeof(T) == typeof(IInitializeSystem)) | |
| { | |
| fieldName = "_initializeSystems"; | |
| } | |
| else if (typeof(T) == typeof(IExecuteSystem)) | |
| { | |
| fieldName = "_executeSystems"; | |
| } | |
| else if (typeof(T) == typeof(ICleanupSystem)) | |
| { | |
| fieldName = "_cleanupSystems"; | |
| } | |
| else if (typeof(T) == typeof(ITearDownSystem)) | |
| { | |
| fieldName = "_tearDownSystems"; | |
| } | |
| FieldInfo field = typeof(Feature).GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance); | |
| if (field != null) | |
| { | |
| return field.GetValue(feature) as List<T>; | |
| } | |
| return new List<T>(); | |
| } | |
| } | |
| } | |
| /** | |
| Usage: | |
| systems = new Feature("Game Systems"); | |
| systems | |
| .Add(new TimerFeature(contexts)) | |
| .Add(new GameStateFeature(contexts)) | |
| .Add(new TutorialFeature(contexts)) | |
| //... | |
| ; | |
| #if UNITY_EDITOR | |
| // let's check if we forgot to include a system -_- | |
| SystemsVerificationTool.EnsureAllSystemsAreAdded(systems, "MyGame.Scripts"); | |
| #endif | |
| */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment