GameDev Architecture
1.44K subscribers
3 photos
2 files
72 links
Привет! На канале я делюсь своими заметками о том, как игровым компаниям строить правильные, эффективные и красивые решения, в основном на C#.

Рекламу не размещаю
Download Telegram
Софтварная разработка многогранна. Давайте немного отвлечемся от типичного веб-девелопмента и поговорим об испытаниях при разработке игр.

Я люблю Git, и предпочитаю использовать именно его. Но кодобаза игровых проектов очень большая. Не столько из-за кода, сколько из-за различных игровых ассетов (текстуры, аудио и т.д.). Проблема Git в том, что он хранит ВСЁ в локальной копии. А это значит, что он будет хранить и все версии ваших больших бинарных файлов.

Например, на одном из проектов размер всех файлов репозитория игры был 60+ Гб (исключая файлы истории). Теперь представьте размер репозитория, который должен хранить все версии на машине.

Эта проблема останавливала от перехода на Git и приходилось пользовать SVN. Ведь нужно было иметь и полную историю для кода, и все ассеты под рукой. Поэтому --depth флаг был не вариант.

Для новых проектов можно структурировать кодобазу таким образом, чтобы ассеты были в отдельном репозитории (сабмодуль), но вот переезд существующих репозиториев — большая проблема.

И вот теперь, Microsoft (опять удивляет!) объединился с Github чтобы внедрить поддержку GVFS [ http://www.gvfs.io/ ]. GVFS, как раз, решает проблему больших репозиториев. Ведь в Microsoft столкнулись ровно с тем же испытанием, но на кодобазе Windows.

Надеюсь, что теперь использовать Git при разработке игр станет намного удобнее и предпочтительнее.
Все мы время от времени сталкиваемся с эфемерными багами, которые больше похожи на магию. Их сложно поймать или даже представить.

Однажды я потратил целую неделю на поиск бага, когда мобильное приложение внезапно начинало жутко тупить даже в idle состоянии. Баг оказался в стороннем компоненте, который в случае потери сетевого соединения начинал спавнить кучу потоков!

Но есть случаи и похардкорнее. Забавный случай от инженера из Quora: https://hackernoon.com/solving-the-most-interesting-bug-of-my-career-in-15-steps-1a1ccd337c35

Главное методичность и упорство :)
Несмотря на то, что есть централизованные ресурсы, где люди пишут технические статьи, персональные блоги разработчиков бывают намного полезнее и интереснее. Но их бывает не так просто найти. Поэтому я периодически буду публиковать подборки с интересными блогами.

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

Поехали:

- https://engineering.riotgames.com/ — блог инженерной команды Riot Games (не знаете кто это? Разработчики League of Legends). Обзоры архитектур, конкретных технических решений и других вкусностей!
- http://highscalability.com/ — ресурс с кучей подборок и статей на тему масштабирования приложений
- http://horicky.blogspot.com — блог дата сайнтиста Ricky Ho с большим количеством тематических статей, написанных понятным языком
- http://tutorials.jenkov.com/software-architecture/index.html — неплохая подборка статей с кратким обзором основных архитектур и подходов в программировании
Вот уже много лет всеми правдами и неправдами программисты борятся с проблемами, связанными с null значениями. Tony Hoare назвал изобретение null reference для языка ALGOL W — "The Billion Dollar Mistake":

https://www.infoq.com/presentations/Null-References-The-Billion-Dollar-Mistake-Tony-Hoare.

И если в языках со сборщиком мусора это грозит всего лишь эксепшеном, то в с++ проблема может повлечь undefined behaviour (http://en.cppreference.com/w/cpp/language/ub) — штука, сулящая много часов безудержного веселья.

Некоторые изобретают свои костыли:

http://www.bfilipek.com/2017/10/notnull.html

Вопрос, зачем? Ведь в C++ есть reference, который не может быть null. Это и есть средство, позволяющее программисту выразить его нежелание возиться с null. Другой способ — Optional типы (std::optional в с++, Optional в Java).

В любом случае, стандарт языка имеет все необходимое для решения проблемы, причем compile-time. Так зачем же люди изобретают свои велосипеды?

Другое дело, когда в стандарте языка нет таких выразительных средств. Что делать? Приходится рассчитывать на средства статического анализа кода. Ребята из JetBrains любят такие штуки.

https://www.jetbrains.com/help/idea/nullable-and-notnull-annotations.html
https://www.jetbrains.com/help/resharper/Code_Analysis__Annotations_in_Source_Code.html

Но как по мне — это тоже так себе решение. Решение должно быть поддержано на уровне языка. Я уже говорил о том, что дизайн языка C# ведется в открытом формате, в репозитории github: https://teleg.eu/poisonous_johns_lair/3. И это поистине потрясающее решение. Ребята действительно слушают коммьюнити. Вот, например, предложение по борьбе с Null:

https://github.com/dotnet/csharplang/blob/master/proposals/nullable-reference-types.md — proposal
https://github.com/dotnet/csharplang/issues/36 — discussion

Программисты — ленивые. Каждый раз проверять на null — большой геморрой. Так пусть это делает компилятор. Пусть он бьет нас по рукам за нашу лень 😃.

А как же быть тем, кто пишет на интерпретируемых языках или языках с динамической типизацией? Я забыл упомянуть о еще одном решении: монада Maybe — https://curiosity-driven.org/monads-in-javascript#maybe . Конечно, имплементации этого подхода не всегда удобны, но все же это может быть неплохим решением.
Привет и спрошедшими праздниками!
Надеюсь всем удалось хорошенько отдохнуть.

Наткнулся на такую забавную статью о буднях разработки Walking Robots, знаете такую игрушку?

https://habrahabr.ru/company/pixonic/blog/346374/

Честно говоря, я и сам приверженец подхода "сделай сначала рабочее решение, а потом сделай его хорошо". Я считаю, что если к рефакторингу подоходить правильно, да и при разработке соблюдать хорошие практики, то это не должно быть проблемой.

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

В игровой индустрии немного другая специфика. Если игрушка не взлетела — ее выкидывают и делают другую. Более того, даже на этапе прототипа ее могут по 10 раз переделывать так, что приходится начинать все с нуля.

Посему, "лучшее — враг хорошего". Перфекционизм — это болезнь. Хотя она и имеет положительное влияние, нужно уметь вовремя остановиться. И это важный скилл! Этот скилл является великим преимуществом.

Часто я нахожу себя со свербящим чувством внутри, толкающим меня исправить этот ужасный код. Но, черт возьми, стоит ли тратить на это время, если этот кусок кода выполняется очень редко? Что это даст?

Рефакторинг — это тоже отдельный скилл. Причем он требует гораздо больше опыта. И другого скилла - понимание чужого кода. Часто замечал за коллегами негативную реакцию и нежелание разбираться, когда приходится читать чужой код. А это выливалось в бездумное изобретение своих велосипедов, потому что "я не понимаю как оно работает". А посему и появление кучи тех же самых багов, которые были починены в предыдущей версии.

Люди боятся рефакторить. А без рефакторинга проект обречен. Команде необходимы люди, которые смогут заниматься этим нелегким делом.

Рефакторинг должен быть частью цикла разработки. Он должен происходить каждую итерацию. А все задачи, связанные с техническим долгом, необходимо фиксировать в трекере, оценивать риски, и наблюдать, чтобы этот пул не разрастался.

Важно понимать не только "как" рефакторить, но и зачем, когда и где.

От себя могу порекомендовать прекрасную книгу от моего любимого Мартина Фаулера и других крутых перцев:

https://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672
Забавная статья о том, как эволюционировал DevOps, на примере собственного опыта автора.

Автор описывает как менялись процессы при разработке веб сайтов:

- Редактирование сорцов в Dreamweaver и заливание их на ко-локейшн сервер по FTP
- Версионирование кода, созданием отдельных папок под каждую версию
- Конфигурация и поддержка серверов собственными силами
- Бесонная ночь из-за сгоревшего на сервере блока питания
- Появление виртуальных машин
- И, наконец, появление облачных PaaS и инструментов автоматизации CI/CD процессов

Автор показывает перспективу того, насколько все стало легче с использованием Azure AppService и Visual Studio Team Services,
когда по коммиту в Git репозиторий происходит автоматическая сборка и деплоймент на тестовую среду, а по одному клику, без
даунтайма это можно шлепнуть в лайв. Как сервис автоматически реагирует на рост и спад нагрузок, скалируя инстансы серверов.

Работать над бэкэндом становится проще в контексте Operational вещей.

С такими сервисами как Azure AppService и Azure Functions даже инди разработчикам под силу за 5 минут развернуть сервер.

https://medium.freecodecamp.org/the-life-changing-wonder-of-continuous-integration-and-deployment-97f833505eea
Статья неоднозначная, но есть о чем задуматься.

Вредоносный код в OSS продукте? Боже упаси!

https://habrahabr.ru/company/ruvds/blog/346442/

Количество параноидальных разработчиков с синдромом "not invented here" может возрасти.

С другой стороны, ну нельзя же все самому писать.

Для контраста другая статья, о когда не стоит писать все самому, и чем это может помочь.

https://medium.freecodecamp.org/when-writing-code-is-a-waste-of-time-6602af8cb759
Войти в индустрию геймдева может быть сложно. А не выпасть из нее — еще сложнее =). После входа легче не становится, и вошедший может испытывать великое давление.

На твиттере есть забавная ветка обсуждения, где известные игровые разработчики, чтобы дать понять, что ВСЕ делают ошибки, рассказывают о своих фейлах при разработке ААА игр:

https://twitter.com/Danim8tion/status/950465438806257664

Несколько хайлайтов от меня:

- First code I ever submitted (a simple if-statement) I somehow broke reloading of all weapons in Battlefield: Bad Company

- I leaked a new character for Evolve in Twitch chat via a copy pasta fail.

- The opening/closing valve animation in first Mirror’s Edge is turning the valve the wrong way. I didn’t know which way you turn to open/close a valve so I think I just guessed.

- In GoW 3 Kratos has a magic that summons Spartan shields and spears. I did not realize I animated all the shields upside down until of after the game shipped! To this day I told everyone I intended it because they where exiled Spartans showing defiance! Don't tell anyone

- As a junior TA, While trying to get everyone’s Perforce workspace root mapped to the same location in everyone’s hard drives I accidentally deleted like... a month or two of animation that hadn’t been checked in.
Система матчмейкинга — типичный компонент для многопользовательских игр. Поэтому давно уже существуют решения, предоставляющие весь необходимый функционал, чтобы собрать игроков в "комнаты".

Такие решения предлагают многие платформы: Steam, Microsoft, Sony, Playfab и т.д.

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

О них и рассказывается в этой статье:

http://joostdevblog.blogspot.ru/2017/10/working-with-generic-room-based.html
В геймдеве #OpenSource как-то не очень сильно почитается. Но посмотреть все же есть на что.
Лист #OSS крутотенюшек для Unity и игровой разработки в целом:

- UniRx — мой любимые расширения для реактивного программирования, специально для Unity
- Nakama — впечатляющий фреймворк для разработки игровых серверов. Вполне себе альтернатива фотону: авторизация юзеров, мультиплеер (реалтайм, пошаговый, пассивный), чат, социальные фичи (друзья и т.д.), сохранение состояния, матчмейкинг, дашборды и метрики. Одна странность — использует cockroachdb для хранения данных
- Crystal AI - быстрый и расширяемый фреймворк для utility based AI. Кстати untility based AI далеко не самый популярный подход, но он точно заслуживает внимания:
+ статья
+ видео с GDC
- Prime31 — команда, у которой много OpenSource проектов, среди которых
+ Твинер
+ Обджект пул
+ 2D Character Controller
+ Библиотека для поддержки gestures
+ Система сообщений (замена SendMessage в Unity)
+ Библиотека для поддержки переходов между сценами
+ и многое др.
- Fungus — фреймворк для очень простой (даже визуальной) разработки игр типа графических новел, hidden object и других похожих
- StrangeIoC — Dependency Injection фреймворк, разработанный специально для Unity
Масштабируемый реалтайм сервер на .Net Core Orleans, WebSockets и серверном Redux.

После этой статьи есть о чем задуматься. Например, использование Redux на серверной стороне. Идея великолепна. Больше всего мне нравится "time-travel" по стейту. Это незаменимо при отладке проблем бизнес-логики! Вместо многочасового копания логов, можно посмотреть цепочку событий и историю состояний, которые привели к проблеме.

Многие разработчики не слышали о модели акторов. Но в игровой разработке этой модели можно найти много применений.

Больше про преимущества модели в статье на хабре, вот несколько, упомянутых в ней:

- простота разработки. Использование асинхронного обмена сообщениями сильно упрощает жизнь когда приходится иметь дело с concurrent computing;
- масштабирование. Модель Акторов позволяет создавать огромное количество акторов, каждый из которых отвечает за свою частную задачу. Принцип shared nothing и асинхронный обмен сообщениями позволяет строить распределенные приложения, горизонтально масштабируясь по мере надобности;
- отказоустойчивость. Сбой одного актора может отлавливаться другими акторами, которые предпринимают соответствующие действия для восстановления ситуации (например, механизм супервизоров из Erlang-а).

Так где оно может пригодится при разработке игр?


- Акторы — это, по сути, конечный автомат (пример Akka.FSM), что является стандартным паттерном для игр
- Большинство действий в игре связано только с одним игроком, так что сервисы типа авторизации, магазина, инвентаря и т.д. могут быть легко представлены в виде акторов. Плюс ко всему вы получаете realtime систему, т.е. можете отгружать все обновления на клиент. Забудьте про REST API и поллинг
- Модель акторов имеет встроенную систему маршрутизации сообщений, с помощью них легко сделать чать для игры, представляя комнаты и пользователей как отдельных акторов. Броадкастинг из коробки :)
- Релтайм ПвП, в очень грубом сравнении, тоже похоже на чат. Юзеры отсылают свой ввод на сервер, сервер его обрабатывает, а потом броадкастит обновления всем в комнате

Хочу хочу хочу! Где взять?

- Для новичков, проще попробовать Project Orleans от Microsoft (использованный в самой первой статье) с системой виртуальных акторов. Система виртуальных акторов на порядок прощей традиционной. Плюс ко всему это позволяет масштабироваться без головной боли
- Традиционным акторным фреймворком считается Akka, оригинально разработанный на Scala. Официально есть реализации Scala и Java. Но людям, работающим с Unity/C# ближе будет порт Akka.Net.
- Для C++ решения рассмотрены в упомянутой статье с хабры:
+ QP/C++
+ Asynchonous Agents Library от Microsoft
+ C++ Actor Framework
+ SObjectizer
Аналатика в игровой разарботке — визуализация данных

Аналитика позволяет понять как себя ведет пользователь. А иногда и открывает глаза на то "Почему?" он делает именно так, а не иначе.

Она позволяет следить за "здоровьем" игры. DAU, игровой баланс, экономика, ревенью. Все это — ключевые показатели. Если с ними что-то не так, то нужно бить тревогу. Поэтому, важно иметь удобные средства аналитки.

Так же жизненно необходимо визуализировать данные. Многое становится ясным, только если это правильно представить. А с этим пунктом обычно возникают трудности. Свою визуализацию писать лень. Excel пользовать не очень удобно. А деньги платить за софт как то не хочется.

Для себя я открыл БЕСПЛАТНЫЙ инструмент PowerBI Desktop.

Радует, что он прост как пробка. Парой кликов можно собрать красивый интерактивный отчет. Умеет импортировать данные из кучи источников, начиная с простых Excel, CSV, Txt и заканчивая базами данных PostgreSQL/MS SQL.
Может даже парсить данные с любого URL (REST API или обычная HTML страница).

Поэтому можно приконнектить его даже к API всяких third party решений по аналитике. И вместо того чтобы писать свое решение по интеграции всего этого добра, можно просто накидать отчет.

Большие сеты данных (>1GB) он вряд ли потянет, но в остальном справляется хорошо.

На картинке дашборд с разбивкой юзеров по девайсам и geo. Накидал за минуту.

Примеры более продвинутых отчетов можно посмотреть здесь. Мой любимый пример отчета по Game of Thrones.

В ближайшее время планирую опубликовать статью о том, как сделать свой облачный сервис по сбору аналитки для игры. Хотите быть в курсе? Подписывайтесь на канал ;)
Разработка игры — это не только геймплей

Вы взялись за разработку игры своей мечты. Вы закончили работать над геймплеем. И в нее даже можно играть. Ну, что, пора показывать шедевр миру?

Погоди ка! Не так быстро. Давай пройдемся по чек листу.

+ Геймплей — это самая интересная часть для разработчика, но самая ли важная?
- Матчмейкинг — если ваша игра предполагает PvP, то нужен сервис, гарантирующий честный бой
- Защита от читеров — если ваша игра предполагает взаимодействие несколько игроков, то вам по-любому нужна защита от читеров. Железобетонная защита — авторитарный сервер. И если вы этого не учтете на раннем этапе, то вас ждет много часов радости по переносу части геймплея на сервер
- Внутриигровой магазин — если нечего купить, то куда игрок будет тратить деньги?
- Банк — нужно дать пользователю возможность обменять реальные деньги на внутриигровую валюту
- Проверка денежных транзакций — нельзя забывать про читеров, если транзакции не проверять, то читеры подделают их, и поломают вам весь баланс, и вряд ли честные пользователи будут рады этому
- Восстановление покупок — если в игре есть уникальные вещи, которые доступны за микротранзакцию, пользователи обязательно захотят их восстановить после переустановки игры. Если такой возможности нет, то ничего хорошего это вам не сулит
- Интеграция рекламы — да-да, никто не любит рекламу. Но так ли это? На самом деле исследования показывают, что "не-платящие" пользователи, да и платящие тоже, не прочь получить что-нибудь в игре на халяву за просмотр рекламы/видео. А для вас — это еще один способ заработать
- Сохранение прогресса — игроки могут удалять вашу игру. А потом устанавливать заново, соскучившись. Как думаете, хотят ли они начинать все с нуля? А если они хотят продолжить играть на другом устройстве? Хранить прогресс игры на самом девайсе — не самый надежный вариант. А чтобы хранить прогресс на сервере — нужна привязка к какому-либо аккаунту. Вы же не думаете, что в 2018 году кто-то желает входить по логину и паролю? Смотрите интеграцию с соц. сетями ниже.
- Саппорт — если вам будут платить деньги за игру, то наверняка и будут жаловаться в духе "Я заплатил доллар! А тут не работает! Верни деньги или почини!". И если у вас не будет канала связи с разработчиком, то люди могут просто сделать рефанд. Плюс через этот канал могут жаловаться и на читеров, или на несправедливый баланс.
- Логи — все нужно логировать. Если пользователь обращается в суппорт, то круто добавить кнопку "отправить лог", чтобы не верить пользователю на словах. А то многие я любят говорить "Я заплатиль $100500, а деньга не пришель". А на самом деле пользователь забашлял $1, и тот уже потратил на какую-то фигню. Логи и аналитика — важный инструменты для выяснения истинного положения вещей.
- Поддержка разного качества графики — люди играют на устройствах с разной производительностью. Ваша игра должна запускаться и быстро работать на любых устройствах (в разумных пределах, конечно). Причем на топовых устройствах люди ожидают увидеть ВАУ графику. Этот пункт сулит много часов веселья. Оптимизация интерфейса, шейдеров, текстур, уровней, памяти, моделей и т.д.
- Локализация — когда вы делитесь своим шедевром с миром, вы же не думаете, что все знают ваш родной язык? Или даже английский? Если вы хотите завоевать ВЕСЬ мир, то должны поддерживать все основные языки.
- Сбор телеметрии — а что если ты выпустил игру, и она падает на старте, только на тех устройствах, которых у тебя физически нет. Как узнать о критических ошибках, падениях игры, сбоях, ну и просто иметь представление о тех девайсах, на которых люди играют?
- Сбор аналитики — в предыдущем посте я рассказывал уже в кратце. Что если все пользователи застряли на 3 уровне? Может это признак бага? Если пользователи не будут продвигаться дальше, то скорее всего уйдут. А если вы где то разместили рекламу игры, как узнать ее эффективность без аналитики? А какую вещь люди покупают больше всего? Без аналитики вы будете слепы.

Это еще не все!
Продолжение ниже :)
- Система динамической конфигурации — баланс игры — дело тонкое. Его нужно постоянно мониторить и править. Будете ли вы каждый раз обновлять клиент игры, если надо поменять всего один параметр в балансе? Или если необходимо обновить/добавить локализацию?
- Система скачиваемого контента — даже когда разработчик завершил свою работу над игрой, она продолжает жить. Без программных обновлений, игра может развиваться. Новые уровни, новые вещи, новые персонажи и т.д. Пусть работают худождники/моделлеры/геймдизайнеры.
- Интеграция с социальными платформами — игроки — это ваши друзья. Если игра им нравится, они сами будут рассказывать об этом. Очень важно дать им такую возможность. Пусть кричат об этом в соц. сетях и приводят друзей
- Масштабирование игры — может заключаться в нескольких аспектах. Первый — пользователи. Представьте, что фишка с соц. сетями удалась, и к вам повалила куча пользователей. Есть ли у вас сервер? Справится ли ваша инфраструктура с этим? Второй аспект — увеличение объемов самой игры. Количество функций, контент, интерфейс — все растет со временем. И если вы тестировали игру с 10 уровнями, и все было отлично, то велик шанс, что при 100 уровнях все начнет тормозить. Самый простой способ — генерировать контент-заглушки, раздувая тем самым объем игры, и смотреть как она себя ведет.
- Публикация в сторах — если вы планируете поддерживать несколько сторов, то нужно это учитывать. Нужно будет интегрироваться с каждым отдельно. Ведь система микротранзакций и других платформозависимых фич у каждого стора и платформы своя. Нельзя забывать про разные операционные системы. Если вы используете кросс-платформенный движок типа Unity, то часть геморроя с вас снимается. Если нет — то у меня для вас печальные новости. Портирование движка на другую платформу — та еще радость.

Черт возьми! Вот сколько еще работы помимо геймплея!

Это на вскидку те пункты, которые вспомнил. Для новичков — будет полезно иметь полную перспективу. А профессионалы, может, дополнят список, если я что-то забыл.

В дальнейших постах я буду выкладывать ссылки на статьи, которые поясняют как сделать один из пунктов. Часть статей еще предстоит написать.

Хотите быть в курсе? Подписывайтесь на канал ;)

А так, вообще, это напоминание, что не все в игровой разработке про фан.
Считаю прекрасная статья. Особенно про тесты. И если вы думаете, что в геймдеве тесты не применимы, то очень зря.
Двустороннее взаимодействие с сервером в реалтайме

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

Но существуют разные механики, требующие реалтаймого обновления.
Типичный пример — чат. Игры, в которых социальная составляющая сильна,
вряд ли обойдутся без него.

Сделать чат на REST API можно, но зачем? REST API подразумевает синхронную связь, а сама концепция чата подразумевает асинхронность.

Выход прост — использовать транспорт, поддерживающий двустронний асинхронный обмен сообщениями. Для разрабочика на Unity логично использовать C# и на сервере.

SignalR — довольно известная библиотека от #Microsoft. Предполагается ее использовать с ASP.Net.

К сожалению, Unity все еще на .Net Framework 3.5, что не позволяет использовать SignalR. Но есть порт под Unity.

Если вы используете последние версии Unity, то там есть экспериментальная поддержка .Net Framework 4.6. Поэтому можете попробовать запустить и оригинальную версию.

Работа с SignalR довольно проста:


// setup proxy
HubConnection connection = new HubConnection("http://localhost:58438/");
IHubProxy proxy = connection.CreateProxy("TestHub");

// subscribe to event
proxy.Subscribe("ClientPing").Data += data =>
{
JToken data = data[0] as JToken;
Console.WriteLine("Received push from server: [{0}]}", data["message"].ToString());
};

// start connection
connection.Start();


Больше информации — в официальной доке.

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

Туториал учит концепции переиспользования компонентов. Плюс показывает чем полезен паттерн Publisher / Subscriber, используя Unity's Event System

http://telegra.ph/Sozdanie-sistemy-bonusov-v-Unity-02-08
Не одним Unity мы живем =)
Сегодня я хочу пошарить вам #gamedevblog инди разработчика, пишущего 2d игру на Lua/LÖVE.

В блоге описывается процесс создания игры, принципы имплементации игровых механик, вроде дерева навыков и т.п.
Так же есть несколько интересных статей по #AI и #bestpractices. Блог на английском.

https://github.com/SSYGEN/blog

#tutorial #lua #love #gamedevblog #AI #bestpractices #english
Как формат постов удобнее читать?
anonymous poll

Короткий пост в телеграме + ссылка на Telegraph (Instant View) – 56
👍👍👍👍👍👍👍 69%

Лонгпост в телеграме – 15
👍👍 19%

Короткий пост в телеграме + ссылка на лонгрид – 10
👍 12%

👥 81 people voted so far.
The Best Dell Monitor for Your Needs