MappedParametersSystem (Unity)
Namespace: Vortex.Unity.MappedParametersSystem, Vortex.Unity.MappedParametersSystem.Base.Preset, Vortex.Unity.MappedParametersSystem.Handlers, Vortex.Unity.MappedParametersSystem.Attributes
Сборка: ru.vortex.unity.mappedparameters
Платформа: Unity 2021.3+
Назначение
Unity-слой системы параметрических карт. Предоставляет ScriptableObject-хранилище для визуальной настройки графа параметров в Inspector, драйвер загрузки из Resources, Inspector-атрибуты для выбора параметров и моделей, MonoBehaviour-хранилище и экспорт графа в DOT-формат.
Возможности:
ParametersMapStorage— ScriptableObject-пресет карты параметровMappedParameterPreset/MappedParameterLink— настройка производных параметров и связей в InspectorMappedParametersDriver— загрузка карт из Resources, регистрация вLoaderMappedModelStorage— абстрактный MonoBehaviour для хранения ссылки наIMappedModel[MappedParameter]/[MappedModel]— Inspector-атрибуты с dropdown-выбором- Валидация: уникальность имён, существование родителей, обнаружение циклов
- Clipboard: JSON export/import карты параметров
- DOT-экспорт графа для визуализации в Graphviz
Вне ответственности:
- Модели данных (
IMappedModel), шина (ParameterMaps) — Core - Интерфейсы
IParameterMap,IParameterLink,ParameterLinkCostLogic— Core - Интерпретация стоимости — прикладной уровень
Зависимости
| Зависимость | Назначение |
|---|---|
Vortex.Core.MappedParametersSystem |
ParameterMaps, ParametersMap, GenericParameter, IMappedModel, IParameterMap, IParameterLink |
Vortex.Core.System |
Singleton<T>, IDataStorage |
Vortex.Core.LoaderSystem |
Loader.Register() для IProcess |
Vortex.Core.Extensions |
StringExtensions, DictionaryExt |
Vortex.Unity.EditorTools |
[ClassLabel] для отображения в коллекциях |
Vortex.Unity.FileSystem |
File.CreateFolders() (Editor) |
Vortex.Unity.Extensions |
OdinDropdownTool (Editor) |
| Odin Inspector | [ValueDropdown], [HideReferenceObjectPicker], [InfoBox], OdinAttributeDrawer |
| UniTask | UniTask, UniTask.Yield() |
Архитектура
MappedParametersDriver : Singleton, IDriverMappedParameters, IProcess (partial)
├── Init() → OnInit.Fire()
├── SetIndex(Dictionary) → _indexMaps
├── RunAsync() → Resources.LoadAll<ParametersMapStorage>
│ └── GetMap(storage) → ParametersMap
├── WaitingFor() → null ← нет зависимостей загрузки
├── [RuntimeInitializeOnLoadMethod] Register()
└── [InitializeOnLoadMethod] EditorRegister() ← #if UNITY_EDITOR
ParametersMapStorage : ScriptableObject (partial)
├── guid: string ← [ValueDropdown] из IMappedModel типов
├── baseParams: string[] ← базовые параметры
├── mappedParams: MappedParameterPreset[] ← [SerializeReference] производные
├── Editor: Sort(), GetParamsNames(), ReloadMaps()
├── ErrorCheck: CheckErrors(), SearchTop() (цикл)
└── Clipboard: CopyToClipboardAsJson(), LoadFromJson()
MappedParameterPreset : IParameterMap [Serializable, ClassLabel]
├── name: string
├── parents: MappedParameterLink[] ← [SerializeReference]
├── costLogic: ParameterLinkCostLogic ← [HideIf] при ≤1 родителе
├── Cost: int (свойство, 0)
└── Editor: EditorInit(map), Sort(), GetFoldoutName()
MappedParameterLink : IParameterLink [Serializable]
├── parent: string ← [ValueDropdown] из параметров карты
├── cost: int ← [Min(1)]
└── Editor: EditorInit(map, owner), GetParentVariants()
MappedModelStorage : MonoBehaviour, IDataStorage (abstract)
├── _data: IMappedModel
├── GetData<T>() → _data as T ← lazy Init()
├── OnUpdateLink: Action (abstract)
└── Init() (abstract)
Загрузка карт
MappedParametersDriver реализует IProcess и регистрируется в Loader. При RunAsync:
Resources.LoadAll<ParametersMapStorage>("")— загрузка всех пресетов- Для каждого пресета
GetMap()конвертируетbaseParams[]+mappedParams[]вIParameterMap[] - Базовые параметры оборачиваются в
MappedParameterPreset(name)(без родителей) - Результат помещается в
_indexMaps(словарь отParameterMaps)
WaitingFor() возвращает null — нет зависимостей от других процессов.
Inspector-интеграция
guid—[ValueDropdown]из всех типов, реализующихIMappedModel(через Reflection по всем сборкам)baseParams— строковый массив,[InfoBox]при пустых значенияхmappedParams—[SerializeReference], каждый элемент —MappedParameterPresetс[ClassLabel("$GetFoldoutName")]parentвMappedParameterLink—[ValueDropdown]из всех параметров карты (исключая владельца)costLogic— отображается только при >1 родителе ([HideIf])- Кнопка
Sort— сортировка производных параметров по родителям, затем по имени
Валидация (Editor)
При изменении списков (OnListChanged) выполняется CheckErrors():
- Проверка уникальности имён базовых и производных параметров (дубликаты переименовываются:
Name→Name_1) - Проверка существования родителей (несуществующие обнуляются)
- Обнаружение циклов (
SearchTop) — рекурсивный обход по родителям; циклический указатель обнуляется - Флаг
Error— пустые имена или пустые родители → красный[InfoBox]
Clipboard (Editor)
CopyToClipboardAsJson()— сериализуетbaseParams+mappedParamsв JSON через DTO, копирует в буфер обменаLoadFromJson()— десериализует из буфера, восстанавливаетMappedParameterPreset[]+MappedParameterLink[], запускает валидацию
Контракт
Вход
ParametersMapStorageсоздаётся автоматически (EditorRegister) вResources/MapsConfig/при отсутствии —[CreateAssetMenu]отсутствуетguidуказывает наFullNameтипаIMappedModel- Базовые и производные параметры настраиваются в Inspector
Выход
- При загрузке драйвер заполняет
_indexMapsвParameterMaps - Runtime-доступ через
ParameterMaps.GetModel<T>(),GetParameters<T>(),InitMap()
Inspector-атрибуты
| Атрибут | Назначение |
|---|---|
[MappedParameter(typeof(T))] |
Dropdown-выбор параметра из карты типа T (Odin drawer) |
[MappedModel] |
Dropdown-выбор типа модели из всех ParametersMapStorage (Odin drawer) |
Оба drawer'а поддерживают кнопку Find — навигация к ParametersMapStorage ассету.
Ограничения
| Ограничение | Причина |
|---|---|
| Загрузка только из Resources | Resources.LoadAll<ParametersMapStorage> |
| Odin Inspector обязателен | [ValueDropdown], OdinAttributeDrawer |
WaitingFor() → null |
Нет зависимостей от других процессов |
Cost на MappedParameterPreset — всегда 0 |
Стоимость хранится в MappedParameterLink, а не в самом параметре |
| Editor-валидация при каждом изменении | Рекурсивный SearchTop для обнаружения циклов |
Использование
Создание карты параметров
- Открыть
ParametersMapStorage— ассет авто-создаётсяEditorRegisterвResources/MapsConfig/ - В
guidвыбрать тип модели (IMappedModel) из dropdown - Добавить базовые параметры (
baseParams) — строковые имена - Добавить производные параметры (
mappedParams) — имя, родители с стоимостями,CostLogicпри >1 родителе - Кнопка
Sort— упорядочить по зависимостям
MonoBehaviour-хранилище
public class CharacterStatsStorage : MappedModelStorage
{
public override event Action OnUpdateLink;
protected override void Init()
{
_data = ParameterMaps.GetModel<CharacterStats>();
_data.OnUpdate += () => OnUpdateLink?.Invoke();
}
}
// Использование
var storage = GetComponent<CharacterStatsStorage>();
var stats = storage.GetData<CharacterStats>();
Inspector-атрибуты
public class SkillButton : MonoBehaviour
{
[MappedParameter(typeof(CharacterStats))]
public string targetParameter;
[MappedModel]
public string modelType;
}
Clipboard
- Inspector → кнопка
To Clipboard— JSON в буфер обмена - Inspector → кнопка
From Clipboard— загрузка из буфера с валидацией
Редакторные инструменты
Экспорт графа в DOT
Menu: Tools > Vortex > Debug > Export Mapped Parameters into Graph
Экспортирует каждую ParametersMapStorage в файл .dot (Graphviz). Базовые параметры выделены цветом #b3e5fc. Связи помечены стоимостью. Визуализация: Graphviz Online.
Граничные случаи
| Ситуация | Поведение |
|---|---|
| Дублирующееся имя параметра | Автопереименование Name → Name_1, лог ошибки |
| Родитель не существует в карте | Обнуляется, лог ошибки |
| Циклическая зависимость | Циклический указатель обнуляется, лог ошибки |
Пустой буфер обмена при LoadFromJson |
Предупреждение, no-op |
| Невалидный JSON в буфере | Лог ошибки, состояние не изменено |
Нет ParametersMapStorage в Resources |
Предупреждение при Editor-загрузке, пустой _indexMaps |
MappedParameterPreset с 0 родителями |
Допустимо — фактически базовый параметр в списке производных |
[MappedParameter] с абстрактным/интерфейсным типом |
PresetType = null, красная подсветка |
cost < 1 в MappedParameterLink |
Ограничен [Min(1)] в Inspector |