Como Corrigir Falhas de Login no Blueprint da Unreal e Erros de Achievements no Epic Online Services
Em resumo
Este artigo aborda como solucionar falhas de login e erros na gravação de achievements ao integrar o Epic Online Services (EOS) no Unreal Engine. Explica-se a diferença crucial entre as credenciais Epic Account ID (EAID) e Product User ID (PUID), detalhando como a falha nessa vinculação impede a sincronização de dados do jogador. Além disso, apresenta-se a forma correta de estruturar o fluxo de execução assíncrona por meio de delegates no Blueprint e em C++, bem como as configurações recomendadas para o arquivo DefaultEngine.ini.
Você compila uma shipping build do seu jogo em Unreal Engine, inicia-o a partir do Epic Games Launcher e clica no seu botão de login personalizado. Nada acontece, ou o client do jogo trava, e seus logs são preenchidos com notificações enigmáticas de falha de autenticação. Pior ainda, seu node de desbloqueio de achievements é executado sem apresentar nenhum erro visível, mas o perfil do jogador no overlay da Epic Games Store continua completamente vazio. Esses erros são incrivelmente comuns ao integrar APIs de storefronts. Felizmente, eles podem ser resolvidos corrigindo o seu fluxo de execução assíncrona e entendendo como o subsystem mapeia as identidades dos usuários.
Entendendo a Pipeline de Autenticação do EOS: EAID vs. PUID
Integrar o Epic Online Services (EOS) via Online Subsystem (OSS) da Unreal Engine exige navegar por um sistema de identidade de duas camadas. O Epic Account ID (EAID) é gerenciado pela Auth Interface. Ele valida quem o usuário é no nível da storefront, habilitando recursos como o overlay social, listas de amigos e checagens de biblioteca da Epic Games Store.
Por outro lado, o Product User ID (PUID) é gerenciado pela Connect Interface. O PUID é um identificador específico do jogo que vincula o usuário aos serviços de backend do jogo. Esses serviços incluem matchmaking, stats, cloud saves e achievements.
Por que Incompatibilidades entre EAID e PUID Quebram os Achievements
Um modo de falha comum ocorre quando os desenvolvedores se autenticam com sucesso na Auth Interface (gerando um EAID), mas o subsystem falha em fazer login na Connect Interface. Como os achievements são gerenciados pela Connect Interface usando PUIDs, gravar o progresso de achievements sem um PUID resolvido falhará com um erro EOS_InvalidUser.
Em jogos lançados sem um wrapper de storefront, os usuários normalmente fazem login com credenciais que são validadas contra uma tabela de usuários centralizada. Em um ecossistema de storefront moderno como a Epic Games Store, a identidade é federada. Quando o seu jogo é iniciado, ele recebe um ticket criptográfico do launcher. O jogo então passa esse ticket para os servidores de autenticação da storefront. O SDK retorna um Epic Account ID, que funciona como o passaporte do usuário para todos os jogos da plataforma.
No entanto, para manter a privacidade e a segurança do cross-play, a Epic não permite que recursos específicos do jogo, como achievements, leiam o Epic Account ID diretamente. Em vez disso, o jogo deve inicializar a Connect Interface, que realiza uma troca secundária para recuperar o Product User ID. Essa separação garante que, caso o seu jogo seja hackeado, as credenciais globais da Epic Account dos jogadores não fiquem comprometidas. Sem o PUID, seu jogo opera efetivamente em um estado de convidado não autenticado, bloqueando o acesso aos recursos da EGS. Se a sua configuração de credenciais ou client policy não tiver as permissões corretas no Epic Developer Portal, essa vinculação falhará. A interface de identidade relatará um login bem-sucedido porque a Epic Account é válida, mas a camada de serviços de jogo não poderá gravar dados de achievements porque nenhum PUID foi vinculado.
A Anatomia de uma Sequência de Login em Blueprints com Erros
Muitos desenvolvedores enfrentam problemas de login ao encadear os pinos de execução do Blueprint de forma linear. Puxar o pino de execução de um node Login diretamente para um node Query Achievements ou Write Achievement Progress sempre resultará em falha.
Autenticar requer uma chamada assíncrona aos servidores da Epic. O engine continua executando a linha de execução do Blueprint no frame seguinte, muito antes de os servidores da Epic retornarem as credenciais do usuário. Nesse estágio, o Unique Net ID do jogador continua nulo.
A Incompatibilidade do "Node Ausente": Race Conditions na Execução Assíncrona
Se você chamar os nodes de achievements imediatamente após o node de login, o subsystem disparará um erro silencioso porque o estado do usuário em cache estará vazio. O workflow correto exige fazer o bind de eventos personalizados aos delegates assíncronos do subsystem.
Além disso, os desenvolvedores costumam esquecer o passo crucial de fazer o cache dos achievements antes de gravar neles. Você não pode modificar o progresso de um achievement sem antes consultar o servidor sobre o schema atual. Chamar Write Achievements sem uma chamada prévia de Query Achievements resulta em uma falha silenciosa ou em um erro EOS_InvalidUser no seu console log, pois o tamanho do map de achievements local em cache é 0.
O Fluxo Assíncrono Correto no Blueprint
Para resolver isso, você deve separar o gatilho de login da atualização de achievements. Primeiro, chame o node de login e especifique as credenciais de autenticação corretas.
Segundo, faça o bind de um evento ao delegate On Login Complete da interface de identidade. Assim que esse evento disparar e retornar um status de sucesso, recupere o Unique Net ID do usuário.
Terceiro, passe esse ID para o node Query Achievements. Por fim, faça o bind de um evento ao delegate On Query Achievements Complete e chame Write Achievement Progress apenas dentro desse callback.
Implementando um Controller Robusto de Login e Achievements do EOS em C++
Para lidar com essas operações assíncronas de forma limpa, é altamente recomendável implementar o loop de autenticação em C++. Isso fornece acesso direto ao IOnlineSubsystem e às suas interfaces.
Abaixo está uma implementação completa e pronta para produção em C++ de um handler de login e achievements:
#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."));
}
}
Este controller utiliza callbacks sequenciais. Ele garante que a interface de achievements seja acessada apenas quando a interface de identidade tiver resolvido com sucesso tanto o Epic Account ID quanto o Product User ID.
Configurando o seu Arquivo DefaultEngine.ini para o EOS
Os nodes de login do Blueprint falharão ao inicializar se as configurações no seu arquivo Config/DefaultEngine.ini estiverem incorretas. O plugin Online Subsystem EOS exige parâmetros específicos para se vincular ao client do seu jogo.
Use o seguinte template de configuração para garantir que o seu subsystem inicialize corretamente:
[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
A configuração do seu arquivo DefaultEngine.ini age como a ponte entre os binários compilados do seu jogo e o Epic Developer Portal. Os parâmetros sob [OnlineSubsystemEOS] devem corresponder exatamente às suas configurações de produto.
Uma fonte comum de confusão é a diferença entre as client credentials e os sandbox IDs. O Client ID e o Client Secret representam as credenciais do seu client de jogo, permitindo que ele se comunique com o backend do EOS. O Sandbox ID representa o ambiente específico (como Development, Staging ou Live) que o seu client está acessando.
Se o client do seu jogo tentar se autenticar com um Sandbox ID que não corresponda à política de Client Credentials, a requisição de autenticação será rejeitada. Além disso, a flag bUseEpicConnect deve ser definida como true para garantir que o Online Subsystem trate o mapeamento de EAID para PUID automaticamente em background.
Gerenciando Incompatibilidades de Foco do Overlay e Integração de Plataformas
O plugin EOS da Unreal depende fortemente do Epic Games Overlay para exibir notificações, lidar com convites de amigos e realizar autenticações web via OAuth. Quando o client do seu jogo dispara um login usando o tipo de credencial AccountPortal, o sistema operacional abre uma janela do navegador ou inicia o overlay.
Esse redirecionamento desvia o foco da janela do jogo. Se os seus modos de entrada (input modes) não estiverem configurados para lidar com a perda de foco, o jogo pode travar ou registrar teclas presas.
Lidar com problemas de entrada induzidos pelo overlay é uma dor de cabeça comum para desenvolvedores de PC. Por exemplo, a injeção do overlay pode conflitar com drivers de entrada brutos (raw input) e fazer com que os estados do teclado/mouse travem. Para evitar que esses bugs estraguem a experiência do jogador, você pode conferir nossa análise de A Correção de Problemas de Input do Marathon: Arquitetando Jogos de PC para Sobreviver a Conflitos de Overlay.
Falhas de inicialização durante os testes geralmente são causadas por conexões de socket mal configuradas ou limites de timeout na sua configuração local. Se você estiver investigando timeouts de driver durante a inicialização da sessão, confira o nosso guia sobre Pesadelos de Timeout ao Iniciar Sessões no Uefn: Diagnosticando Drivers de Rede da Unreal Engine.
Simplificando Backends de Storefronts Multiplataforma
Configurar manualmente subsystems de storefronts, escrever cadeias de delegates em C++ e lidar com problemas de foco do overlay específicos de cada plataforma consome muito tempo. Fazer isso para múltiplas storefronts como Steam, EGS e consoles multiplica a sua carga de trabalho de desenvolvimento.
Desenvolver isso por conta própria exige configurar load balancers, database sharding e gerenciamento de certificados SSL — facilmente 4 a 6 semanas de trabalho.
Com o horizOn, você tem um backend multiplataforma unificado que abstrai essas APIs de storefronts. Em vez de lidar com tokens de dupla identidade (EAID/PUID), sandboxes da Epic ou código de inicialização do Steamworks, você usa uma única API que gerencia perfis de usuários, achievements, matchmaking e leaderboards.
O horizOn funciona como uma ponte, sincronizando automaticamente os achievements e o progresso do jogador com qualquer storefront de onde o usuário tenha iniciado o jogo, permitindo que você foque no game loop em vez de boilerplate de storefront. Isso significa que seus jogadores podem desbloquear achievements, acessar cloud saves e buscar partidas independentemente de qual plataforma ou launcher estejam utilizando, sem que você precise escrever uma única linha de código de SDK específica daquela storefront.
Melhores Práticas Modernas para Integrações com Epic Online Services
Nunca Encadeie Nodes Assíncronos Diretamente: Sempre espere os delegates
OnLoginCompleteeOnQueryAchievementsCompletedispararem antes de executar operações subsequentes, como gravar estatísticas ou achievements.Habilite Logging Detalhado Durante o Desenvolvimento: Adicione as seguintes linhas ao seu
DefaultEngine.inisob[Core.Log]para rastrear avisos ocultos do EOS:[Core.Log] LogOnline=VeryVerbose LogOnlineGame=VeryVerbose LogEOSSDK=VeryVerboseMapeie Achievements para o EOS no Dev Portal: Certifique-se de que os achievements criados sob a Epic Games Store (EGS) estejam explicitamente mapeados para o seu backend do Epic Online Services (EOS). Se não estiverem vinculados, o EOS SDK não reconhecerá o ID do achievement.
Use ExchangeCode em Shipping Builds: Durante o desenvolvimento local, o tipo de login
Developercom uma Dev Auth Tool é conveniente, mas você deve alterar o tipo de credenciais paraExchangeCodeem shipping builds iniciadas a partir do Epic Games Launcher. Usar o tipo de autenticaçãoExchangeCodefornecido pelo launcher ignora o redirecionamento OAuth do navegador web, reduzindo o tempo da sequência de login de 8-12 segundos de interação manual do usuário para um handshake automatizado de menos de 500ms.
Simplificando Integrações com Storefronts
Resolver erros de login e achievements do Epic Online Services no Unreal Engine resume-se a compreender o pipeline assíncrono e manter os perfis de configuração perfeitamente alinhados. Ao gerenciar a transição entre as interfaces de identidade e de serviços de jogo, os desenvolvedores podem eliminar erros silenciosos e entregar uma experiência fluida aos jogadores.
Pronto para escalar o seu backend multiplayer? Experimente o horizOn gratuitamente ou confira a documentação da API.