Назад к блогу

Как исправить сбои авторизации в Unreal Blueprint и ошибки achievements в Epic Online Services

Опубликовано 9 июля 2026 г.
Как исправить сбои авторизации в Unreal Blueprint и ошибки achievements в Epic Online Services

Коротко о главном

Руководство по исправлению типичных ошибок авторизации и интеграции achievements при использовании Epic Online Services (EOS) в Unreal Engine. В материале подробно рассматривается разница между идентификаторами EAID и PUID, а также разбираются проблемы асинхронного потока выполнения в Blueprint и C++. В дополнение приведены практические советы по конфигурации файлов `DefaultEngine.ini` и решению конфликтов ввода из-за оверлея. В качестве альтернативы предлагается использование кроссплатформенного backend-решения horizOn для упрощения интеграции.

Вы компилируете shipping-билд своей игры на Unreal Engine, запускаете ее через Epic Games Launcher и кликаете по кастомной кнопке авторизации. Ничего не происходит, либо клиент игры зависает, а логи заполняются непонятными уведомлениями об ошибках аутентификации. Хуже того, нода разблокировки achievements выполняется без каких-либо видимых ошибок, но профиль игрока в оверлее Epic Games Store остается абсолютно пустым. Эти проблемы невероятно часто встречаются при интеграции API цифровых магазинов. К счастью, их можно решить, скорректировав асинхронный поток выполнения (asynchronous execution flow) и разобравшись в том, как subsystem сопоставляет user identities.

Understanding the EOS Authentication Pipeline: EAID vs. PUID

Интеграция Epic Online Services (EOS) через Online Subsystem (OSS) в Unreal Engine требует работы с двухуровневой системой идентификации. Epic Account ID (EAID) управляется через Auth Interface. Он проверяет личность пользователя на уровне магазина, активируя такие функции, как социальный оверлей, списки друзей и проверки библиотеки Epic Games Store.

В свою очередь, Product User ID (PUID) управляется через Connect Interface. PUID — это уникальный для конкретной игры идентификатор, который связывает пользователя с backend-сервисами игры. Эти сервисы включают в себя matchmaking, статистику, облачные сохранения (cloud saves) и achievements.

Why EAID and PUID Mismatches Break Achievements

Типичный сбой происходит, когда разработчики успешно проходят аутентификацию в Auth Interface (получая EAID), но subsystem не может авторизоваться в Connect Interface. Поскольку управление achievements осуществляется через Connect Interface с использованием PUID, попытка записать прогресс achievement без полученного PUID завершается ошибкой EOS_InvalidUser.

В играх, запускаемых без обертки магазина (storefront wrapper), пользователи обычно входят под учетными данными, которые проверяются по централизованной таблице пользователей. В современной экосистеме цифровых магазинов вроде Epic Games Store идентификация является федеративной. При запуске игры она получает криптографический тикет от лаунчера. Затем игра передает этот тикет на серверы аутентификации магазина. SDK возвращает Epic Account ID, который служит своего рода паспортом пользователя во всех играх на платформе.

Однако для обеспечения конфиденциальности и безопасности кроссплея Epic не позволяет специфичным для игры функциям, таким как achievements, напрямую читать Epic Account ID. Вместо этого игра должна инициализировать Connect Interface, который выполняет вторичный обмен для получения Product User ID. Такое разделение гарантирует, что даже в случае взлома вашей игры глобальные учетные данные Epic Account игроков останутся в безопасности. Без PUID ваша игра фактически работает в режиме неавторизованного гостя, что блокирует доступ к функциям EGS. Если в конфигурации ваших учетных данных (credentials config) или client policy в Epic Developer Portal не настроены нужные разрешения, эта связь разорвется. Интерфейс идентификации сообщит об успешном входе, поскольку аккаунт Epic валиден, но уровень игровых сервисов не сможет записать данные achievements, так как PUID не был привязан.

The Anatomy of a Broken Blueprint Login Sequence

Многие разработчики сталкиваются с проблемами авторизации, когда связывают пины выполнения Blueprint линейно. Перетаскивание execution pin из ноды Login напрямую в ноду Query Achievements или Write Achievement Progress неизбежно приведет к ошибке.

Запросы на аутентификацию должны пройти путь до backend Epic, что делает их асинхронными. Движок продолжает выполнять Blueprint-граф на следующем же кадре, задолго до того, как серверы Epic вернут учетные данные пользователя. На этом этапе Unique Net ID игрока все еще остается null.

The "Missing Node" Mismatch: Race Conditions in Async Execution

Если вы вызываете ноды achievements сразу после ноды входа, subsystem выдает скрытую (silent) ошибку, так как кэшированное состояние пользователя пусто. Корректный рабочий процесс требует привязки кастомных событий к асинхронным делегатам subsystem.

Кроме того, разработчики часто упускают важнейший шаг — кэширование achievements перед записью прогресса. Вы не можете изменить прогресс achievement, предварительно не запросив текущую схему с сервера. Вызов Write Achievements без предварительного вызова Query Achievements приводит к тихому сбою или ошибке EOS_InvalidUser в консольном логе, поскольку размер локальной кэшированной карты achievements равен 0.

The Correct Asynchronous Blueprint Flow

Чтобы исправить это, вам нужно отделить триггер входа от обновления achievements. Сначала вызовите ноду login и укажите правильные учетные данные для аутентификации.

Во-вторых, привяжите событие к делегату On Login Complete интерфейса identity. Как только это событие сработает и вернет статус успешного выполнения, получите Unique Net ID пользователя.

В-третьих, передайте этот ID в ноду Query Achievements. Наконец, привяжите событие к делегату On Query Achievements Complete и вызывайте Write Achievement Progress только внутри этого коллбэка.

Implementing a Robust EOS Login & Achievement Controller in C++

Для чистого управления этими асинхронными операциями настоятельно рекомендуется реализовать цикл аутентификации на C++. Это дает прямой доступ к IOnlineSubsystem и его интерфейсам.

Ниже приведена готовая к продакшену реализация обработчика авторизации и achievements на C++:

#include "OnlineSubsystem.h"
#include "Interfaces/OnlineIdentityInterface.h"
#include "Interfaces/OnlineAchievementsInterface.h"
#include "OnlineSubsystemUtils.h"

void UEOSLoginHandler::LoginToEpicGames(APlayerController* PlayerController)

{
    if (!PlayerController) return;

    IOnlineSubsystem* Subsystem = IOnlineSubsystem::Get(TEXT("EOS"));
    if (!Subsystem)
    {
        UE_LOG(LogTemp, Warning, TEXT("EOS Subsystem not found. Make sure the plugin is enabled."));
        return;
    }

    IOnlineIdentityPtr Identity = Subsystem->GetIdentityInterface();
    if (Identity.IsValid())
    {
        FOnlineAccountCredentials Credentials;
        Credentials.Type = TEXT("ExchangeCode");
        Credentials.Id = TEXT("");
        Credentials.Token = TEXT(""); // The launcher passes this via command line arguments

        Identity->AddOnLoginCompleteDelegate_Handle(0, FOnLoginCompleteDelegate::CreateUObject(this, &UEOSLoginHandler::OnLoginComplete));
        Identity->Login(0, Credentials);
    }
}

void UEOSLoginHandler::OnLoginComplete(int32 LocalUserNum, bool bWasSuccessful, const FUniqueNetId& UserId, const FString& Error)
{
    if (!bWasSuccessful)
    { 
        UE_LOG(LogTemp, Error, TEXT("Epic Online Services Login Failed. Error: %s"), *Error);
        return;
    }

    UE_LOG(LogTemp, Log, TEXT("EOS Login Successful. ID resolved: %s"), *UserId.ToString());

    IOnlineSubsystem* Subsystem = IOnlineSubsystem::Get(TEXT("EOS"));
    IOnlineAchievementsPtr Achievements = Subsystem->GetAchievementsInterface();
    if (Achievements.IsValid())
    { 
        Achievements->QueryAchievements(UserId, FOnQueryAchievementsCompleteDelegate::CreateUObject(this, &UEOSLoginHandler::OnQueryAchievementsComplete));
    }
}

void UEOSLoginHandler::OnQueryAchievementsComplete(const FUniqueNetId& PlayerId, bool bWasSuccessful)
{
    if (!bWasSuccessful)
    {
        UE_LOG(LogTemp, Warning, TEXT("Failed to query achievements from Epic Developer Portal."));
        return;
    }

    UE_LOG(LogTemp, Log, TEXT("Achievements queried successfully. Now writing progress."));

    IOnlineSubsystem* Subsystem = IOnlineSubsystem::Get(TEXT("EOS"));
    IOnlineAchievementsPtr Achievements = Subsystem->GetAchievementsInterface();
    if (Achievements.IsValid())
    {
        FOnlineAchievementsWriteRef WriteObject = MakeShared<FOnlineAchievementsWrite>();
        WriteObject->SetFloatStat(TEXT("ACH_FIRST_BLOOD"), 100.0f);

        Achievements->WriteAchievements(PlayerId, WriteObject, FOnAchievementsWrittenDelegate::CreateUObject(this, &UEOSLoginHandler::OnAchievementsWritten));
    }
}

void UEOSLoginHandler::OnAchievementsWritten(const FUniqueNetId& PlayerId, bool bWasSuccessful)
{
    if (bWasSuccessful)
    {
        UE_LOG(LogTemp, Log, TEXT("Achievement successfully unlocked on Epic Games Store!"));
    }
    else
    {
        UE_LOG(LogTemp, Error, TEXT("Failed to write achievement progress. Check sandbox mappings."));
    }
}

Этот контроллер использует последовательные коллбэки. Он гарантирует, что доступ к интерфейсу achievements будет получен только после того, как интерфейс identity успешно сопоставит как Epic Account ID, так и Product User ID.

Configuring your DefaultEngine.ini File for EOS

Ноды Blueprint для входа не смогут инициализироваться, если конфигурации в вашем файле Config/DefaultEngine.ini указаны неверно. Плагин Online Subsystem EOS требует определенных параметров для привязки к вашему игровому клиенту.

Используйте следующий шаблон конфигурации, чтобы подсистема инициализировалась правильно:

[OnlineSubsystem]
DefaultPlatformService=EOS

[OnlineSubsystemEOS]
bEnabled=true
bUseEpicConnect=true
ProductId=your_product_id_here
SandboxId=your_sandbox_id_here
DeploymentId=your_deployment_id_here
ClientId=your_client_id_here
ClientSecret=your_client_secret_here

[OnlineSubsystemEOS.Auth]
bUseEpicAccount=true

Конфигурация вашего файла DefaultEngine.ini выступает в роли моста между скомпилированными бинарными файлами игры и Epic Developer Portal. Параметры в секции [OnlineSubsystemEOS] должны в точности соответствовать настройкам вашего продукта.

Распространенным источником путаницы является разница между client credentials и sandbox ID. Client ID и Client Secret представляют собой учетные данные вашего игрового клиента, позволяющие ему взаимодействовать с backend EOS. Sandbox ID представляет конкретное окружение (например, Development, Staging или Live), к которому обращается ваш клиент.

Если ваш игровой клиент попытается пройти аутентификацию с Sandbox ID, который не соответствует политике Client Credentials, запрос на аутентификацию будет отклонен. Кроме того, флаг bUseEpicConnect должен быть установлен в значение true, чтобы Online Subsystem автоматически и незаметно для разработчика обрабатывала маппинг EAID в PUID.

Managing Overlay Focus Mismatches and Platform Integration

Плагин EOS для Unreal в значительной степени полагается на Epic Games Overlay для отображения уведомлений, обработки приглашений друзей и выполнения OAuth веб-аутентификации. Когда игровой клиент инициирует вход с типом учетных данных AccountPortal, операционная система запускает окно браузера или открывает оверлей.

Это перенаправление смещает фокус с окна игры. Если ваши режимы ввода не настроены на обработку потери фокуса, игра может зависнуть или начать регистрировать залипшие клавиши.

Решение проблем с вводом, вызванных оверлеем, — частая головная боль для PC-разработчиков. Например, внедрение (injection) оверлея может конфликтовать с драйверами raw input и приводить к зависанию состояния клавиатуры и мыши. Чтобы предотвратить появление этих багов, портящих впечатление игроков, вы можете ознакомиться с нашим анализом The Marathon Input Issues Fix: Architecting PC Games to Survive Overlay Conflicts.

Кроме того, сбои инициализации во время тестирования часто вызваны неверно настроенными сокет-соединениями или пороговыми значениями таймаута в вашей локальной конфигурации. Если вы устраняете таймауты драйверов при запуске сессии, изучите наше руководство Uefn Session Launch Timeout Nightmares: Diagnosing Unreal Engine Network Drivers.

Simplifying Cross-Platform Storefront Backends

Ручная настройка подсистем магазинов, написание цепочек делегатов на C++ и решение проблем с фокусом оверлея на разных платформах отнимают массу времени. Выполнение этого для нескольких магазинов, таких как Steam, EGS и консолей, увеличивает затраты на разработку в разы.

Создание всего этого самостоятельно требует настройки load balancers, шардирования баз данных и управления SSL-сертификатами — а это легко может занять 4–6 недель работы.

С horizOn вы получаете унифицированный кроссплатформенный backend, который абстрагирует API этих магазинов. Вместо того чтобы возиться с двухкомпонентными токенами идентификации (EAID/PUID), Epic sandboxes или кодом инициализации Steamworks, вы используете единый API для работы с профилями пользователей, achievements, matchmaking и лидерами (leaderboards).

horizOn выступает в роли моста, автоматически синхронизируя achievements и прогресс игроков с любым магазином, из которого запущена игра, что позволяет вам сосредоточиться на геймплее (game loop), а не на написании шаблонного кода (boilerplate) под конкретный магазин. Это означает, что ваши игроки смогут разблокировать achievements, использовать облачные сохранения и искать матчи независимо от используемой платформы или лаунчера, а вам не придется писать ни строчки SDK-кода под конкретные магазины.

Modern Best Practices for Epic Online Services Integrations

  1. Никогда не связывайте асинхронные ноды напрямую: Всегда дожидайтесь вызова делегатов OnLoginComplete и OnQueryAchievementsComplete перед запуском последующих операций, таких как запись статистики или achievements.

  2. Включите подробное логирование во время разработки: Добавьте следующие строки в ваш DefaultEngine.ini в секцию [Core.Log] для отслеживания скрытых предупреждений EOS:

    [Core.Log]
    LogOnline=VeryVerbose
    LogOnlineGame=VeryVerbose
    LogEOSSDK=VeryVerbose
    
  3. Свяжите achievements с EOS на Dev Portal: Убедитесь, что достижения, созданные в Epic Games Store (EGS), явно привязаны к вашему backend Epic Online Services (EOS). Если связь отсутствует, EOS SDK не распознает ID достижений.

  4. Используйте ExchangeCode в Shipping-билдах: При локальной разработке удобен тип входа Developer с использованием Dev Auth Tool, однако в shipping-билдах, запускаемых из Epic Games Launcher, необходимо переключить тип учетных данных на ExchangeCode. Использование типа авторизации ExchangeCode, предоставляемого лаунчером, позволяет пропустить перенаправление OAuth в веб-браузере, сокращая время авторизации с 8–12 секунд ручного взаимодействия до автоматического хендшейка менее чем за 500 мс.

Streamlining Storefront Integrations

Решение проблем со входом и ачивками в Epic Online Services в Unreal Engine сводится к пониманию асинхронного пайплайна (async pipeline) и точной настройке конфигурационных файлов. Управляя переходом между интерфейсами идентификации и игровых сервисов, разработчики могут избавиться от скрытых ошибок и обеспечить игрокам безупречный игровой опыт.

Готовы масштабировать свой multiplayer-backend? Попробуйте horizOn бесплатно или изучите API docs.


Источник: Epic Games Store (Online Services AND Achievements)