Saltar al contenido principal

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.

Arquitectura de módulos

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​

  1. El Core Runtime no tiene ninguna dependencia externa de los módulos Online o Importer.
  2. Las funciones en línea son opcionales mediante el símbolo de scripting define MCE_ONLINE.
  3. El código de Editor está estrictamente separado del Runtime mediante límites de .asmdef.
  4. 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:

EnsambladoUbicaciónPropósitoReferencias
OpenMon.Foundation.RuntimeFoundation/Runtime/Framework compartido: DI, audio, localización, gestión de escenas, tweeningZenject y paquetes de Unity
OpenMon.Foundation.EditorFoundation/Editor/Herramientas de editor de FoundationFoundation Runtime + UnityEditor
OpenMon.MCE.RuntimeCore/Runtime/Sistemas de juego centralesSolo las bibliotecas de Foundation
OpenMon.MCE.EditorCore/Editor/Herramientas de editorRuntime + UnityEditor
OpenMon.Hub.EditorCore/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.RuntimeOnline/Runtime/Red con NakamaRuntime + SDK de Nakama
MCE.Online.EditorOnline/Editor/Herramientas de editor de la capa en líneaOnline Runtime + UnityEditor
MCE.EssentialsImporter.RuntimeImporter/Runtime/Analizadores PBS/rxdata y el validador de importaciónRuntime + KaitaiStruct
MCE.EssentialsImporter.EditorImporter/Editor/Pipeline de importaciónRuntime + KaitaiStruct
OpenMon.SetupSetup/Instalador de dependencias de paquetes y configuración rápidaninguna (aislado a propósito)
MCE.Runtime.TestsCore/Tests/Runtime/Pruebas de modo de juego del CoreRuntime + NUnit
MCE.Editor.TestsCore/Tests/Editor/Pruebas de modo edición del CoreRuntime + 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​

InstaladorEnlaza
GameFlowInstallerServicios centrales del flujo del juego
PlayerCharacterInstallerPlayerCharacter, servicios de personajes
BattleLauncherInstallerIBattleLauncher, el punto de entrada de la batalla
GridInstallerLa cuadrícula de la escena (un MonoInstaller)
SceneInfoInstallerSceneInfo, metadatos de escena
WorldDatabaseInstallerWorldDatabase, datos globales de mapas
TileDataInstallerDatos de tipos de tile
GlobalGridManagerInstallerNavegación entre mapas
SavegameInstallerSavegameManager, serialización
EvolutionManagerInstallerEvolutionManager

Convenciones​

  • Los enlaces son .AsSingle().Lazy() por convención (una sola instancia, creada en el primer uso).
  • [Inject] se usa en métodos Construct(), no en constructores.
  • El patrón DialogManager.Factory se usa para instanciar la interfaz en tiempo de ejecución.
  • Los instaladores con ámbito de escena (por ejemplo GridInstaller, un MonoInstaller) 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] private en lugar de campos públicos.
  • Runtime/ y Editor/ separados tras límites de .asmdef.
  • Conventional Commits: feat:, fix:, docs:, refactor:.
Campos serializados

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​

  1. Crea tus clases en Runtime/YourSystem/.
  2. Crea un instalador para la inyección de dependencias.
  3. Agrega el instalador al contexto de escena o de proyecto adecuado.
  4. Si necesita datos de guardado, extiende SavableObject.
  5. Si tiene herramientas de editor, crea clases en Editor/YourSystem/.

Modificar un sistema existente​

  1. Lee el código existente y comprende las dependencias del módulo.
  2. Comprueba si el cambio se puede hacer mediante configuración o extensión en lugar de modificación.
  3. Si modificas, sigue los patrones existentes del módulo.
  4. Actualiza las pruebas para cubrir el cambio.
  5. 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.