Files

106 lines
5.6 KiB
Markdown

---
id: data
title: Ассеты данных
---
# Ассеты данных
Ассет данных хранит числа и ссылки, которые настраивают игру без кода: характеристики врагов, веса добычи, настройки уровней.
## Объявление типа
Зарегистрируйте структуру Go как тип данных в нативном модуле:
```go
package native
import (
"aego/core/mathx"
"aego/sdk"
)
type EnemyStats struct {
Speed float32 `aego:"speed,min=0,max=10"`
Cooldown float32 `aego:"cooldown,min=0,max=5"`
Damage int64 `aego:"damage,min=0"`
Tint mathx.Color `aego:"tint"`
}
func registerData(r *sdk.Registry) {
sdk.DataType[EnemyStats](r, sdk.Name("mygame.EnemyStats"))
sdk.Live[EnemyStats](r, "speed")
}
```
Поля используют те же теги и подсказки, что и поля компонентов. Короткие имена типов (`EnemyStats`) должны быть уникальны во всех модулях, потому что скрипты называют типы данных по ним.
## Ассеты и базы
`.aedata` хранит одну запись:
```
data version=1 type="mygame.EnemyStats" {
speed=5
}
```
Запись начинается со значений типа по умолчанию, копирует свою базу, если она есть, и применяет собственные поля. Записываются только поля, которые отличаются от базы. Для наследования добавьте атрибут `base` с настоящим AssetID другой записи: многоточие или путь к файлу не являются допустимой ссылкой. База должна быть того же типа; цепочка, которая возвращается к самой себе или глубже 16, — ошибка.
В редакторе выберите ассет `.aedata`, чтобы редактировать его в Инспекторе. Поля, которые задаёт ассет, отмечены слева; щёлкните такое поле правой кнопкой, чтобы вернуть его к базе. «Сохранить» записывает файл и заново импортирует его.
## Таблицы
`.aetable` хранит строки одного типа, у каждой уникальный id. Дважды щёлкните таблицу, чтобы открыть редактор таблиц. Он сортирует по столбцу (щёлкните его заголовок), фильтрует строки, редактирует ячейки на месте и применяет правку ко всем выбранным строкам, если редактируемая строка тоже выбрана. «Экспорт CSV» записывает `<table>.csv` рядом с таблицей; «Импорт CSV» читает его обратно. Столбцы — это id и каждое поле типа bool, число, строка, перечисление и ассет.
## Скрипты
```
@export
var Stats AssetRef<EnemyStats>
@export
var Loot TableRef<LootEntry>
speed := Stats.Speed
copy := Stats.Copy()
if Loot.Has("goblin") {
entry := Loot.Row("goblin")
}
n := Loot.Len()
```
Поля читаются через ссылку, присваивать им нельзя. `Copy()` возвращает структуру, которой владеет скрипт. Пустая ссылка или отсутствующая строка останавливает скрипт с AES6004. Поля, у типа Go которых нет формы в скриптах, например строки и списки, скриптам не видны.
## Go
```go
package native
import "aego/sdk"
type EnemyStats struct {
Speed float32 `aego:"speed,min=0,max=10"`
}
type Enemy struct {
Stats sdk.DataRef[EnemyStats] `aego:"stats"`
}
func speedOf(ctx *sdk.Context, e *Enemy) float32 {
stats, err := sdk.Data(ctx, e.Stats)
if err != nil {
return 0
}
return stats.Speed
}
```
Поля `sdk.DataRef[T]` и `sdk.TableRef[T]` в компонентах показываются в Инспекторе как выбор ассета, и их можно передавать в скрипты и получать из них.
## Настройка на лету
Пока игра идёт, поля неизменяемы, кроме отмеченных `sdk.Live`. Во время игры Инспектор позволяет менять живые поля ассета данных; изменение сразу применяется к идущей игре и к каждому ассету, основанному на этом, который сам не задаёт это поле. Когда игра останавливается, редактор спрашивает, сохранить ли изменения в ассетах. Таблицы и неживые поля во время игры доступны только для чтения.
## Проверка
`aego check`, панель «Проблемы» и запуск игры сообщают об ассетах данных, которые не разбираются, называют неизвестный тип, имеют сломанную базу, значения вне диапазона своего поля или ссылки на отсутствующие ассеты.