Как стать автором
Обновить

Комментарии 30

Хотел бы я почитать про архитектуру какой-нибудь популярный игры, например Dota 2.
Что именно вас интересует?
Сразу определимся — а есть что рассказать?
Ну я многое знаю про устройство Source Engine и как оно работает в контексте Dota 2. Если бы вы мне подсказали, какой аспект интересует — я думаю статью бы написал.
Конкретно мне интересно послушать про организацию способностей, что они из себя представляют, как реализованы на уровне исходного кода. Если играли, то наверняка замечали, что их там великое множество, довольно четко прописаны правила их взаимодействия, все прямо скажем непросто. Это «что именно». Но и в целом про основной цикл, распределение ролей по клиенту и серверу и т.д.

P.S. не нужно воспринимать мой довольно резкий вопрос как большинство (минусами в карму), просто не хотел тратить время на пояснения, а в ответ ничего не услышать.
Спасибо, полезная статья.
«машины состояний» (state machines) — это то, что в общепринятой русскоязычной терминологии называется конечными автоматами
Мне показалось, что «машина состояний» будет понятней большему числу читателей, чем «конечный автомат». Не все в институте учились, и не у всех была теория автоматов. Но вы правы, стоит упомянуть в статье про конечный автомат.
>>> «машины состояний» (state machines) — это то, что в общепринятой русскоязычной терминологии называется конечными автоматами

Использование кальки «машина состояний» позволяет избежать смешения с математической абстракцией «конечный автомат». Программистская машина состояний принадлежит к другому классу мощности, нежели математический конечный автомат. В частности, допускает «бесконечное» множество состояний (параметризация состояний), бесконечный алфавит (параметризация событий), наличие состояний у состояний (sic!), зависимость переходов не только от явного входа и текущего состояния, но и от состояния «мира».
нигде нет более менее полной публикации на тему проектирования архитектуры в играх

А как же Game Coding Complete?
Спасибо за ссылку на книгу! Надо будет глянуть, в том числе и другие ее части.
Правильнее было бы сказать, что я не встретил книги или публикации, где собраны воедино описания реализаций типовых игровых механик, таких как:
характеристики объектов;
баффы/дебаффы;
способности/заклинания;
организация процессов экипировки персонажа, изучения навыков, покупки, особенно в клиент-серверных играх;
система диалогов;
система квестов.

Пока что пролистал мельком книгу. Про КОП, FSM, Behavior Tree в ней написано. А вот про перечисленное выше я не увидел. Большинство книг по архитектуре игр обычно ориентированно скорее на создание архитектуры движка, чем самой игры.
нигде нет более менее полной публикации на тему проектирования архитектуры в играх


Да ладно.
Вам тоже спасибо за книгу! Хотя ранее она мне уже попадалась. Вот только времени почитать не нашлось.
Могу сказать только то же, что и в моем комменте выше.
Хорошая статья. Я тоже пришел к аналогичному приему. Но с некоторыми поправками. Использую MVC, где Unity3d view и иногда часть модельной логики (через интерфейсы). Unit — модельный класс, имеющий базовые поля и словарь стратегий, во вью аналогичное решение но с юнити компонентами. А на уровне общения только IAction (для контроллеров) и IEvent для (View или сети).
С XML существует проблема на WinRT. Рекомендую использовать Xml.Linq XElement и тд. Но с ней существует проблема в Web player. Лечится это, через копирование System.Xml.Linq.dll (лучше вытянуть из папки unity) в Plugins и указанием билда только под веб.
Характеристики объектов в игре

Предложение автору. Как я решил подобную проблему. Все Unit имееют стратегии. Не важно что это heath mana и тд. С бафами можно обыграть так.
Код
namespace Engine
{ 
   
    public abstract class UnitStrategyBase 
    {

        public virtual EventHandler Handler { get; set; }

        public virtual Unit CurrentUnit { get; set; }

        public virtual void OnAdd(Unit unit)
        {
            CurrentUnit = unit;
        }
        public virtual void OnRemove(Unit unit)
        {
            CurrentUnit = null;
        }

        public virtual void Send(IEvent @event)
        {
            if (Handler != null)
            {
                Handler.Send(@event);
            }
        }
    }
}



При добавлении стратегии, например баф. Сам баф сохраняет дельту, и обновляет нужные данные. После удаления, по этой самой дельте вернуть изначальное состояние. И так далее. Однажды пробовал обратную связь. Тоже работает, мол Armor например ищет бафы и сам возвращает результат. Но такой подход не очень, когда бафов становится огромное n количество.
Спасибо! Толковое предложение!
Я тоже предполагал, что при добавлении/удалении лучше только 1 операцию сделать (прибавить/отнять), а не все баффы брать для данной характеристики и вычислять. Но т.к. не делал, не был уверен, что получиться избежать перерасчёта при наличии разных операций: умножить, увеличить на заданный процент и т.д.
Про ооп vs коп: у вас в обоих случаях описывается ооп. Когда говорите об ооп подразумеваете наследование, а коп агрегацию. Действительно, обычно лучше агрегироваться, а не наследоваться. Коп — это уровень сборки приложения, когда у компонента есть не только код, но и данные и ui.

Для кругозора можно еще почитать про аспекты (ваши компоненты на них сильно похожи) и мультиагентное программирование.
КОП как бы более продвинутое ООП. ООП. Родственные методологии.

Коп — это уровень сборки приложения, когда у компонента есть не только код, но и данные и ui.
Тут просто одно и то же название используется в разных контекстах. То, о чем вы говорите – скорее модулями правильней называть, а не компонентами.
https://ru.wikipedia.org/wiki/Модульность_(программирование)
Шаблоны игрового программирования.Компонент

Для кругозора можно еще почитать про аспекты (ваши компоненты на них сильно похожи) и мультиагентное программирование.
Полезно конечно будет почитать. Но из того, что я сейчас прочитал про аспекты – не сказал бы, что мои компоненты на них похожи. Я так понял, что если какой-то общий функционал вынести в отдельный метод, и как-то организовать его вызов при выполнении любого метода в любом классе, к которому он привязан, то эта дополнительная привязанная функциональность и будет называться аспектом.
Аспектно-ориентированное программирование на C#
КОП не продвинутое ООП, а надстройка над ним. Согласен с вами по сути изложенного, но не согласен по форме: нельзя противопоставлять ООП и КОП, иначе, прочитав вашу статью, может сложиться впечатление, что ООП — устаревшее зло без права на всплытие.
В вашем примере, кстати, компоненты, отвечающие за урон ближнего боя и урон дальнего боя, вполне логично пронаследовать от одного компонента, отвечающего за урон в принципе.
Согласен, что не нужно пытаться использовать ООП для объектов игрового мира, т.к. они заведомо собираются из различных компонент (начиная от transform и rigitbody, заканчивая контроллерами баффов и собственных действий), но его можно и нужно использовать для реализации аспектов, действительно связанных отношениями родитель-потомок.
Статья не идеальная, что тут сказать. Тема компонентного подхода плоховато раскрыта.

На мой взгляд, выделение компонентов похоже на выделение интерфейсов. Но компоненты помимо описания позволяют еще и реализацию вынести в отдельный класс. В одних случаях стоит базовый класс использовать, в других – интерфейс. Аналогично и с компонентами. Ну и вдобавок, в некоторых случаях для компонентов стоит также выделить интерфейс.

В вашем примере, кстати, компоненты, отвечающие за урон ближнего боя и урон дальнего боя, вполне логично пронаследовать от одного компонента, отвечающего за урон в принципе.
Согласен. Да и упоминал немного в статье, что наследование компонентов – вполне нормально.
Еще, если действительно нужна динамическая динамичность, то можно использовать динамические языки на платформе .net. Позволит проще/чище реализовать нужную динамичность. Не знаю насколько это Юнити поддерживает.

И наоборот, если даже делать универсальное хранилище для характеристик объектов, то апи доступа к ним стоит сделать типизированным (не object GetPropertyByName, а int GetLivesCount).
И наоборот, если даже делать универсальное хранилище для характеристик объектов, то апи доступа к ним стоит сделать типизированным (не object GetPropertyByName, а int GetLivesCount).
Кстати, я делал аналогично для доступа к данным из аниматора в Mecanim. Становиться удобней работать.
public class AnimatorParams
{
	private Animator _animator;

	public float Speed
	{
		get { return _animator.GetFloat("Speed"); }
		set { _animator.SetFloat("Speed", value); }
	}
...
}
по string ключу дорого. Лучше используйте хеш.
 int [animation]key= Animator.StringToHash("Speed");
...
 _animator.SetFloat( [animation]key, speed);
Компонент медиатр это мега ошибка в коп, и каждый человек пытается создать свой класс для удобного доступа. В новой юнити наконец то все такие ссылки пометили как обсолет.
Можно чуточку пояснить Вашу мысль?
Вот и мне непонятно. Не скажете, где говорится, что медиатор или что-то подобное плохо в коп? Мне таким образом стало куда удобней работать, чем в каждом компоненте заводить несколько ссылок на другие компоненты и вызывать getComponent() для получения каждого.

Компоненты какого-то сложного объекта в любом случае как-то должны общаться друг с другом. Поэтому не вижу проблемы добавления класса-посредника для конкретного типа объекта.
В случае посредников для объектов сцены, особенно если их разделять по подсистемам (гуи, звук), тоже не вижу проблем. Объектам сцены все равно как-то потребуется обращаться друг к другу.

Касательно Unity3d. В нем раньше было сделано так, что у компонента были ссылки на кучу других компонентов, которые он не использует, что приводит к ненужной связанности компонентов. И это скорее создавало проблемы разработчикам движка, а не разработчикам, которые пишут на движке.
Ссылок не было, фактически, это были геттеры, каждый вызов которых выполнял запрос через GetComponent(typeof(T)), что было не быстро. Теперь они просто выпилили эти геттеры, что немного почистило апи.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации