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.
These three are injected, not looked up. Swapping the persister for a cloud one is a binding change, not a refactor.
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.
| Parameter | Type | Description |
|---|---|---|
data | TOriginal | The object to persist |
destination | string | Where to write it |
suppressErrors | bool | Don'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.
| Parameter | Type | Description |
|---|---|---|
data | out TOriginal | Receives the loaded object |
origin | string | Where to read from |
suppressErrors | bool | Don'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 requiredContainer.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.
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"));
}
}