このガイドでは、Unreal Engine を使用してアプリ内でアプリ内アップデートをサポートする方法について説明します。実装に Kotlin プログラミング言語または Java プログラミング言語を使用するケースと、ネイティブ コード(C/C++)または Unity を使用するケースについては、個別のガイドが用意されています。
Unreal Engine SDK の概要
Play In-App Updates API は Play Core SDK ファミリーの一部です。Unreal Engine の API には、アプリと Play API 間の通信を処理する UInAppUpdatesManager クラスが用意されています。リクエストの実行後、アプリは EAppUpdateErrorCode を使用してリクエストのステータスを確認できます。
サポートされている Unreal Engine のバージョン
このプラグインは、Unreal Engine 5.0 以降のすべてのバージョンをサポートしています。
開発環境をセットアップする
- GitHub リポジトリから Play Unreal Engine Plugin をダウンロードします。 
- Unreal Engine プロジェクトの - Pluginsフォルダ内に- GooglePlayフォルダをコピーします。
- Unreal Engine プロジェクトを開き、[編集 → プラグイン] をクリックします。 
- [Google Play] を検索し、[有効] チェックボックスをオンにします。 
- ゲーム プロジェクトを再起動してビルドをトリガーします。 
- プロジェクトの - Build.csファイルを開き、- PlayInAppUpdatesモジュールを- PublicDependencyModuleNamesに追加します。- using UnrealBuildTool; public class MyGame : ModuleRules { public MyGame(ReadOnlyTargetRules Target) : base(Target) { // ... PublicDependencyModuleNames.Add("PlayInAppUpdates"); // ... } }
アップデートの有無の確認
アップデートをリクエストする前に、アプリにアップデートが利用可能かどうかを確認します。UInAppUpdatesManager::RequestInfo を使用してアップデートを確認します。
MyClass.h
void MyClass::OnRequestInfoOperationCompleted(
  EAppUpdateErrorCode ErrorCode,
  UAppUpdateInfo* UpdateInfo)
{
  // Check the resulting error code.
  if (ErrorCode == EAppUpdateErrorCode::AppUpdate_NO_ERROR)
  {
    // Check AppUpdateInfo's UpdateAvailability, UpdatePriority,
    // IsUpdateTypeAllowed(), ... and decide whether to ask the user
    // to start an in-app update.
  }
}
MyClass.cpp
void MyClass::CheckForUpdateAvailability()
{
  // Create a delegate to bind the callback function.
  FRequestInfoOperationCompletedDelegate Delegate;
  // Bind the completion handler (OnRequestInfoOperationCompleted) to the delegate.
  Delegate.BindDynamic(this, &MyClass::OnRequestInfoOperationCompleted);
  // Initiate the request info operation, passing the delegate to handle the result.
  GetGameInstance()
    ->GetSubsystem<UInAppUpdatesManager>()
    ->RequestInfo(Delegate);
}
返される UAppUpdateInfo インスタンスには、アップデートの有無を示すステータスが含まれます。アプリ内アップデートがすでに進行中の場合、インスタンスは進行中のアップデートのステータスも報告します。
アップデートの新しさの確認
アップデートが適用可能であるかどうかを確認するだけでなく、ユーザーが Google Play ストアからアップデートの通知を受信してから経過した期間を確認することもできます。これは、フレキシブル アップデートと即時アップデートのどちらを開始したらよいかを判断する際に有用です。たとえば、ユーザーにフレキシブル アップデートを通知するまで数日待ち、その後、即時アップデートを要求するまでさらに数日待つこともできます。
UAppUpdateInfo:GetClientVersionStalenessDays を使用して、Google Play ストアからのアップデートの入手が可能になった時点から経過した日数を確認します。
int32 ClientVersionStalenessDays = UpdateInfo->GetClientVersionStalenessDays();
アップデートの優先度の確認
Google Play Developer API を使用すると、各アップデートの優先度を設定できます。これにより、アプリはユーザーへの更新の推奨度を決定できます。たとえば、アップデートの優先度を設定するための次のような戦略を考えてみます。
- UI の小さな改善: 優先度が低いアップデート。フレキシブル アップデート、即時アップデートのいずれもリクエストしません。
- パフォーマンスの改善: 優先度が中程度のアップデート。フレキシブル アップデートをリクエストします。
- 重要なセキュリティ アップデート: 優先度が高いアップデート。即時アップデートをリクエストします。
優先度を決定するにあたり、Google Play は 0~5 の整数値を使用します。0 はデフォルトの値、5 は優先度が最も高い値です。アップデートの優先度を設定するには、Google Play Developer API の Edits.tracks.releases の下にある inAppUpdatePriority フィールドを使用します。リリースで新たに追加されたすべてのバージョンの優先度は、リリースと同じとみなされます。優先度は新しいリリースの公開時にのみ設定できます。後から変更することはできません。
Google Play Developer API を使用した優先度の設定については、Google Play Developer API のドキュメントをご覧ください。アプリ内アップデートの優先度は、Edit.tracks: update メソッドで渡される Edit.tracks リソースで指定する必要があります。次の例に、バージョン コード 88、inAppUpdatePriority 5 のアプリのリリースを示します。
{ "releases": [{ "versionCodes": ["88"], "inAppUpdatePriority": 5, "status": "completed" }] }
アプリのコードで、UAppUpdateInfo::UpdatePriority を使用して特定のアップデートの優先度を確認できます。
int32 Priority = UpdateInfo->GetPriority();
アップデートの開始
アップデートが利用可能であることを確認したら、UInAppUpdatesManager::StartUpdate を使用してアップデートをリクエストできます。更新をリクエストする前に、最新の UAppUpdateInfo オブジェクトがあることを確認します。また、更新フローを構成する UAppUpdateOptions オブジェクトも作成する必要があります。
次の例では、即時アップデート フロー用の UAppUpdateOptions オブジェクトを作成します。
// Creates an UAppUpdateOptions defining an immediate in-app
// update flow and its parameters.
UAppUpdateOptions* Options = NewObject<UAppUpdateOptions>();
Options->CreateOptions(EAppUpdateType::AppUpdate_TYPE_IMMEDIATE);
次の例では、フレキシブル アップデート フロー用の UAppUpdateOptions オブジェクトを作成します。
// Creates an UAppUpdateOptions defining a flexible in-app
// update flow and its parameters.
UAppUpdateOptions* Options = NewObject<UAppUpdateOptions>();
Options->CreateOptions(EAppUpdateType::AppUpdate_TYPE_FLEXIBLE);
UAppUpdateOptions オブジェクトには IsAssetPackDeletionAllowed 関数も含まれており、デバイスのストレージが限られている場合に、アップデートによるアセットパックの消去を許可するかどうかを返します。このフィールドはデフォルトで false に設定されていますが、UAppUpdateOptions::SetAssetPackDeletionAllowed を使用してフィールドを設定することで、代わりに true に設定することもできます。
// Sets the AssetPackDeletionAllowed field to true.
Options->SetAssetPackDeletionAllowed(true);
次のステップは、フレキシブル アップデートと即時アップデートのどちらをリクエストするかによって異なります。
フレキシブル アップデートの処理
最新の UAppUpdateInfo オブジェクトと適切に構成された UAppUpdateOptions オブジェクトを取得したら、UInAppUpdatesManager::StartUpdate を呼び出してアップデート フローをリクエストできます。
MyClass.h
void MyClass::OnStartUpdateOperationCompleted(EAppUpdateErrorCode ErrorCode)
{
  // ...
}
MyClass.cpp
// .cpp
void MyClass::StartUpdate()
{
  // Create a delegate to bind the callback function.
  FUpdateOperationCompletedDelegate Delegate;
  // Bind the completion handler (OnStartUpdateOperationCompleted) to the delegate.
  Delegate.BindDynamic(this, &MyClass::OnStartUpdateOperationCompleted);
  // Initiate the start update operation, passing the delegate to handle the result.
  GetGameInstance()
    ->GetSubsystem<UInAppUpdatesManager>()
    ->StartUpdate(UpdateInfo, UpdateOptions, Delegate);
}
フレキシブル アップデート フローでは、ダウンロードが正常に完了した後、アプリのアップデートのインストールをトリガーする必要があります。そのためには、次の例のように InAppUpdatesManager::CompleteUpdate を呼び出します。
MyClass.h
void MyClass::OnCompleteUpdateOperationCompleted(EAppUpdateErrorCode ErrorCode)
{
  // ...
}
MyClass.cpp
void MyClass::CompleteFlexibleUpdate()
{
  // Create a delegate to bind the callback function.
  FUpdateOperationCompletedDelegate Delegate;
  // Bind the completion handler (OnCompleteUpdateOperationCompleted) to the delegate.
  Delegate.BindDynamic(this, &MyClass::OnCompleteUpdateOperationCompleted);
  // Initiate the complete update operation, passing the delegate to handle the result.
  GetGameInstance()
    ->GetSubsystem<UInAppUpdatesManager>()
    ->CompleteUpdate(UpdateInfo, UpdateOptions, Delegate);
}
即時アップデートの処理
最新の UAppUpdateInfo オブジェクトと適切に構成された UAppUpdateOptions オブジェクトを取得したら、InAppUpdatesManager::StartUpdate を呼び出してアップデート フローをリクエストできます。
MyClass.h
void MyClass::OnStartUpdateOperationCompleted(EAppUpdateErrorCode ErrorCode)
{
  // ...
}
MyClass.cpp
void MyClass::StartUpdate()
{
  // Create a delegate to bind the callback function.
  FUpdateOperationCompletedDelegate Delegate;
  // Bind the completion handler (OnStartUpdateOperationCompleted) to the delegate.
  Delegate.BindDynamic(this, &MyClass::OnStartUpdateOperationCompleted);
  // Initiate the start update operation, passing the delegate to handle the result.
  GetGameInstance()
    ->GetSubsystem<UInAppUpdatesManager>()
    ->StartUpdate(UpdateInfo, UpdateOptions, Delegate);
}
即時アップデート フローの場合、Google Play にはユーザーの確認ダイアログが表示されます。ユーザーがリクエストを承認すると、Google Play はアップデートのダウンロードとインストールを自動的に行い、インストールが成功すると更新後のバージョンでアプリを再起動します。
エラー処理
このセクションでは、一般的なエラーに対する解決策について説明します。
- UInAppUpdatesManager::StartUpdateが- AppUpdate_INVALID_REQUESTエラーを返した場合、- UAppUpdateInfoが無効であることを意味します。アップデート フローを開始する前に、- UInAppUpdatesManager::RequestInfoから返された- UAppUpdateInfoオブジェクトが null でないことを確認してください。
- UInAppUpdatesManager::StartUpdateが- AppUpdate_NOT_ALLOWEDエラーを返した場合、- UAppUpdateOptionsオブジェクトが、利用可能なアップデートで許可されていない更新タイプを示していることを意味します。アップデート フローを開始する前に、選択したアップデート タイプが許可されていることを- UAppUpdateInfoオブジェクトが示しているかどうかを確認してください。
次のステップ
アプリのアプリ内アップデートをテストして、統合が正しく機能していることを確認します。
