Оно не является обязательным, но рекомендовано весьма настоятельно. Как будто разработчика надо специально упрашивать. Лучше бы взяли, да объяснили популярно, как внедрить Steamworks SDK в UE4, и как дальше ковыряться в блюпринтах. Можно конечно, немного погуглить, много подумать, и наконец, разобраться самостоятельно. Но не каждый программист настолько трудолюбив. Для многих эта статья сэкономит уйму времени и нервов.
Должен признаться, у автора есть свой шкурный интерес. Давайте договоримся так: вы идете по сcылке и давите кнопку «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, а потом еще из корня клиента Steam подкладываем Steamclient.dll, tier0_s.dll, vstdlib_s.dll. В каталог Win64 из SDK\redistributable_bin\win64 копируем steam_api64.dll, а из клиента Steam копируем 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 кому как удобнее.
Комментарии (2)
iKipson
18.10.2021 10:11Спасибо, очень своевременно
PS мне кажется 8Мб ОЗУ для игры это не совсем правильно указано;)
RESTORATiON
Насчёт копирования steamclient64.dll, tier0_s64.dll, vstdlib_s64.dll: это лишнее. Собственно, достаточно иметь в папке steam_api64.dll: при инициализации библиотека откроет реестр и поищет место, где установлен Steam. После этого, из папки с клиентом спокойно подгрузится steamclient64.dll и остальные две.