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.
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.
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.