Unreal Engine·Godot 로그인 예제
계정 생성부터 로그인까지의 샘플 코드
SDK 설치 후 사용할 Unreal Engine 5와 Godot의 최소 구현 예제입니다. GS2에 adventure-account라는 Account 네임스페이스를 준비하고 프로젝트의 Default에 있는 ApplicationClientId / ApplicationClientSecret을 설정합니다. 인증 키는 default 네임스페이스의 default를 사용합니다.
아래의 {region}과 {ownerId}를 자신의 리전(예: ap-northeast-1)과 오너 ID로 바꿉니다. 이 예제는 계정 생성부터 로그인까지 한 번 실행합니다. 같은 플레이어로 재개하려면 생성한 ID와 비밀번호를 저장하고, 저장된 정보가 있으면 생성을 건너뛰어 로그인에 사용합니다. 비밀번호를 화면이나 로그에 출력하지 마세요.
Unity에서 저장과 재로그인까지 포함한 구현은 모험 튜토리얼 1장에 있습니다.
// Gs2Tutorial.cpp
#include "Sample/Gs2Tutorial.h"
#include "Core/Gs2Domain.h"
#include "Util/Authentication/Gs2AccountAuthenticator.h"
DEFINE_LOG_CATEGORY(GameLog);
class EZGS2_API FSampleTask final : public Gs2::Core::Util::TGs2Future<void*>
{
public:
virtual ~FSampleTask() override = default;
virtual Gs2::Core::Model::FGs2ErrorPtr Action(const TSharedPtr<TSharedPtr<void*>> Result) override
{
// Setup variables
const auto ClientId = "YourClientId";
const auto ClientSecret = "YourClientSecret";
const auto AccountNamespaceName = "adventure-account";
const auto AccountEncryptionKeyId = "grn:gs2:{region}:{ownerId}:key:default:key:default";
// Create GS2 client
const auto InitializeFuture = Gs2::UE5::Core::FGs2Client::Create(
MakeShared<Gs2::Core::Model::FBasicGs2Credential>(
ClientId,
ClientSecret
),
Gs2::Core::Model::ApNorthEast1
);
InitializeFuture->StartSynchronousTask();
if (InitializeFuture->GetTask().IsError())
{
UE_LOG(GameLog, Error, TEXT("%s"), ToCStr(InitializeFuture->GetTask().Error()->String()));
return InitializeFuture->GetTask().Error();
}
const auto Gs2 = InitializeFuture->GetTask().Result();
// Create an anonymous account
UE_LOG(GameLog, Display, TEXT("Create anonymous account"));
const auto CreateFuture = Gs2->Account->Namespace(
AccountNamespaceName
)->Create();
CreateFuture->StartSynchronousTask();
if (CreateFuture->GetTask().IsError())
{
UE_LOG(GameLog, Error, TEXT("%s"), ToCStr(CreateFuture->GetTask().Error()->String()));
return CreateFuture->GetTask().Error();
}
// Load created account
const auto LoadFuture = CreateFuture->GetTask().Result()->Model();
LoadFuture->StartSynchronousTask();
if (LoadFuture->GetTask().IsError())
{
UE_LOG(GameLog, Error, TEXT("%s"), ToCStr(LoadFuture->GetTask().Error()->String()));
return LoadFuture->GetTask().Error();
}
const auto Account = LoadFuture->GetTask().Result();
// Dump anonymous account
UE_LOG(GameLog, Display, TEXT("UserId: %s"), ToCStr(*Account->GetUserId()));
// Log-in created anonymous account
const auto LoginFuture = Gs2->Login(
MakeShareable<Gs2::UE5::Util::IAuthenticator>(
new Gs2::UE5::Util::FGs2AccountAuthenticator(
MakeShared<Gs2::UE5::Util::FAccountSetting>(
AccountNamespaceName,
AccountEncryptionKeyId
)
)
),
*Account->GetUserId(),
*Account->GetPassword()
);
LoginFuture->StartSynchronousTask();
if (LoginFuture->GetTask().IsError())
{
UE_LOG(GameLog, Error, TEXT("%s"), ToCStr(LoginFuture->GetTask().Error()->String()));
return LoginFuture->GetTask().Error();
}
const auto GameSession = LoginFuture->GetTask().Result();
// Load TakeOver settings
const auto It = Gs2->Account->Namespace(
AccountNamespaceName
)->Me(
GameSession
)->TakeOvers();
for (const auto TakeOver : *It)
{
UE_LOG(GameLog, Display, TEXT("Type: %d"), *TakeOver->GetType());
UE_LOG(GameLog, Display, TEXT("Identifier: %s"), ToCStr(*TakeOver->GetUserIdentifier()));
}
// Finalize GS2-SDK
const auto FinalizeFuture = Gs2->Disconnect();
FinalizeFuture->StartSynchronousTask();
if (FinalizeFuture->GetTask().IsError())
{
UE_LOG(GameLog, Error, TEXT("%s"), ToCStr(FinalizeFuture->GetTask().Error()->String()));
return FinalizeFuture->GetTask().Error();
}
return nullptr;
}
};
AGs2Tutorial::AGs2Tutorial()
{
PrimaryActorTick.bCanEverTick = true;
}
void AGs2Tutorial::BeginPlay()
{
Super::BeginPlay();
(new FAsyncTask<FSampleTask>())->StartBackgroundTask();
}
void AGs2Tutorial::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
// Gs2Tutorial.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Gs2Tutorial.generated.h"
DECLARE_LOG_CATEGORY_EXTERN(GameLog, Log, All);
UCLASS()
class EZGS2_API AGs2Tutorial : public AActor
{
GENERATED_BODY()
public:
AGs2Tutorial();
protected:
virtual void BeginPlay() override;
public:
virtual void Tick(float DeltaTime) override;
};extends Node
func _ready() -> void:
# Setup variables
var client_id = "YourClientId"
var client_secret = "YourClientSecret"
var account_namespace_name = "adventure-account"
var account_encryption_key_id = "grn:gs2:{region}:{ownerId}:key:default:key:default"
# Initialize GS2 SDK
var credential = Gs2BasicCredential.new(client_id, client_secret)
var connection = Gs2Connection.new(credential, Gs2Region.AP_NORTHEAST_1)
var ez = Gs2EzDomain.new(connection)
# Define the GS2-Account namespace
var gs2_account = ez.account.namespace_(
account_namespace_name
)
# Create an anonymous account
var create_result = await gs2_account.create()
if create_result.error != null:
push_error(str(create_result.error))
return
# Load the created account
var model_result = await create_result.result.model()
if model_result.error != null:
push_error(str(model_result.error))
return
var account = model_result.result
# Dump the anonymous account
print("UserId: ", account.user_id)
# Log in with the created anonymous account
var authenticator = Gs2AccountAuthenticator.new(
account_namespace_name,
account_encryption_key_id
)
var game_session = Gs2GameSession.new(
authenticator,
connection,
account.user_id,
account.password
)
var login_result = await game_session.login()
if login_result.error != null:
push_error(str(login_result.error))
return
# Load TakeOver settings
var load_result = await gs2_account.me(
game_session
).take_overs().load()
if load_result.error != null:
push_error(str(load_result.error))
return
for take_over in load_result.result:
print("Type: ", take_over.type)
print("Identifier: ", take_over.user_identifier)
# Finalize GS2 SDK
connection.disconnect_session()