HIKI Tech Blog

yhikishimaのブログ。ゆるくUE4やUnity、web開発の記事を書いてます。

UE5 + Unity Game Servicesでマルチプレイ vol.2 マッチメイクの設定と認証

1. はじめに

前回の Vol.1の続き。

前回はホスティングサーバーへの接続までできたので、今度はマッチメイクの設定と認証をしていきます。

2. マッチメイクの設定

Unreal Game Servicesのダッシュボードに移動して、MatchMakerのセットアップのところまで移動します。

Integrate Matchmaker のボタンを押して、 Unreal API を押して次へ

Download API Specification のボタンを押して、別ブラウザで開かれた yaml ファイルを保存します。

次にキューの作成に進みます。

キュー名とMaxPlayerを指定します。

次にPoolの設定に進みます。

Pool名を入力して、Queueには先ほど作成したQueue、Timeoutは300秒などいれて次へ。

FleetとBuild Configurationも前回作成したものを選ぶ。

最後にルールを設定します。

ルール名を入力。RegionはAsisa、BackFillはTrueを選択しておきます。

あとは、希望のルール設定を入れる。

設定はできたので、あとは実際にマッチメイクの処理を追加していきます。

3. マッチメイク処理実装追加

UEに関しては、HTTPリクエストのそれぞれのAPIをたたく必要があるので、仕組みをいれていきます。

UE5にてHTTPリクエストできるようにするには以下などを参考に。

#UnrealEngine5 でHTTPリクエスト機能を実装してAPIコールしてみた | DevelopersIO

また、Unityのサンプルプロジェクトがあるので、こちらなど参考に。

GitHub - Unity-Technologies/com.unity.services.samples.matchplay: A Matchmaking with Multiplay Unity example project. Implements the Unity Matchmaking and Multiplay SDK to create an end to end matchmaking game experience.

3-1. 認証API

まずは認証のAPI。

https://services.docs.unity.com/docs/service-account-auth/index.html

クライアントからAPIをたたく際には、

  • ClientAuthを使用
  • ServiceAccountを使用

のどちらかの認証APIを先に叩いて、AuthTokenを取得する必要がある。

今回は手っ取り早くServiceAccountを使用します。

Service Account Authentication | Unity Services Web API docs

↑のドキュメント通りに。

まずは、サービスアカウントのキーIDとシークレットIDを作成します。

アカウントにログインして、Service Accountsの項目に移動して、以下の「Create Service Account」ボタンを押します。

サービスアカウント名と詳細を入力して、OKを押します。

サービスアカウントが作成されたので、Keysの Create Keyを押します。

すると以下のようにキーIDとシークレットIDがでてくるので、メモしておきます。

サービスアカウントの資格情報が欲しいので、以下のコマンドを実行します。(Unixでのコマンドなので、Windowsの標準コマンドプロンプトの場合は別途。。)

echo -n "{キーID}:{シークレットID}" | base64

すると、以下のようにハッシュが表示されます。(以下はサンプルの例)

これをメモっておきます。

マッチングのAPIでは ステートレストークンが必要になってきます。↓を参考。

Service Account Authentication | Unity Services Web API docs

ステートレストークンには PROJECT_IDENVIRONMENT_ID が必要になってくるので、サービスアカウントからメモしておきます。

これで、認証用のAPIを叩く準備ができました。

メモした

  • サービスアカウントの資格情報のハッシュ(Basicをつけて)
  • PROJECT_ID
  • ENVIRONMENT_ID

こちらを Config.csに追加しておきます。

初期化のタイミングで以下のように HTTPリクエストを送るようにします。


void ACPP_MatchUI::BeginPlay()
{
    Super::BeginPlay();

    // Auth設定
    MatchAuth = NewObject();
    if (MatchAuth)
    {
        MatchAuth->Request();
    }
}
void UCPP_MatchAuth::Request()
{
    // URLを作成
    const FString URL = TEXT("https://services.api.unity.com/auth/v1/token-exchange") + TEXT("?projectId=") + PRODUCT_ID + TEXT("&environmentId=") + ENVIROMENT_ID;

    UHTTP* Request = NewObject();
    Request->Request(*URL, EHttpVerbs::POST, *BASIC_TOKEN, TEXT(""), [=](const FString& Response)
    {
        // レスポンスをパース
        TSharedPtr JsonObject;
        TSharedRef> Reader = TJsonReaderFactory<>::Create(Response);
        if (FJsonSerializer::Deserialize(Reader, JsonObject))
        {
            // AuthTokenを取得
            AuthToken = JsonObject->GetStringField(TEXT("accessToken"));
        }
    });
}

HTTPリクエストのサンプルは以下。

void UHTTP::Request(
    const FString& Url,
    const EHttpVerbs Verb,
    const FString& Header,
    const FString& Body,
    const TFunction Callback)
{
    // HTTPリクエストオブジェクト作成
    const FHttpRequestRef Request = FHttpModule::Get().CreateRequest();

    // HTTPリクエスト完了時に実行する関数のポインタをセット
    Request->OnProcessRequestComplete().BindWeakLambda(this, [=](FHttpRequestPtr HttpRequest, FHttpResponsePtr HttpResponse, bool ConnectionSuccessfully)
    {
        if (HttpResponse)
        {
            // UEでログ出力(APIから受け取った文字列そのまま)
            UE_LOG(LogTemp, Log, TEXT("UHTTP:Response %s"), *HttpResponse->GetContentAsString());

            FColor DisplayColor = FColor::Green;
            if (!ConnectionSuccessfully)
            {
                DisplayColor = FColor::Red;
            }

            // 画面上に表示
            GEngine->AddOnScreenDebugMessage(-1, 3.0f, DisplayColor, FString::Printf(TEXT("HTTP Response!!! Response(%s)"), *HttpResponse->GetContentAsString()), true, FVector2D(1.0f, 1.0f));
        
            // Callback実行
            Callback(*HttpResponse->GetContentAsString());
        }
    });

    // HTTPリクエストのURLをセット
    Request->SetURL(Url);

    UEnum* const Enum = FindObject(ANY_PACKAGE, TEXT("EHttpVerbs"));
    const FString VerbString =  Enum->GetNameStringByIndex(static_cast(Verb));
    
    // HTTPリクエストのメソッドをセット
    Request->SetVerb(VerbString);

    // HTTPリクエストのヘッダーをセット
    Request->SetHeader(TEXT("Content-Type"), TEXT("application/json"));
    if (!Header.IsEmpty())
    {
        UE_LOG(LogTemp, Log, TEXT("UHTTP:Request Authorization : %s"), *Header);
        Request->SetHeader(TEXT("Authorization"), Header);
    }

    // HTTPリクエストのボディをセット
    UE_LOG(LogTemp, Log, TEXT("UHTTP:Request Verb : %s, Url : %s, Body : %s"), *VerbString, *Url, *Body);

    Request->SetContentAsString(Body);

    Request->SetContentAsString(Body);

    // HTTPリクエスト実行
    Request->ProcessRequest();

    // 画面上に表示
    GEngine->AddOnScreenDebugMessage(-1, 3.0f, FColor::Yellow, FString::Printf(TEXT("HTTP Request!!! Url(%s)"), *Url), true, FVector2D(1.0f, 1.0f));
}

上記を追加して、ゲームをプレイします。以下のようにaccessTokenを取得できるかと思います。

これでようやくマッチメイクのAPIを叩く準備ができました。

次は実際にマッチメイクのAPIを叩いて、動作を確認していきます。

参考

How to set up Matchmaker | Unity Gaming Services - YouTube

Unity Matchmaker service