Как я кувыркался с ачивками
Каждому разработчику Стим настоятельно рекомендует прикрутить к своей игре ачивки, как будто все уперлись рогом в землю, и никак. А народ вовсе не против, просто никто не объясняет популярно, как внедрить Steamworks SDK в UE4, и как дальше ковыряться в блюпринтах. Можно немного погуглить, много подумать, и наконец, разобраться самостоятельно. Но не каждый программист настолько трудолюбив. Мне не повезло, я гуглил, думал и разбирался. Зато у вас появилась возможность прочитать полезную статью.
Должен признаться, у автора есть свой шкурный интерес. Давайте договоримся так: вы идете по сылке https://store.steampowered.com/app/1786330/The_Pied_Piper_of_Gamelin/?beta=1 и давите кнопку «WISHLIST». Это бесплатно, и ни к чему не обязывает. А я рассказываю коротко и ясно, как мутить ачивки. Заметано?
Итак, в ответ на тычок мышкой, прилетает Steamworks_SDK_152.zip. И что? Куда его распаковывать?? Оказывается, правильную папку надо создавать руками. Оттуда, где лежит любимая UE4, ныряем глубже, и в дебрях Engine\Source\ThirdParty\SteamWorks видим папку Steamv142. Это такая подсказка, как правильно именовать каталог. Создаем рядом Steamv152, и разворачиваем архив туда.
Внутри Steamv152 должна попасть папка SDK, а дальше glmr, publik, tools . . . Ну вы поняли. А еще в папке SteamWorks лежит файлик steamworks.build.cs, который надо открыть любым текстовым редактором и внимательно прочитать. Мне бросились в глаза такие строки:
string SteamVersion = "v142"; и еще
PublicDefinitions.Add("STEAM_SDK_VER=TEXT(\"1.42\")");
Не раздумывая, аккуратно перебил четверки на пятерки. Теперь файлы SDK на месте, но это только начало. Находясь в глубине дерева движка, выходим немного выше в подкаталог Engine. Оттуда идем в Binaries\ThirdParty\Steamworks. Внутри снова создаем подпапку Steamv152, заходим туда. и делаем еще две папки: Win32 и Win64.
В Win32 кладем Steam_api.dll из sdk\redistributable_bin, а в Win64 кладем steam_api64.dll из SDK\redistributable_bin\win64. Как утверждают умные люди, этого достаточно, но я все же подкинул в Win32 файлики Steamclient.dll, tier0_s.dll, vstdlib_s.dll взятые из клиента Стим, а в Win64 тоже из клиента - steamclient64.dll, tier0_s64.dll, vstdlib_s64.dll.
Было ли это лишним — не проверял.
Гемор конечно. Но зато теперь Steamworks_SDK корректно подключен к движку UE4. Не забудьте в окне плагинов найти строчку «Online Platform», прокрутить список до блока «Online Susbsystem Steam» и взвести галку «Enabled». Потребуется перезагрузка, а как вы хотели?
Настало время конфигурить проект. Там в папке Config лежит файл DefaultEngine.ini, открываем его любым текстовым редактором и копипастим в хвост такой вот блок:
[/Script/Engine.GameEngine]
+NetDriverDefinitions=(DefName="GameNetDriver",DriverClassName="OnlineSubsystemSteam.SteamNetDriver",DriverClassNameFallback="OnlineSubsystemUtils.IpNetDriver")
[OnlineSubsystem]
DefaultPlatformService=Steam
[OnlineSubsystemSteam]
bEnabled=true
SteamDevAppId=480
[/Script/OnlineSubsystemSteam.SteamNetDriver]
NetConnectionClassName="OnlineSubsystemSteam.SteamNetConnection"
Вот теперь мы готовы добавлять ачивки. Делается это с двух сторон: на странице в SteamWorks и в DefaultEngine.ini.
В SteamWorks в «управлении приложениями» прокручиваем до блока «Облик в сообществе» и жмем «Достижения». Для каждого достижения нужно назначить три текстовые строки и загрузить два варианта иконки, цветной и черно-белый. «Название для API» - по сути идентификатор, некая уникальная строка, написанная латинскими буквами. «Название для отображения» - краткое имя ачивки, а «Описание» - краткая формулировка условий получения. К примеру, «100 хедшотов подряд» - это описание, название для отображения — пусть будет «Desperado”. В строке «Название для API» можно написать «ACH_DESPERADO». Названия для API надо будет перечислить в DefaultEngine.ini в секции [OnlineSubsystemSteam]. Как-то так: Achievement_0_id="ACH_DESPERADO"
Главное — не ошибиться в названии для API.
И наконец, начинаем ваять блюпринты. К нашим услугам примерно пять нод. «Примерно» - это потому, что шестая устаревшая, а из пяти актуальных реально нужны только три.
Самая нужная нода всего одна, это «Write Achievement Progress». Как только она сработает, оверлей выведет иконку с текстом на экран, и следует хорошенько подумать, не явится ли это раздражающим фактором для геймера. Хорошими событиями являются только те, которые происходят во время. Учитесь тонкостям геймдизайна.
Вообще, онлайновые ноды примечательны тем, что имеют на выходе целых три контакта: один безымянный и два других: On Success/On Failure.
Безымянный контакт позволяет продолжить выполнение логики не дожидаясь ответа от сервера. Это полезно, поскольку ожидание может нарушить обработку кастомных событий, не может быть, чтоб вы обошлись без добавления оных.
Кстати: для отладки ачивок не забудьте вместо Selected ViewPort запускать игру в режиме Standalone Game. Если все правильно настроено, будет виден оверлей и иконки ачивок.
Я не знаю, что будет с геймером, который всю ночь потратил на совершение подвига, если под утро Write Achievement Progress вернет Failure. Делать паузу и повторять попытку записи? Для очистки совести программиста этого хватит, но для успешного сохранения — не факт. В любом случае следует понимать, что результат операции будет известен с весьма ощутимой задержкой, возможно, не менее секунды. В масштабе игровых таймингов это целая вечность.
Внутри игры бывает необходимо знать заранее, какие ачивки уже получены. К примеру, моя игра имеет два различных финала, для каждого своя ачивка. Если геймер прошел игру второй раз, и выбрал другой финал — ему полагаются две ачивки сразу: за финал номер два, и за то, что собрал оба варианта. Для реализации такой логики надо знать, был когда-то альтернативный финал, или нет.
Если даже сервер отзывчивый, ответ прийдет не сразу, возможно, через секунду. Вот почему для чтения нам предоставлено целых две ноды: «Cache Achievements» и «Get Cached Achievement Progress».
Самую тяжелую работу делает «Cache Achievements», она лезет в сеть, потому у ней на выходе три ключа: один безымянный и сладкая парочка On Success/On Failure.
Очень логично расположить ее в последовательности «BeginPlay», причем если не в самом конце, то продолжать тянуть белую соплю надо именно из безымянного ключа. К тому моменту, когда полученные из сети данные понадобятся, либо Success, либо Failure стопудово сработает. Я кстати, не знаю, что делать геймеру, если случилась Failure: все равно играть, или пойти гулять с собакой?
Лично я определяю Success или Failure по результату работы ноды «Get Cached Achievement Progress»: если ачивка не получена, но сервер отозвался, вернется вполне вразумительный ноль. А если сервер не виден - булевый выход «Found Id» вернет неправду.
Исходя из названия, нода в сеть не лезет, цифра прогресса берется из памяти, а потому работает мгновенно.
Есть еще нода «Achievement Description», но зачем нужна – не понимаю в упор. Программист и так все знает, а для игрока есть оверлей.
Если кому интересно, что у меня на уме сейчас — подписывайтесь на блог разработчика: https://vk.com/creatorone или https://t.me/TheCreatorOne кому как удобнее.

Лига Разработчиков Видеоигр
9.1K постов23.2K подписчиков
Правила сообщества
ОБЩИЕ ПРАВИЛА:
- Уважайте чужой труд и используйте конструктивную критику
- Не занимайтесь саморекламой, пишите качественные и интересные посты
- Никакой политики
СТОИТ ПУБЛИКОВАТЬ:
- Посты о Вашей игре с историей её разработки и описанием полученного опыта
- Обучающие материалы, туториалы
- Интервью с опытными разработчиками
- Анонсы бесплатных мероприятий для разработчиков и истории их посещения;
- Ваши работы, если Вы художник/композитор и хотите поделиться ими на безвозмездной основе
НЕ СТОИТ ПУБЛИКОВАТЬ:
- Посты, содержащие только вопрос или просьбу помочь
- Посты, содержащие только идею игры
- Посты, единственная цель которых - набор команды для разработки игры
- Посты, не относящиеся к тематике сообщества
Подобные посты по решению администрации могут быть перемещены из сообщества в общую ленту.
ЗАПРЕЩЕНО:
- Публиковать бессодержательные посты с рекламой Вашего проекта (см. следующий пункт), а также все прочие посты, содержащие рекламу/рекламные интеграции
- Выдавать чужой труд за свой
Подобные посты будут перемещены из сообщества в общую ленту, а их авторы по решению администрации могут быть внесены в игнор-лист сообщества.
О РАЗМЕЩЕНИИ ССЫЛОК:
Ссылка на сторонний ресурс, связанный с игрой, допускается только при следующих условиях:
- Пост должен быть содержательным и интересным для пользователей, нести пользу для сообщества
- Ссылка должна размещаться непосредственно в начале или конце поста и только один раз
- Cсылка размещается в формате: "Страница игры в Steam: URL"