Descripción general de la arquitectura
Esta guía es para los usuarios de las ediciones Source y Studio que tienen acceso al código fuente C# completo de MCE.
Las flechas apuntan en una sola dirección a propósito. Core nunca depende de Online ni del importador,
y eso es lo que permite que la capa en línea sea de verdad opcional y no opcional solo en el README.
Este documento cubre la jerarquía de módulos, la estructura de ensamblados, los patrones de inyección de dependencias y los sistemas de ejecución clave que componen el Monster Capture Engine.
Jerarquía de módulos
MCE se organiza en módulos que siguen una arquitectura por capas:
Assets/
OpenMon/
Core/
Runtime/ # Core engine (REQUIRED)
Initialization/ # Engine startup, first-time wizard
Monster/ # MonsterInstance, Roster, evolution, breeding
MonsterDatabase/ # ScriptableObject definitions (species, moves, items, abilities)
Battle/ # BattleManager, 15 modules, state machine, AI
Characters/ # MCECharacterController, PlayerCharacter, followers
Actors/ # Actor system, CommandGraph visual scripting
World/ # GridController, GlobalGridManager, tiles, encounters
Saves/ # SavegameManager, SavableObject, GameVariables
Player/ # GlobalGameData, player state
UI/ # All UI controllers and views
Quests/ # Quest system (objectives, rewards, tracking)
SDK/ # Public API interfaces
GameFlow/ # Game state management
Configuration/ # ScriptableObject configs
Rendering/ # URP shaders, time-of-day, weather
Audio/ # AudioSettingsManager, AudioConfiguration (the playback engine is in Foundation)
Localization/ # Multi-language support
Badges/ # Badge tracking
Input/ # Input abstraction
MonsterDex/ # Dex tracking (seen/caught)
Animation/ # Animation utilities
WorldGenerator/ # Procedural region generator
Licensing/ # Tier and license checks
Shaders/ # Shader source files
Editor/ # Editor-only tooling
MonsterCreator/ # Monster creation wizard
Tools/ # Database Browser, Type Chart Editor, validators
Followers/ # Follower spritesheet tools
Actors/ # CommandGraph editor
Hub/ # The OpenMon Hub window
MapEditor/ # Scene View map painting overlays
Callbacks/ # Editor callback utilities
Reglas de dependencia
- El Core Runtime no tiene ninguna dependencia externa de los módulos Online o Importer.
- Las funciones en línea son opcionales mediante el símbolo de scripting define
MCE_ONLINE. - El código de Editor está estrictamente separado del Runtime mediante límites de
.asmdef. - Las interfaces del SDK en
Runtime/SDK/son la superficie de API pública para los usuarios de las ediciones compiladas (DLL).
Estructura de ensamblados
MCE usa Assembly Definitions de Unity para imponer límites de compilación:
| Ensamblado | Ubicación | Propósito | Referencias |
|---|---|---|---|
OpenMon.Foundation.Runtime | Foundation/Runtime/ | Framework compartido: DI, audio, localización, gestión de escenas, tweening | Zenject y paquetes de Unity |
OpenMon.Foundation.Editor | Foundation/Editor/ | Herramientas de editor de Foundation | Foundation Runtime + UnityEditor |
OpenMon.MCE.Runtime | Core/Runtime/ | Sistemas de juego centrales | Solo las bibliotecas de Foundation |
OpenMon.MCE.Editor | Core/Editor/ | Herramientas de editor | Runtime + UnityEditor |
OpenMon.Hub.Editor | Core/Editor/Hub/ | La ventana del OpenMon Hub (llama por nombre a las herramientas del importador y de la capa en línea, así que no depende de ninguna de las dos) | Foundation Runtime |
MCE.Online.Runtime | Online/Runtime/ | Red con Nakama | Runtime + SDK de Nakama |
MCE.Online.Editor | Online/Editor/ | Herramientas de editor de la capa en línea | Online Runtime + UnityEditor |
MCE.EssentialsImporter.Runtime | Importer/Runtime/ | Analizadores PBS/rxdata y el validador de importación | Runtime + KaitaiStruct |
MCE.EssentialsImporter.Editor | Importer/Editor/ | Pipeline de importación | Runtime + KaitaiStruct |
OpenMon.Setup | Setup/ | Instalador de dependencias de paquetes y configuración rápida | ninguna (aislado a propósito) |
MCE.Runtime.Tests | Core/Tests/Runtime/ | Pruebas de modo de juego del Core | Runtime + NUnit |
MCE.Editor.Tests | Core/Tests/Editor/ | Pruebas de modo edición del Core | Runtime + Editor + NUnit |
Por qué importan las Assembly Definitions
- Aislamiento de compilación: los cambios en el código de Editor no recompilan el Runtime.
- Cumplimiento de dependencias: el compilador impide que el Runtime referencie las API de Editor.
- Eliminación en la compilación: los ensamblados de Editor se excluyen de las compilaciones del jugador.
- Aislamiento de las pruebas: los ensamblados de prueba pueden referenciar internos sin exponerlos en producción.
Inyección de dependencias (Zenject)
MCE usa Zenject (Extenject) con el patrón de instaladores para la inyección de dependencias.
Patrón de instaladores
Cada subsistema tiene su propio instalador que registra los enlaces. La mayoría son instaladores ScriptableObject; el del lanzador de batalla es típico:
[CreateAssetMenu(menuName = "MCE/Dependency Injection/Battle Launcher Installer",
fileName = "BattleLauncherInstaller")]
public class BattleLauncherInstaller : LazySingletonScriptableInstaller<BattleLauncher>
{
public override void InstallBindings()
{
Reference.Reset();
Container.QueueForInject(Reference);
Container.Bind<IBattleLauncher>().FromInstance(Reference).AsSingle().Lazy();
}
}
BattleLauncher es en sí un ScriptableObject (un asset), y el asset del instalador apunta a él. La página de Inyección de dependencias lista todos los instaladores.
Instaladores clave
| Instalador | Enlaza |
|---|---|
GameFlowInstaller | Servicios centrales del flujo del juego |
PlayerCharacterInstaller | PlayerCharacter, servicios de personajes |
BattleLauncherInstaller | IBattleLauncher, el punto de entrada de la batalla |
GridInstaller | La cuadrícula de la escena (un MonoInstaller) |
SceneInfoInstaller | SceneInfo, metadatos de escena |
WorldDatabaseInstaller | WorldDatabase, datos globales de mapas |
TileDataInstaller | Datos de tipos de tile |
GlobalGridManagerInstaller | Navegación entre mapas |
SavegameInstaller | SavegameManager, serialización |
EvolutionManagerInstaller | EvolutionManager |
Convenciones
- Los enlaces son
.AsSingle().Lazy()por convención (una sola instancia, creada en el primer uso). [Inject]se usa en métodosConstruct(), no en constructores.- El patrón
DialogManager.Factoryse usa para instanciar la interfaz en tiempo de ejecución. - Los instaladores con ámbito de escena (por ejemplo
GridInstaller, unMonoInstaller) gestionan los servicios por escena. - Los instaladores con ámbito de proyecto (assets ScriptableObject en el prefab
ProjectContext) gestionan los servicios globales.
Puntos de inyección
public class SomeManager : MonoBehaviour
{
// Field injection (for MonoBehaviours).
// Note: of the SDK interfaces, only IMonsterCaptureEngine is bound —
// take Database/Battle/Player/SaveSystem from its properties.
[Inject] private IMonsterCaptureEngine engine;
private IBattleSystem battle;
private void Awake()
{
battle = engine.Battle;
}
// Method injection (preferred for explicit dependencies on engine-internal types)
[Inject]
public void Construct(MCESettings settings, MonsterDatabaseInstance database)
{
this.settings = settings;
this.database = database;
}
}
Sistemas clave de ejecución
Flujo de MCEInitialization
MCEInitialization es lo primero que se ejecuta cuando arranca el juego:
1. Screen setup (resolution, orientation)
2. Load databases (monsters, moves, items, abilities)
3. Download localization data (if remote)
4. Run first-time wizard (if needed)
5. Initialize subsystems (save manager, audio, input)
6. Signal ready
7. Load main menu or continue saved game
Es un MonoBehaviour en un GameObject persistente que sobrevive a las cargas de escena.
Sistema de monstruos
El modelo de datos de los monstruos:
MonsterEntry (ScriptableObject - species definition)
├── Base stats, types, abilities
├── List<DataByFormEntry> (private per-form overrides)
├── DataByFormEntry.Evolutions: List<EvolutionData> (evolution paths)
└── Move lists (level-up, TM, egg, tutor)
MonsterInstance (runtime - individual monster)
├── Species reference (MonsterEntry)
├── Level, XP
├── IVs[6], EVs[6]
├── Nature
├── Current HP, Status
├── MoveSlot[4] (with PP)
├── Friendship, OT data
└── Form index
Roster (party of up to 6 MonsterInstances)
MonsterStorage (PC boxes)
Sistema de batalla
Consulta Internos de la batalla para el análisis a fondo.
Sistema del mundo
GlobalGridManager (cross-map navigation)
└── GridController (per-scene grid)
├── TileData grid (collision, type per tile)
├── EncounterTile zones
└── SceneInfo (metadata)
MCECharacterController (movement)
├── PlayerCharacter (input + encounters)
└── ActorCharacter (NPC AI movement)
Sistema de guardado
SavegameManager
├── MCESavesSerializer (JSON read/write)
├── SavableObject[] (registered savables)
└── GameVariables (global state)
Estilo de código
El código base sigue estas convenciones:
- Sangría de 4 espacios, llaves en líneas nuevas.
- PascalCase para tipos, métodos y propiedades públicos.
- camelCase para campos privados y variables locales.
[SerializeField] privateen lugar de campos públicos.Runtime/yEditor/separados tras límites de.asmdef.- Conventional Commits:
feat:,fix:,docs:,refactor:.
Nunca renombres campos serializados sin un plan de migración. Las escenas y los prefabs dependen de los nombres de los campos serializados. Usa [FormerlySerializedAs("oldName")] para los cambios de nombre.
Extender el motor
Agregar un sistema nuevo
- Crea tus clases en
Runtime/YourSystem/. - Crea un instalador para la inyección de dependencias.
- Agrega el instalador al contexto de escena o de proyecto adecuado.
- Si necesita datos de guardado, extiende
SavableObject. - Si tiene herramientas de editor, crea clases en
Editor/YourSystem/.
Modificar un sistema existente
- Lee el código existente y comprende las dependencias del módulo.
- Comprueba si el cambio se puede hacer mediante configuración o extensión en lugar de modificación.
- Si modificas, sigue los patrones existentes del módulo.
- Actualiza las pruebas para cubrir el cambio.
- Documenta el cambio en los mensajes de commit.
Consideraciones de rendimiento
- Las consultas a la base de datos mediante el SDK (
GetMonster(dexNumber),GetMonster(name)) recorren la lista de especies. Guarda la entrada en caché si las llamas a menudo. - Los módulos de batalla son componentes del GameObject de la batalla, creados con él una vez por batalla, no por turno.
- Los tilemaps grandes cuestan más por paso y por fotograma. Divide los mapas muy grandes en escenas conectadas (consulta Neighbours en Movimiento basado en cuadrícula).
- La serialización del guardado es síncrona en el hilo principal. Mantén razonable el tamaño de los datos de guardado.
- La ejecución de CommandGraph se basa en corrutinas. Los grafos complejos con muchos nodos están bien para el scripting de eventos, pero no deben usarse para lógica por fotograma.