Skip to main content

Foundation Services

The OpenMon.Foundation layer is the shared framework the whole engine sits on: dependency injection, persistence, scene management and localization. These interfaces are stable, Zenject-injectable, and reusable in your own systems. This page documents the three service interfaces plus the two DI helpers you subclass most often.

foundation services

These three are injected, not looked up. Swapping the persister for a cloud one is a binding change, not a refactor.

Foundation is engine-agnostic

Nothing in OpenMon.Foundation knows about monsters or battles. Injecting these interfaces (rather than the concrete implementations) keeps your code testable and lets the engine swap implementations without breaking you.

IPersister​

Namespace: OpenMon.Foundation.Persistence

The storage abstraction behind every save. Implementations (JsonFilePersister, ConfigurationJsonFilePersister, …) decide where bytes land; callers only deal with typed save/load.

public interface IPersister
{
bool Save<TOriginal>(TOriginal data, string destination, bool suppressErrors = false);
bool Load<TOriginal>(out TOriginal data, string origin, bool suppressErrors = false);
}

Save<TOriginal>(TOriginal data, string destination, bool suppressErrors = false)​

Serialize data to destination.

ParameterTypeDescription
dataTOriginalThe object to persist
destinationstringWhere to write it
suppressErrorsboolDon't log errors — useful for systems that work fine when the resource is missing (e.g. the configuration manager reading an absent config on first run)

Returns: bool — true on success.

Load<TOriginal>(out TOriginal data, string origin, bool suppressErrors = false)​

Deserialize from origin into data.

ParameterTypeDescription
dataout TOriginalReceives the loaded object
originstringWhere to read from
suppressErrorsboolDon't log errors when the resource may legitimately be absent

Returns: bool — true on success (a missing file returns false, not an exception).

ISceneManager​

Namespace: OpenMon.Foundation.SceneManagement

Wraps Unity's SceneManager to add loaded-scene tracking, availability validation and event broadcasting. Scenes are addressed either by SceneReference or by name.

public interface ISceneManager
{
List<string> LoadedScenes { get; }
string[] SceneNames { get; }

bool IsSceneAvailable(SceneReference scene);
bool IsSceneAvailable(string scene);

void LoadScene(SceneReference sceneReference, Action<float> progressCallback,
Action<bool> callback, LoadSceneMode mode = LoadSceneMode.Additive);
void LoadScene(string sceneName, Action<float> progressCallback,
Action<bool> callback, LoadSceneMode mode = LoadSceneMode.Additive);

void UnloadScene(SceneReference sceneReference, Action<float> progressCallback, Action<bool> callback);
void UnloadScene(string sceneName, Action<float> progressCallback, Action<bool> callback);

Scene GetActiveScene();
string GetActiveSceneName();
void SetActiveScene(SceneReference scene);
void SetActiveScene(string sceneName);

void MoveObjectToActiveScene(GameObject gameObject);
void MoveObjectToScene(GameObject gameObject, SceneReference scene);
void MoveObjectToScene(GameObject gameObject, string scene);
}

LoadedScenes​

Names of all currently loaded scenes.

Type: List<string> (read-only)

SceneNames​

All known scene names — both in Build Settings and addressable.

Type: string[] (read-only)

IsSceneAvailable(SceneReference scene)​

Whether a scene can actually be loaded (its asset is present). An overload takes a scene name.

Returns: bool.

LoadScene(SceneReference sceneReference, Action<float> progressCallback, Action<bool> callback, LoadSceneMode mode = LoadSceneMode.Additive)​

Load a scene, reporting progress via progressCallback and success via callback. Defaults to Additive so the boot/persistent scene stays loaded. A name-based overload exists.

UnloadScene(SceneReference sceneReference, Action<float> progressCallback, Action<bool> callback)​

Unload a scene, reporting progress and success. A name-based overload exists.

GetActiveScene() / GetActiveSceneName() / SetActiveScene(...)​

Read or set Unity's active scene (the one new objects are instantiated into).

MoveObjectToActiveScene(GameObject gameObject) / MoveObjectToScene(...)​

Move a GameObject to the active scene or a specific scene — the standard way to hand a pooled/persistent object to whichever scene should own it.

ILocalizer​

Namespace: OpenMon.Foundation.Localization

The localization service. Text is keyed; valueModifiers substitute {0}, {1}, … placeholders in the resolved string. The indexer is the ergonomic path for a single key; the GetText / GetTexts overloads add language selection and batching.

public interface ILocalizer
{
string this[string key, bool modifiersAreLocalizableKeys = true, params string[] valueModifiers] { get; }

string GetText(string key, bool modifiersAreLocalizableKeys = true, params string[] valueModifiers);
string GetText(string key, string language, bool modifiersAreLocalizableKeys = true, params string[] valueModifiers);
string GetText(string key, int languageIndex, bool modifiersAreLocalizableKeys = true, params string[] valueModifiers);

List<string> GetTexts(List<string> keys);
List<string> GetTexts(List<string> keys, string language);

string GetCurrentLanguage();
int GetCurrentLanguageIndex();
int GetLanguageIndex(string language);
List<string> GetAllLanguageIds();

void SetLanguage(string language);
void SetLanguage(int language);

void SubscribeToLanguageChange(Action<string> callback);
void SubscribeToLanguageChange(Action callback);
void UnsubscribeFromLanguageChange(Action<string> callback);
void UnsubscribeFromLanguageChange(Action callback);

void LoadNewLanguageValues(List<ScriptableLanguage> newLanguages);
void ReDownloadLanguagesFromGoogleSheet();
}

this[string key, bool modifiersAreLocalizableKeys = true, params string[] valueModifiers]​

Indexer that returns the localized string for key in the current language. valueModifiers replace {number} placeholders; when modifiersAreLocalizableKeys is true the modifiers are themselves treated as keys and localized first.

Returns: string.

GetText(string key, bool modifiersAreLocalizableKeys = true, params string[] valueModifiers)​

Method form of the indexer. Overloads add a target language (by id or index) to pull from a specific language regardless of the current one.

Returns: string.

GetTexts(List<string> keys)​

Batch-resolve several keys at once. Overloads add a target language.

Returns: List<string>.

GetCurrentLanguage() / GetCurrentLanguageIndex() / GetAllLanguageIds()​

Query the active language (key or index) and enumerate all available language ids.

SetLanguage(string language) / SetLanguage(int language)​

Switch the active language by id or index. Raises the language-changed event.

SubscribeToLanguageChange / UnsubscribeFromLanguageChange​

Register/unregister for language-change notifications (with or without the new language id). Use the same delegate instance to unsubscribe.

Dependency Injection helpers​

Namespace: OpenMon.Foundation.DependencyInjection

The engine binds every shared asset through small Zenject installers. When you make a data asset injectable, subclass one of these.

LazySingletonScriptableInstaller<T>​

A ScriptableObjectInstaller that binds an inspector-assigned ScriptableObject as a lazy singleton of type T.

public class LazySingletonScriptableInstaller<T> : ScriptableObjectInstaller
where T : ScriptableObject
{
[SerializeField] protected T Reference;

public override void InstallBindings()
{
Container.QueueForInject(Reference);
Container.Bind<T>().FromInstance(Reference).AsSingle().Lazy();
}
}
QueueForInject is required

Container.QueueForInject(Reference) is not optional. ScriptableObjects are not injected automatically by Zenject — without this call any [Inject] members on the asset stay null. The .AsSingle().Lazy() binding then shares one instance and defers resolution until T is first requested.

To make your own data asset injectable, subclass with a concrete T:

using OpenMon.Foundation.DependencyInjection;
using UnityEngine;

[CreateAssetMenu(menuName = "MyGame/MyConfig")]
public class MyConfig : ScriptableObject { public int Difficulty; }

public class MyConfigInstaller : LazySingletonScriptableInstaller<MyConfig> { }

A sibling LazySingletonMonoInstaller<T> does the same for scene MonoBehaviour singletons.

AssetManagementUtils (editor-only)​

Namespace: OpenMon.Foundation.Editor.Utils

Editor helpers for bulk asset loading. Lives in the Runtime assembly but the whole body is gated behind UNITY_EDITOR, so it never ships in a player build.

public static class AssetManagementUtils
{
public static void CreateFolderIfDoesNotExist(string path);
public static List<T> FindAssetsByType<T>() where T : Object;
}

FindAssetsByType<T>()​

Load every asset of type T in the project.

Abstract base types need the subclass fallback

A plain AssetDatabase.FindAssets("t:BaseType") returns nothing for an abstract base type — Unity stores the assets as concrete subclasses. When T is abstract, FindAssetsByType<T> falls back to scanning every concrete subclass across all loaded assemblies. Without that fallback, loading e.g. an abstract Move base yields an empty list, and a caller like MonsterDatabaseInstance.LoadAllMoves() would overwrite the database's move list with nothing on an update — wiping every move in imported and demo games. If you write similar bulk loaders, reuse this helper rather than calling FindAssets directly.

Returns: List<T> — matching assets, or an empty list if none.

Usage Example​

using OpenMon.Foundation.Localization;
using OpenMon.Foundation.SceneManagement;
using Zenject;

public class TitleScreen : MonoBehaviour
{
[Inject] private ILocalizer localizer;
[Inject] private ISceneManager sceneManager;

private void Start()
{
// Localized, placeholder-substituted text.
Debug.Log(localizer["TitleScreen/Welcome", true, "Player"]);
Debug.Log($"Language: {localizer.GetCurrentLanguage()}");

// Load the first map additively, logging progress.
sceneManager.LoadScene(
"Overworld",
progress => Debug.Log($"Loading: {progress:P0}"),
success => Debug.Log(success ? "Loaded" : "Failed"));
}
}