Публичный API
Публичный API входит в редакции Indie, Pro, Source и Studio (в Starter API закрыт); полный исходный код C# есть только в Source и Studio. Это руководство описывает стабильную поверхность публичного API, которую можно использовать для взаимодействия с MCE и его расширения из собственных скриптов на C#, не связывая игровой код с внутренними дет алями.
Стабильность — это обещание об ИМЕНИ. Всё остальное может меняться между версиями.
Пространство имён SDK
MCE предоставляет свой публичный API через пространство имён OpenMon.MCE.SDK. Оно содержит чистые интерфейсы, дающие доступ к подсистемам движка без привязки вашего кода к внутренним реализациям.
IMonsterCaptureEngine
Главная точка входа. Все остальные интерфейсы доступны через неё:
using OpenMon.MCE.SDK;
public class MyGameManager : MonoBehaviour
{
[Inject] private IMonsterCaptureEngine engine;
private void Start()
{
Debug.Log($"MCE Version: {engine.Version}");
Debug.Log($"Monsters in DB: {engine.Database.MonsterCount}");
Debug.Log($"Player name: {engine.Player.PlayerName}");
}
}
Свойства:
| Свойство | Тип | Описание |
|---|---|---|
Database | IMonsterDatabase | Доступ только для чтения к базе данных монстров/приёмов/предметов |
Battle | IBattleSystem | Состояние и события сражения |
Player | IPlayerData | Команда, деньги, имя и значки игрока |
SaveSystem | ISaveSystem | Операции сохранения и загрузки |
Version | string | Строка версии движка MCE |
IMonsterDatabase
Запрашивайте монстров, приёмы, способности, предметы и типы:
IMonsterDatabase db = engine.Database;
// Get a monster by dex number (National Dex; the parameter is a uint)
MonsterEntry flameleon = db.GetMonster(152u);
// Get a monster by name
MonsterEntry sparkbit = db.GetMonster("Sparkbit");
// Get all monsters
IReadOnlyList<MonsterEntry> allMonsters = db.GetAllMonsters();
// Get a move
Move thunderbolt = db.GetMove("Thunderbolt");
// Get all moves
IReadOnlyList<Move> allMoves = db.GetAllMoves();
// Get type effectiveness. Types are ScriptableObjects fetched from the database
// (there is no MonsterType enum), so look them up by name first:
MonsterType electric = db.GetAllTypes().FirstOrDefault(t => t.name == "Electric");
MonsterType water = db.GetAllTypes().FirstOrDefault(t => t.name == "Water");
float effectiveness = db.GetTypeEffectiveness(electric, water);
// Returns 2.0 (super effective)
// Get all types
IReadOnlyList<MonsterType> types = db.GetAllTypes();
// Get total count
int count = db.MonsterCount;
IBattleSystem
Контракт SDK для состояния и событий сражения:
IBattleSystem battle = engine.Battle;
// Is a battle in progress?
if (battle.IsInBattle) { /* ... */ }
// Subscribe to battle events
battle.OnBattleStarted += HandleBattleStarted;
battle.OnBattleEnded += HandleBattleEnded; // bool playerWon
IsInBattle, OnBattleStarted и OnBattleEnded питаются хуками движка (BattleSystemFacade.NotifyBattleStarted / NotifyBattleEnded), которые текущий движок не вызывает, поэтому они остаются неактивными. Наблюдайте за сражениями через лаунчер сражений — см. Паттерн 1 и заметки в IBattleSystem.
IPlayerData
Доступ к текущему состоянию игрока:
IPlayerData player = engine.Player;
// Player's monster team
Roster roster = player.PlayerRoster;
int teamSize = roster.RosterSize;
MonsterInstance firstMonster = roster[0];
// Player's money, as of the last save (the live balance is in the bag)
int money = player.Money;
// The name of the player's CharacterData asset
string name = player.PlayerName;
// Player's badge count
int badges = player.BadgeCount;
ISaveSystem
Контракт SDK для сохранения и загрузки:
ISaveSystem saves = engine.SaveSystem;
saves.Save(1);
saves.Load(1);
bool hasData = saves.HasSaveData(1);
saves.DeleteSave(1);
saves.OnSaved += (slot) => Debug.Log($"Saved to slot {slot}");
saves.OnLoaded += (slot) => Debug.Log($"Loaded from slot {slot}");
В текущем движке engine.SaveSystem не подключён к SavegameManager: Save и Load лишь порождают запросы, которые никто не обрабатывает, а события никогда не срабатывают. Движок сохраняет именованные папки (см. руководство Система сохранений). Чтобы хранить собственные флаги и счётчики вместе с сохранением игрока, используйте игровые переменные в GlobalGameData (см. Паттерн 3).
Внедрение зависимостей
MCE использует Zenject (Extenject) для внедрения зависимостей. Чтобы получить интерфейсы SDK в ваших скриптах, используйте атрибут [Inject]:
using Zenject;
using OpenMon.MCE.SDK;
public class MyCustomFeature : MonoBehaviour
{
// IMonsterCaptureEngine is the only SDK interface bound in DI
// (see SDKInstaller). Reach the subsystems through its properties.
[Inject] private IMonsterCaptureEngine engine;
private IMonsterDatabase database;
private IBattleSystem battle;
private void Awake()
{
// engine is injected before Awake/Start runs
database = engine.Database;
battle = engine.Battle;
}
}
Если вы новичок во внедрении зависимостей, вот простая версия: добавьте [Inject] над закрытым полем IMonsterCaptureEngine, и Zenject заполнит его автоматически. Вызывать GetComponent или FindObjectOfType н е нужно. Поле будет заполнено до запуска Start(), а остальные интерфейсы SDK доступны через него (engine.Database, engine.Battle, engine.Player, engine.SaveSystem).
Если ваш скрипт не является MonoBehaviour, управляемым Zenject, можно получить зависимость вручную:
var engine = ProjectContext.Instance.Container.Resolve<IMonsterCaptureEngine>();
Настраиваемые через Inspector параметры
Многие системы MCE предоставляют настройки через Inspector Unity, не требуя кода:
Настройка через ScriptableObject
| Ассет | Назначение |
|---|---|
MCESettings | Общие настройки игры: шанс встречи по типам (TileEncounterChance), шанс дикого шайни, правило опыта, длина игровых суток, эмоциональные шарики |
BattleConfigurationFile | Боевые настройки для игрока: стиль сражения и ускорение анимации |
BattleLauncher | Сцена сражения, боевая музыка диких сражений и сражений с тренерами и ИИ сражений по умолчанию |
MonsterEntry | Данные вида монстра |
Move | Определения приёмов (по одному конкретному классу на приём) |
WildEncountersSet | Таблицы встреч, связанные из ассета SceneInfo каждой карты |
BattleAI | Стратегии ИИ, объединяемые через Fallback |
Настройка компонентов
Большинство компонентов MCE выводят ключевые настройки в Inspector:
- MCECharacterController / PlayerCharacter: скорость шага в секундах на тайл, отображаемый персонаж или монстр.
- EncounterTile: тип встречи тайла.
- SceneInfo (и его
SceneInfoAsset): название карты, музыка, регион, погода, встречи. - Actor и его подклассы: слоты CommandGraph (при включении, цикл, взаимодействие, по требованию).
События и обратные вызовы
MCE не использует поля UnityEvent в своих компонентах; он вызывает обы чные события и обратные вызовы C#, на которые вы подписываетесь из своих скриптов. Наиболее полезные:
| Где | Событие | Срабатывает, когда |
|---|---|---|
IBattleLauncher | SubscribeToBattleLaunched, SubscribeToBattleToUnload, SubscribeToBattleEnded(Action<BattleResultParameters>) | Сцена сражения запущена, вот-вот выгрузится или сражение завершилось |
IBattleSystem | OnBattleStarted, OnBattleEnded(bool playerWon) | Зарезервировано: фасад SDK вызывает их, когда движок вызывает его хуки (пока не подключено) |
Roster | OnRosterUpdated | Монстры в команде изменились |
QuestManager | OnQuestStarted, OnObjectiveProgressed, OnObjectiveChanged, OnQuestCompleted, OnQuestFailed, OnRewardsGranted | Соответствующее событие квеста |
PlayerEmotes (статический) | Played(string balloonName) | Локальный игрок показывает эмоциональный шарик |
Чтобы запустить собственный C# из графа, напишите пользовательский узел (следующий раздел).
Расширение MCE без исходного кода
Паттерн 1: слушатель событий
Создайте MonoBehaviour, который слушает события MCE и запускает вашу логику. Лаунчер сражений привязан в DI и уведомляет о завершении сражения:
using OpenMon.MCE.Battle;
public class AchievementTracker : MonoBehaviour
{
[Inject] private IBattleLauncher battleLauncher;
private int battlesWon;
private void OnEnable() => battleLauncher.SubscribeToBattleEnded(OnBattleEnded);
private void OnDisable() => battleLauncher.UnsubscribeFromBattleEnded(OnBattleEnded);
private void OnBattleEnded(BattleResultParameters result)
{
if (!result.PlayerWon) return;
battlesWon++;
if (battlesWon >= 100)
UnlockAchievement("Battle Master");
}
}
Паттерн 2: запрос к базе данных
Используйте API базы данных для создания собственных функций:
public class TypeMatchupHelper : MonoBehaviour
{
[Inject] private IMonsterCaptureEngine engine;
private IMonsterDatabase database;
private void Awake()
{
database = engine.Database;
}
public List<MonsterType> GetWeaknesses(MonsterType type)
{
var weaknesses = new List<MonsterType>();
foreach (var attackType in database.GetAllTypes())
{
if (database.GetTypeEffectiveness(attackType, type) > 1f)
weaknesses.Add(attackType);
}
return weaknesses;
}
}
Паттерн 3: интеграция с сохранением
Храните собственные флаги и счётчики в сохранении игрока, записывая их как игровые переменные в GlobalGameData — то же хранилище, что использует CommandGraph. Они сохраняются, загружаются и сбрасываются вместе со всем остальным:
using OpenMon.MCE.Player;
// The marker interface IPlayerDataReceiver is what makes the player's data
// (GlobalGameData, Roster, CharacterData...) injectable into a class.
public class AchievementCounters : MonoBehaviour, IPlayerDataReceiver
{
[Inject] private GlobalGameData globalGameData;
public void CountBattleWon()
{
int won = globalGameData.GetVariable<int>("battlesWon");
globalGameData.SetVariable("battlesWon", won + 1);
}
}
Переменная должна существовать у держателя (определите её в игровых переменных ассета GlobalGameData). См. руководство Система сохранений.
Паттерн 4: пользовательский узел CommandGraph
Чтобы запускать собственный C# из визуального скриптинга, напишите узел. Узел — это небольшой класс [Serializable] в вашей собственной сборке, наследующий SingleExecutionPathCommandNode; редактор перечисляет его в меню Create Command графа под последним сегментом его пространства имён:
using System;
using System.Collections;
using OpenMon.MCE.Actors.CommandGraph;
namespace MyGame.Events
{
[Serializable]
public class AwardAchievement : SingleExecutionPathCommandNode
{
[UnityEngine.SerializeField] private string AchievementId;
protected override IEnumerator Run(CommandParameterData parameterData,
Action<CommandParameterData> callback)
{
MyAchievements.Unlock(AchievementId);
yield break;
}
}
}
Узел затем появится как Create Command / Events / AwardAchievement. О контексте (CommandParameterData), который может читать узел, см. API CommandGraph.
Что нельзя сделать без исходного кода
| Ограничение | Обходной путь |
|---|---|
| Изменить саму формулу урона | Добавляйте множители через способности, предметы, статусы и приёмы (ScriptableObject); формула относится к редакциям Source и Studio |
| Добавить новые боевые модули | Модули — компоненты движка (редакции Source и Studio); реагируйте через события IBattleSystem |
| Изменить физику движения | Настройте скорость шага и типы тайлов в TileData |
| Изменить порядок выполнения цикла сражения | Редакции Source и Studio |
| Изменить макеты интерфейса | Переопределите префабы (если они доступны) или наложите свой интерфейс поверх |
Если публичный API кажется вам слишком ограниченным для вашего проекта, рассмотрите переход на редакцию Source. Он включает весь исходный код C# и документацию по архитектуре для глубокой настройки.
Ссылки на сборки
Чтобы ссылаться на типы MCE в своих скриптах, ваше определение сборки (.asmdef) должно ссылаться на:
{
"references": [
"OpenMon.MCE.Runtime"
]
}
Если вы не используете определения сборок, типы MCE доступны глобально через DLL.
Рекомендации
- Зависьте от интерфейсов, а не от реализаций. Используйте
IMonsterCaptureEngine, а не конкретные классы. - Отписы вайтесь от событий. Всегда удаляйте обработчики событий в
OnDisableилиOnDestroy, чтобы избежать утечек памяти. - Не кешируйте устаревшие данные. Запрашивайте SDK каждый раз, когда нужны актуальные данные, особенно для
IPlayerData. - Используйте внедрение Zenject. Избегайте
FindObjectOfTypeи синглтонов для доступа к MCE. - Смотрите справочник API. У интерфейсов SDK есть XML-документация на каждом члене. Ваша IDE покажет подсказки.