Как стать автором
Обновить
8
0
Никита Великовский @velik97

Разработчик Unity

Отправить сообщение

БД это ответ на вопрос где хранить сейвы. А MVC отвечает на вопрос как данные должны быть структурированы в игре, чтобы их было максимально удобно далее сериализовать/десериализовать. Например с помощью NewtonJSON можно одним вызовом сериализовать класс со всем его деревом полей. Поэтому если у вас все данные выделены в отдельную область (Data или Model), то их одним вызовом можно перенести в json и обратно. А если этого нет, то придется каждое поле руками сериализовать. И это не номер пройденного уровня, а весь игровой стейт. Все позиции персонажей и мобов, все абилки, весь инвентарь, все статусы, весь лут на карте, все дерево прогрессии персонажа. А если вам нужно просто номер уровня сохранить, то подойдут внутренние механизмы юнити, типа PlayerPrefs.

И мне еще интересно, вот вы говорите про БД. Вы пробовали писать систему сейвов с использованием БД? Поднимать базу у игрока? Или хостить ее у себя и подключаться к ней от игрового клиента?

И приходилось ли вам вообще писать систему сейвов где есть весь игровой стейт?

Ага, только там все раз в 10 все сложнее. И на мой взгляд все оправданно. Когда стоит задача создать игру с таким масштабом и с такой гибкостью, работая в команде 50+ человек, другого пути я не вижу. И тут даже вопрос не в теории. Попробуйте перевести все SO на монобехи (боюсь соврать, но по моим ощущениям там 100к+), юнити просто колом встанет и все тут) Она итак еле живая была с таким количеством данных.

Ну и как адекватно сохранять такое большое дерево данных со всеми абилками со всеми стейтами игровых сущностей без MVC я не представляю.

Обид конечно нет. Я основывался на своем опыте работы в крупной студии. Если у вас другой опыт, могу понять.

Работать умею, спасибо)
Но хотелось попробовать себя и в преподавании. Спойлер: совмещать работу и преподавание очень сложно.

И маленькая ремарка, это был курс по выбору. Его обязательно пройти, если ты его выбрал, но выбирать его не обязательно.

Я являюсь автором этого курса.

Во-первых, спасибо большое за статью, очень интересно было услышать мнение о курсе от кого-то кроме студентов. Я постараюсь объяснить мой подход при создании архитектуры игры на юнити, который возможно объяснит зачем все делать так сложно.

Я вижу своей задачей создать конструктор для геймдизайнера, в котором он сможет создать собственно игру. Без геймдизайнера мой проект выглядит больше как конструктор, в котором пока еще не во что играть. И пока не увидишь работу геймдизайнера, вся эта сложность и гибкость может показаться излишней. Но когда ему придется настроить 20 юнитов, у которых чуть отличаются абилки, параметры и тд и тп, они будут вам очень благодарны за такую гибкость. Говорю это как человек, который два года проработал над очень крупной РПГ. Мне хотелось подготовить студентов к большим проектам, поэтому я пытался привить им такой подход. Не утверждаю, что у меня это получилось хорошо (первый раз пробовал преподавать), но по крайней мере цель была такая.

1) Мне кажется, что SO гораздо более гибкие для настройки игровых сущностей и не имеют лишних полей (типа Transform), лишних функций префаба, что дает меньше возможности запутаться. Проверено опять же на крупном проекте.

2) Использование static полей. Использование их налево и направо действительно чревато, но если создать одну точку входа в виде Game, то я не вижу особых проблем в этом.

3) MVC. На данном этапе игры это кажется излишним, но на самом деле это задел под сериализацию, мультиплеер и сохранение состояния игры в файл (сейвы проще говоря). В этом случае мы сохраняем/передаем по сети только Data. Это кроме того, что так на мой взгляд код гораздо лучше декомпозируется. Плюсы от этого легче ощутить, работая над большим проектом в команде.

4) Как уже кто-то написал выше, частое использование монобехов ведет к сложностям с отслеживанием зависимостей. Я очень много раз на это натыкался на крупном проекте (особенно в UI). Что-то где-то произошло, а ты не понимаешь почему. А оказывается там в каком-то мелком объекте выставлена криво ссылка. Дебажить это почти нереально. А вот если все из кода, проблема становится сильно проще. Но тут опять же надо ловить грань: что является ответственностью программиста, а что является ответственностью дизайнера. И надо стараться не давать дизайнеру ничего лишнего, потому что они рано или поздно ошибутся, а баг вам искать)

Я понимаю откуда возникает диссонанс от этого проекта. С одной стороны игра выглядит простой, делается в одиночку, но при этом содержит излишнюю гибкость. Я же хотел подготовить студентов к будущим проектам, на которых будет требоваться масштабируемость кодовой базы, возможность разработки в команде, удобство для гейм/левел и прочих дизайнеров. Если бы я готовил студентов к хакатонам, то подход конечно был бы совсем другой.

На встроенных событиях можно построить систему по второму типу (подписка по типу события). Я тут предлагаю другую и на мой взгляд более продвинутую реализацию.

Вариант с массивом объектов я описал для полноты картины. Согласен, что он весьма проблемный и не советую никому к нему прибегать.
Не очень понимаю, как увеличение проекта ведет к проблемам со связностью. Могу лишь сказать, что мы используем такую систему (с различными расширениями) в наших играх (Pathfinder: Kingmaker и Pathfinder: WoTR). Это весьма большие проекты и никаких особых проблем с EventBus мы не испытываем.
Да, в UniRx есть своя система событий и ее можно отнести ко второму типу (подписка по типу события). Я тут представил другой подход.

WeakRef у нас нету, поэтому утечки потенциально возможны. Для борьбы с этим можно придумывать различные тактики. Один из вариантов это использовать паттерн Disposable. То есть можно чуть править метод подписки, чтобы он возвращал IDisposable. Это хорошо сочетается с использованием того же UniRx. Но встроить WeakRef звучит как неплохая идея, спасибо за совет.
Сам уровень в SO хранить не выйдет, так как SO не имеет Transform, соответсвенно не может иметь «детей». Можно хранить в SO информацию об уровне, например двумерный массив int'ов, а потом генерировать уровень из этого массива. По сути SO выступает здесь вместо xml.
Остается вопрос, в чем же преимущество SO перед обычным xml? SO использует внутренние, бинарные (если не изменяет память) протоколы сериализации и десериализации, которые очень хорошо оптимизированы.
Но думается мне, что для таких несложных объектов, как уровни в вашей игре, это не играет большую роль. Поэтому я скорее делюсь еще одним способом, который активно продвигает Unity, а не советую вам что-то поменять.
Но все же один вопрос у меня остается, зачем вы создаете префабы? Почему бы не хранить в asset'ах просто xml файлы, а потом в рантайме генерировать уровни из них?
Недавно слушал лекцию на Unity MeetUp в Москве, как раз по теме сериализации данных в Unity. Так вот, там рассказывали про ScriptableObject (далее SO). SO это что-то вроде Monobehaviour, только без всех callback'ов типа Start и Update и, что самое главное, оно может сохранять изменения, сделанные в игровой сессии после ее завершения, в отличие от Monobehaviour, который сбрасывает все поля после завершения игровой сессии на изначальные. Таким образом при помощи SO можно создать редактор уровней внутри самого Unity без xml.
Вообще SO был как раз разработан для таких решений, а использование Prefab'ов для хранения данных считают неким костылем.

P.S. Если будет желание создать редактор уровней для игрока (чтоб он сам смог создавать свои уровни), одним SO не обойдешься, так как состояние SO можно сохранять только в Ediotr'е.

Информация

В рейтинге
Не участвует
Откуда
Москва, Москва и Московская обл., Россия
Дата рождения
Зарегистрирован
Активность