You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository was archived by the owner on Aug 15, 2024. It is now read-only.
Copy file name to clipboardExpand all lines: Packages/com.nuclearband.sodatabase/Documentation/Documentation.ru.md
+87-17Lines changed: 87 additions & 17 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -5,10 +5,10 @@
5
5
Для хранения таких данных существует много способов - кто-то хранит их в таблицах, в xml или json файлах, которые редактируют собственными инструментами. Unity предоставляет свой способ - Scriptable Objects (SO), которые мне нравится тем, что для их визуального представления не нужно писать свой редактор, легко делать ссылки на ассеты игры и друг на друга, а с появлением Addressables эти данные можно легко и удобно хранить вне игры и обновлять отдельно.
6
6
7
7
В этой статье я хотел бы рассказать о своей библиотеке SODatabase, с помощью которой можно удобно создавать, редактировать и использовать в игре (редактировать и сериализовать) scriptable objects.
8
-
8
+
<cut />
9
9
### Создание и редактирование SO
10
10
11
-
Создание и редактирование SOшек я веду в отдельном окне, которое чем-то похоже на окно проекта с инспектором - слева находится дерево папок (папка, в которой находятся все SOшки - группа в addressables), а справа - инспектор выделенной SOшки.
11
+
Создание и редактирование SOшек я веду в отдельном окне, которое чем-то похоже на окна проекта с инспектором - слева находится дерево папок (папка, в которой находятся все SOшки - группа в addressables), а справа - инспектор выделенной SOшки.
В игре обычно нужно либо получить какую-то конкретную модель, например, SO со списком настроек какого-либо окна, либо набор моделей из папки - например, список айтемов, где модель каждого айтема представляет собой отдельный SO.
27
+
В рантайме обычно нужно либо получить какую-то конкретную модель, например, SO со списком настроек какого-либо окна, либо набор моделей из папки - например, список айтемов, где модель каждого айтема представляет собой отдельный SO.
28
28
Для этого в static классе SODatabase есть два основных метода, которые возвращают либо весь список моделей из нужной папки, либо конкретную модель из папки с определённым именем.
29
29
30
30
```csharp
@@ -33,8 +33,7 @@ public static T GetModel<T>(string path) where T : DataNode
Уточню, что один раз в начале игры перед запросом моделей SODatabase нужно проинициализировать, чтобы обновились данные из Addressables.
36
+
Уточню, что один раз в начале игры перед запросом моделей SODatabase нужно проинициализировать, чтобы обновились и прогрузились данные из Addressables.
и все его *JsonProperty* сериализуются в файл save.txt при сохранении игры. Соответственно при инициализации SODatabase кроме запроса данных об изменении addressables происходит *JsonConvert.PopulateObject* для каждой динамической модели из SODatabase, используя данные из этого файла.
50
+
и все его *JsonProperty* сериализуются в файл save.txt при сохранении игры. Соответственно при инициализации *SODatabase* кроме запроса данных об изменении addressables происходит *JsonConvert.PopulateObject* для каждой динамической модели из *SODatabase*, используя данные из этого файла.
52
51
53
-
Для того, чтобы это работало гладко, я сериализую ссылки на SO (которые могут являтся динамическими полями, помеченными как JSONProperty) в строку-путь, и потом десериализую обратно в ссылки на SO при загрузке. Есть ограничение - данные на игровые ассеты динамическими быть не могут. Но это не фундаментальное ограничение, просто у меня ещё не было случая, когда такие динамические данные потребовались бы, поэтому я не реализовывал специальную сериализацию для таких данных.
52
+
Для того, чтобы это работало гладко, я сериализую ссылки на SO (которые могут являтся динамическими полями, помеченными как JsonProperty) в строку-путь, и потом десериализую обратно в ссылки на SO при загрузке. Есть ограничение - данные на игровые ассеты динамическими быть не могут. Но это не фундаментальное ограничение, просто у меня ещё не было случая, когда такие динамические данные потребовались бы, поэтому я не реализовывал специальную сериализацию для таких данных.
54
53
55
54
### Примеры
56
-
В рпг для хранения информации об игроке я прямо создаю *PlayerSO*, в котором одни только динамические поля - имя, количество экспы игрока, кристаллов и так далее. Точно также для инвентаря игрока я создаю *PlayerInventorySO*, где храню список ссылок на айтемы игрока (каждый айтем представляет собой ссылку на статичный SO из SODatabase).
57
-
58
-
Бывают наполовину статические, наполовину динамические данные - например, квесты. Возможно, это не лучший подход, но я прямо в моделях *QuestSO *со статической информацией о квестах (название, описание, цели и т.д.) храню динамическую информацию по прогрессу в этом квесте. Таким образом гейм-дизайнер в одном инспекторе видит всю инфу о текущем состоянии квеста и его описание.
59
-
60
-
61
-
62
-
63
-
64
-
65
55
56
+
В классе-стартере игры инициализация и загрузка данных
57
+
```csharp
58
+
asyncvoidAwake()
59
+
{
60
+
awaitSODatabase.InitAsync(null, null);
61
+
awaitSODatabase.LoadAsync();
62
+
}
63
+
```
64
+
и сохранение стейта при выходе
65
+
```csharp
66
+
privatevoidOnApplicationPause(boolpauseStatus)
67
+
{
68
+
if (pauseStatus)
69
+
SODatabase.Save();
70
+
}
71
+
72
+
privatevoidOnApplicationQuit()
73
+
{
74
+
SODatabase.Save();
75
+
}
76
+
```
66
77
78
+
В рпг для хранения информации об игроке я прямо создаю *PlayerSO*, в котором одни только динамические поля - имя, количество экспы игрока, кристаллов и так далее. Также хорошей практикой по-моему является создание статической строки с путём, по которому я сохраняю данную модель в SODatabase, чтобы потом обращаться к ней в рантайме.
79
+
```csharp
80
+
publicclassPlayerSO : DataNode
81
+
{
82
+
publicstaticstringPath=>"PlayerInfo/Player";
67
83
84
+
[JsonProperty]
85
+
publicstringTitle=string.Empty;
68
86
87
+
[JsonProperty]
88
+
publicintExperience;
89
+
}
90
+
```
91
+
92
+
Точно также для инвентаря игрока я создаю *PlayerInventorySO*, где храню список ссылок на айтемы игрока (каждый айтем представляет собой ссылку на статичный SO из SODatabase).
Бывают наполовину статические, наполовину динамические данные - например, квесты. Возможно, это не лучший подход, но я прямо в моделях *QuestSO* со статической информацией о квестах (название, описание, цели и т.д.) храню динамическую информацию по прогрессу в этом квесте. Таким образом гейм-дизайнер в одном инспекторе видит всю инфу о текущем состоянии квеста и его описание.
В продакшене несколько лет использовался прообраз этой библиотеки - в ней аналогичное окно-проводник для создания/редактирования моделей, которые содержали статичные и динамические данные, но все эти модели не использовали SO, а были целиком в json. Из-за этого для каждой модели приходилось писать свой эдитор вручную, ссылки моделей друг на друга и игровые ассеты(спрайты и т.д.) делались довольно неудобными способами. Переход на SO совершён в прошлом году, и пока всего одна игра с SODatabase ушла в релиз, но в ней не использовались Addressables.
72
139
140
+
На addressables я перешёл совсем недавно для использования в текущем проекте (на разработку которой [я ищу в команду второго программиста](https://gamedev.ru/projects/forum/?id=254030) в партнёры). В данный момент идёт активное допиливание этой библиотеки под нужды этой игры.
73
141
142
+
Библиотека лежит в открытом доступе на github. Написана с использованием Nullable из c# 8, соответственно требует Unity 2020.1.4 в качестве минимальной версиии.
0 commit comments