using System; using UnityEngine; using Framework.Support; namespace Framework.Services { /// Manages and provides access to a game object holding the services public static class ServiceContainer { /// Name of the game object for game-wide services public const string GlobalServicesGameObjectName = "Global"; /// Name of the game object for services limited to the scenes public const string SessionServicesGameObjectName = "Session"; /// Name of the game object for services in the current scene public const string SceneServicesGameObjectName = "Scene"; /// Retrieves or creates the service of the specified type /// Component that will be created /// Scope in which the service will be created /// The requested component public static TComponent GetOrCreateComponent(Scope scope) where TComponent : MonoBehaviour { GameObject container = GetOrCreate(scope); TComponent component = container.GetComponent(); if(component == null) { component = container.AddComponent(); } return component; } /// Retrieves the services root for the specified scope /// Scope for which the services root will be retrieved /// The services root for the specified scope public static GameObject GetOrCreate(Scope scope) { switch(scope) { case Scope.Scene: { bool needDestroyer = GameObjectHelper.IsNullOrDestroyed(sceneServicesGameObject); GameObject gameObject = getOrCreate( SceneServicesGameObjectName, ref sceneServicesGameObject ); if(needDestroyer) { gameObject.AddComponent(); } return gameObject; } case Scope.Session: { return getOrCreate(SessionServicesGameObjectName, ref sessionServicesGameObject); } case Scope.Global: { return getOrCreate(GlobalServicesGameObjectName, ref globalServicesGameObject); } default: { throw new ArgumentException("Unsupported scope", "scope"); } } } /// Kills all components in the specified scope /// Scope in which components will be killed public static void Kill(Scope scope) { switch(scope) { case Scope.Scene: { kill(SceneServicesGameObjectName, ref sceneServicesGameObject); break; } case Scope.Session: { kill(SessionServicesGameObjectName, ref sessionServicesGameObject); break; } case Scope.Global: { kill(GlobalServicesGameObjectName, ref globalServicesGameObject); break; } default: { throw new ArgumentException("Unsupported scope", "scope"); } } } /// Kills the specified service container /// Name of the service container that will be killed /// Field holding the cached service container private static void kill(string name, ref GameObject cached) { if(GameObjectHelper.IsNullOrDestroyed(cached)) { GameObject servicesRoot = ServicesRoot.Get(); if(GameObjectHelper.IsNullOrDestroyed(servicesRoot)) { return; } cached = GameObjectHelper.GetChildByName(servicesRoot, name); if(GameObjectHelper.IsNullOrDestroyed(cached)) { return; } } GameObject.Destroy(cached); cached = null; } /// Retrieves or creates a game object under the service root /// The game object with the specified name private static GameObject getOrCreate(string name, ref GameObject cached) { if(GameObjectHelper.IsNullOrDestroyed(cached)) { GameObject servicesRoot = ServicesRoot.GetOrCreate(); cached = GameObjectHelper.GetChildByName(servicesRoot, name); if(GameObjectHelper.IsNullOrDestroyed(cached)) { cached = new GameObject(name); GameObjectHelper.SetAsChild(servicesRoot, cached); } } return cached; } /// Game object in which scene-scoped services will be stored private static GameObject sceneServicesGameObject; /// Game object in which session-scoped services will be stored private static GameObject sessionServicesGameObject; /// Game object in which global services will be stored private static GameObject globalServicesGameObject; } } // namespace Framework.Services