> For the complete documentation index, see [llms.txt](/llms.txt)

# GS2-Datastore SDK for Game Engine API リファレンス

ゲームエンジン向け GS2-Datastore SDK の モデルの仕様 と API のリファレンス



## モデル

### EzDataObject

データオブジェクト<br>

データオブジェクトはゲームプレイヤーがアップロードしたデータです。<br>
データは世代管理され、30日分の過去のデータも保管されます。<br>

データにはアクセス権限を設定できます。<br>
スコープには3種類あり、<br>
- だれでもアクセスできる `public`<br>
- 指定したユーザーIDのゲームプレイヤーのみがアクセスできる `protected`<br>
- 自身のみがアクセスできる `private`<br>

があります。

|  | 型 | 有効化条件 | 必須 | デフォルト | 値の制限 | 説明 |
| --- | --- | --- | --- | --- | --- | --- |
| dataObjectId | string |  | ※ |  |  ~ 1024文字 | データオブジェクトGRN<br>※ サーバーが自動で設定 |
| name | string |  | ✓ | UUID |  ~ 128文字 | データオブジェクトの名前<br>データオブジェクトを識別する一意な名前です。デフォルトでは UUID 形式で自動生成されます。ネームスペース内でアップロードされたデータの参照・管理に使用されます。 |
| userId | string |  | ✓ |  |  ~ 128文字 | ユーザーID |
| scope | 文字列列挙型<br>enum {<br>&nbsp;&nbsp;"public",<br>&nbsp;&nbsp;"protected",<br>&nbsp;&nbsp;"private"<br>}<br> |  |  | "private" |  | ファイルのアクセス権<br>このデータオブジェクトにアクセスできるユーザーを制御します。`public` は誰でもアクセス可能、`protected` は allowUserIds に指定されたユーザーIDのみアクセス可能、`private` はオーナー本人のみアクセス可能です。"public": 公開 / "protected": 指定したユーザーにのみ公開 / "private": 非公開 /  |
| allowUserIds | List&lt;string&gt; | {scope} == "protected" |  | [] | 0 ~ 100 items | 公開するユーザーIDリスト<br>スコープが `protected` に設定されている場合に、このデータオブジェクトにアクセスできるユーザーを指定します。このリストに含まれるユーザーIDのユーザーのみが読み取りアクセスを許可されます。<br><br>※ scope が "protected" であれば 有効 |
| status | 文字列列挙型<br>enum {<br>&nbsp;&nbsp;"ACTIVE",<br>&nbsp;&nbsp;"UPLOADING",<br>&nbsp;&nbsp;"DELETED"<br>}<br> |  | ✓ |  |  | 状態<br>データオブジェクトの現在のライフサイクル状態です。`ACTIVE` はデータがアクセス可能であることを示し、`UPLOADING` は新しいバージョンがアップロード中であることを示し、`DELETED` は削除済みであることを示します（実際の削除は30日後に行われます）。"ACTIVE": 有効 / "UPLOADING": アップロード中 / "DELETED": 削除済み(削除処理から30日後に実際に削除) /  |
| generation | string |  |  |  |  ~ 128文字 | データの世代<br>アップロードされたデータの現在のバージョンを表す識別子です。データが再アップロードされるたびに新しい世代IDが割り当てられます。 |
| createdAt | long |  | ※ | 現在時刻 |  | 作成日時<br>UNIX 時間・ミリ秒<br>※ サーバーが自動で設定 |
| updatedAt | long |  | ※ | 現在時刻 |  | 最終更新日時<br>UNIX 時間・ミリ秒<br>※ サーバーが自動で設定 |

**関連するメソッド:**
deleteDataObject - アップロードしたファイルを削除する
doneUpload - ファイルのアップロードを確定する
listMyDataObjects - プレイヤーがアップロードしたデータの一覧を取得する
prepareDownload - ファイルのダウンロード URL を取得する（データオブジェクトIDで指定）
prepareDownloadByUserIdAndDataObjectName - 他プレイヤーのファイルのダウンロード URL を取得する（ユーザーIDと名前で指定）
prepareDownloadOwnData - プレイヤー自身のファイルのダウンロード URL を取得する（名前で指定）
prepareReUpload - 既存ファイルの再アップロード（上書き）を準備する
prepareUpload - 新しいファイルのアップロードを準備する
restoreDataObject - データオブジェクトの管理情報を修復する
updateDataObject - データオブジェクトのアクセス設定を変更する


---

### EzDataObjectHistory

データオブジェクト履歴<br>

データオブジェクトの更新履歴が確認できます。<br>
データオブジェクトが再アップロードされるたびに、世代IDとファイルサイズを含む履歴レコードが作成されます。履歴データは30日間保持され、以前のバージョンへのロールバックや監査が可能です。

|  | 型 | 有効化条件 | 必須 | デフォルト | 値の制限 | 説明 |
| --- | --- | --- | --- | --- | --- | --- |
| dataObjectHistoryId | string |  | ※ |  |  ~ 1024文字 | データオブジェクト履歴GRN<br>※ サーバーが自動で設定 |
| generation | string |  | ✓ |  |  ~ 128文字 | 世代ID<br>アップロード時点のデータオブジェクトの特定バージョンを示す一意な識別子です。DataObject の generation フィールドに対応し、PrepareDownloadByGeneration でこの特定バージョンをダウンロードする際に使用できます。 |
| contentLength | long |  | ✓ |  | 0 ~ 10485760 | データサイズ<br>この世代のアップロードデータのサイズ（バイト単位）です。最大ファイルサイズは 10 MB（10,485,760 バイト）です。 |
| createdAt | long |  | ※ | 現在時刻 |  | 作成日時<br>UNIX 時間・ミリ秒<br>※ サーバーが自動で設定 |

**関連するメソッド:**
listDataObjectHistories - データオブジェクトのバージョン履歴を取得する


---

## メソッド

### deleteDataObject

アップロードしたファイルを削除する<br>

指定したデータオブジェクトを削除予定としてマークします。実際のファイルは30日後に削除されます。<br>
プレイヤーが不要になったセーブデータやアップロード済みコンテンツを削除するときに使います。

#### Request

|  | 型 | 有効化条件 | 必須 | デフォルト | 値の制限 | 説明 |
| --- | --- | --- | --- | --- | --- | --- |
| namespaceName | string |  | ✓|  |  ~ 128文字 | ネームスペース名<br>ネームスペース固有の名前。英数字および -(ハイフン) _(アンダースコア) .(ピリオド)で指定します。 |
| gameSession | GameSession | | ✓|  |  | GameSession |
| dataObjectName | string |  | ✓| UUID |  ~ 128文字 | データオブジェクトの名前<br>データオブジェクトを識別する一意な名前です。デフォルトでは UUID 形式で自動生成されます。ネームスペース内でアップロードされたデータの参照・管理に使用されます。 |

#### Result

|  | 型 | 説明 |
| --- | --- | --- |
| item | [EzDataObject](#ezdataobject) | データオブジェクト|

#### Error

このAPIには特別な例外が定義されています。<br>
GS2-SDK for Game Engine ではゲーム内でハンドリングが必要そうなエラーは一般的な例外から派生した特殊化した例外を用意することでハンドリングしやすくしています。<br>
一般的なエラーの種類や、ハンドリング方法は [こちら]() のドキュメントを参考にしてください。

| 型 | 基底クラス | 説明 |
| --- | --- | --- |
| InvalidStatusException | BadRequestException | DataObject が操作可能な状態ではありません |

#### 実装例




**Unity (UniTask)**
```csharp

try {
    var domain = gs2.Datastore.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).DataObject(
        dataObjectName: "dataObject-0001"
    );
    var result = await domain.DeleteDataObjectAsync(
    );
    var item = await result.ModelAsync();
} catch(Gs2.Gs2Datastore.Exception.InvalidStatusException e) {
    // DataObject is not in operable state.
}

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Datastore.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).DataObject(
        dataObjectName: "dataObject-0001"
    );
    var future = domain.DeleteDataObjectFuture(
    );
    yield return future;
    if (future.Error != null)
    {
        if (future.Error is Gs2.Gs2Datastore.Exception.InvalidStatusException)
        {
            // DataObject is not in operable state.
        }
        onError.Invoke(future.Error, null);
        yield break;
    }
    var future2 = future.Result.ModelFuture();
    yield return future2;
    if (future2.Error != null)
    {
        onError.Invoke(future2.Error, null);
        yield break;
    }
    var result = future2.Result;

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Datastore->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->DataObject(
        "dataObject-0001" // dataObjectName
    );
    const auto Future = Domain->DeleteDataObject(
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        auto e = Future->GetTask().Error();
        if (e->IsChildOf(Gs2::Datastore::Error::FInvalidStatusError::Class))
        {
            // DataObject is not in operable state.
        }
        return false;
    }

    // obtain changed values / result values
    const auto Future2 = Future->GetTask().Result()->Model();
    Future2->StartSynchronousTask();
    if (Future2->GetTask().IsError())
    {
        return Future2->GetTask().Error();
    }
    const auto Result = Future2->GetTask().Result();

```


---

### doneUpload

ファイルのアップロードを確定する<br>

PrepareUpload または PrepareReUpload で取得した URL へのファイルアップロードが完了したあとに呼び出します。<br>
アップロードを確定し、データオブジェクトをダウンロード可能な状態（ステータス `ACTIVE`）にします。<br>
この呼び出しを行わないと、データオブジェクトは `UPLOADING` のままダウンロードできません。

#### Request

|  | 型 | 有効化条件 | 必須 | デフォルト | 値の制限 | 説明 |
| --- | --- | --- | --- | --- | --- | --- |
| namespaceName | string |  | ✓|  |  ~ 128文字 | ネームスペース名<br>ネームスペース固有の名前。英数字および -(ハイフン) _(アンダースコア) .(ピリオド)で指定します。 |
| gameSession | GameSession | | ✓|  |  | GameSession |
| dataObjectName | string |  | ✓| UUID |  ~ 128文字 | データオブジェクトの名前<br>データオブジェクトを識別する一意な名前です。デフォルトでは UUID 形式で自動生成されます。ネームスペース内でアップロードされたデータの参照・管理に使用されます。 |

#### Result

|  | 型 | 説明 |
| --- | --- | --- |
| item | [EzDataObject](#ezdataobject) | データオブジェクト|

#### Error

このAPIには特別な例外が定義されています。<br>
GS2-SDK for Game Engine ではゲーム内でハンドリングが必要そうなエラーは一般的な例外から派生した特殊化した例外を用意することでハンドリングしやすくしています。<br>
一般的なエラーの種類や、ハンドリング方法は [こちら]() のドキュメントを参考にしてください。

| 型 | 基底クラス | 説明 |
| --- | --- | --- |
| InvalidStatusException | BadRequestException | DataObject が操作可能な状態ではありません |
| NotUploadedException | BadRequestException | DataObject がアップロードされていません |

#### 実装例




**Unity (UniTask)**
```csharp

try {
    var domain = gs2.Datastore.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).DataObject(
        dataObjectName: "dataObject-0001"
    );
    var result = await domain.DoneUploadAsync(
    );
    var item = await result.ModelAsync();
} catch(Gs2.Gs2Datastore.Exception.InvalidStatusException e) {
    // DataObject is not in operable state.
} catch(Gs2.Gs2Datastore.Exception.NotUploadedException e) {
    // DataObject is not uploaded.
}

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Datastore.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).DataObject(
        dataObjectName: "dataObject-0001"
    );
    var future = domain.DoneUploadFuture(
    );
    yield return future;
    if (future.Error != null)
    {
        if (future.Error is Gs2.Gs2Datastore.Exception.InvalidStatusException)
        {
            // DataObject is not in operable state.
        }
        if (future.Error is Gs2.Gs2Datastore.Exception.NotUploadedException)
        {
            // DataObject is not uploaded.
        }
        onError.Invoke(future.Error, null);
        yield break;
    }
    var future2 = future.Result.ModelFuture();
    yield return future2;
    if (future2.Error != null)
    {
        onError.Invoke(future2.Error, null);
        yield break;
    }
    var result = future2.Result;

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Datastore->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->DataObject(
        "dataObject-0001" // dataObjectName
    );
    const auto Future = Domain->DoneUpload(
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        auto e = Future->GetTask().Error();
        if (e->IsChildOf(Gs2::Datastore::Error::FInvalidStatusError::Class))
        {
            // DataObject is not in operable state.
        }
        if (e->IsChildOf(Gs2::Datastore::Error::FNotUploadedError::Class))
        {
            // DataObject is not uploaded.
        }
        return false;
    }

    // obtain changed values / result values
    const auto Future2 = Future->GetTask().Result()->Model();
    Future2->StartSynchronousTask();
    if (Future2->GetTask().IsError())
    {
        return Future2->GetTask().Error();
    }
    const auto Result = Future2->GetTask().Result();

```


---

### listMyDataObjects

プレイヤーがアップロードしたデータの一覧を取得する<br>

プレイヤーがアップロードしたデータオブジェクト（ファイル）の一覧を取得します。<br>
ステータスでフィルタリングできます: `ACTIVE`（ダウンロード可能）、`UPLOADING`（アップロード中）、`DELETED`（削除予定）。<br>
セーブデータ一覧画面の表示や、プレイヤーが保存しているファイルの確認に使います。

#### Request

|  | 型 | 有効化条件 | 必須 | デフォルト | 値の制限 | 説明 |
| --- | --- | --- | --- | --- | --- | --- |
| namespaceName | string |  | ✓|  |  ~ 128文字 | ネームスペース名<br>ネームスペース固有の名前。英数字および -(ハイフン) _(アンダースコア) .(ピリオド)で指定します。 |
| gameSession | GameSession | | ✓|  |  | GameSession |
| status | 文字列列挙型<br>enum {<br>&nbsp;&nbsp;"ACTIVE",<br>&nbsp;&nbsp;"UPLOADING",<br>&nbsp;&nbsp;"DELETED"<br>}<br> |  | |  |  | 状態"ACTIVE": 有効 / "UPLOADING": アップロード中 / "DELETED": 削除済み(削除処理から30日後に実際に削除) /  |
| pageToken | string |  | |  |  ~ 1024文字 | データの取得を開始する位置を指定するトークン |
| limit | int |  | | 30 | 1 ~ 1000 | データの取得件数 |

#### Result

|  | 型 | 説明 |
| --- | --- | --- |
| items | [List&lt;EzDataObject&gt;](#ezdataobject) | データオブジェクトのリスト|
| nextPageToken | string | リストの続きを取得するためのページトークン|

#### 実装例




**Unity (UniTask)**
```csharp
    var domain = gs2.Datastore.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    );
    var items = await domain.DataObjectsAsync(
        status: "ACTIVE"
    ).ToListAsync();

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Datastore.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    );
    var it = domain.DataObjects(
        status: "ACTIVE"
    );
    List<EzDataObject> items = new List<EzDataObject>();
    while (it.HasNext())
    {
        yield return it.Next();
        if (it.Error != null)
        {
            onError.Invoke(it.Error, null);
            break;
        }
        if (it.Current != null)
        {
            items.Add(it.Current);
        }
        else
        {
            break;
        }
    }

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Datastore->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    );
    const auto It = Domain->DataObjects(
        "ACTIVE" // status
    );
    TArray<Gs2::UE5::Datastore::Model::FEzDataObjectPtr> Result;
    for (auto Item : *It)
    {
        if (Item.IsError())
        {
            return false;
        }
        Result.Add(Item.Current());
    }

```


##### 値の変更イベントハンドリング




**Unity (UniTask)**
```csharp
    var domain = gs2.Datastore.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    );
    
    // イベントハンドリングを開始
    var callbackId = domain.SubscribeDataObjects(
        () => {
            // リストの要素が変化した時に呼び出される
        }
    );

    // イベントハンドリングを停止
    domain.UnsubscribeDataObjects(callbackId);

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Datastore.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    );
    
    // イベントハンドリングを開始
    var callbackId = domain.SubscribeDataObjects(
        () => {
            // リストの要素が変化した時に呼び出される
        }
    );

    // イベントハンドリングを停止
    domain.UnsubscribeDataObjects(callbackId);

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Datastore->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    );
    
    // イベントハンドリングを開始
    const auto CallbackId = Domain->SubscribeDataObjects(
        []() {
            // リストの要素が変化した時に呼び出される
        }
    );

    // イベントハンドリングを停止
    Domain->UnsubscribeDataObjects(CallbackId);

```


{{% alert title="Warning" color="warning" %}}このイベントはSDKがもつローカルキャッシュの値が変更された時に呼び出されます。

ローカルキャッシュは SDK が持つ API の実行、または GS2-Gateway の通知を有効にした GS2-Distributor 経由でのスタンプシートの実行、または GS2-Gateway の通知を有効にした GS2-JobQueue の実行によって変化したもののみが対象となります。

そのため、これらの方法以外で値が変更されてもコールバックは呼び出されません。
{{% /alert %}}

---

### prepareDownload

ファイルのダウンロード URL を取得する（データオブジェクトIDで指定）<br>

指定したデータオブジェクトの一時的なダウンロード URL を返します。<br>
データオブジェクトは ID（GRN）で指定します。アクセス制御が適用され、ファイルのオーナーまたは許可リストに登録されたユーザーのみダウンロードできます。<br>
返された URL に HTTP GET でアクセスしてファイルをダウンロードします。

#### Request

|  | 型 | 有効化条件 | 必須 | デフォルト | 値の制限 | 説明 |
| --- | --- | --- | --- | --- | --- | --- |
| namespaceName | string |  | ✓|  |  ~ 128文字 | ネームスペース名<br>ネームスペース固有の名前。英数字および -(ハイフン) _(アンダースコア) .(ピリオド)で指定します。 |
| dataObjectId | string |  | ✓|  |  ~ 1024文字 | データオブジェクトGRN |
| gameSession | GameSession | | ✓|  |  | GameSession |

#### Result

|  | 型 | 説明 |
| --- | --- | --- |
| item | [EzDataObject](#ezdataobject) | データオブジェクト|
| fileUrl | string | ファイルをダウンロードするためのURL|
| contentLength | long | ファイルの容量|

#### 実装例




**Unity (UniTask)**
```csharp
    var domain = gs2.Datastore.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    );
    var result = await domain.PrepareDownloadAsync(
        dataObjectId: "grn:gs2:ap-northeast-1:YourOwnerId:datastore:namespace-0001:user:user-0001:data:dataObject-0001"
    );
    var item = await result.ModelAsync();
    var fileUrl = result.FileUrl;
    var contentLength = result.ContentLength;

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Datastore.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    );
    var future = domain.PrepareDownloadFuture(
        dataObjectId: "grn:gs2:ap-northeast-1:YourOwnerId:datastore:namespace-0001:user:user-0001:data:dataObject-0001"
    );
    yield return future;
    if (future.Error != null)
    {
        onError.Invoke(future.Error, null);
        yield break;
    }
    var future2 = future.Result.ModelFuture();
    yield return future2;
    if (future2.Error != null)
    {
        onError.Invoke(future2.Error, null);
        yield break;
    }
    var result = future2.Result;
    var fileUrl = future.Result.FileUrl;
    var contentLength = future.Result.ContentLength;

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Datastore->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    );
    const auto Future = Domain->PrepareDownload(
        "grn:gs2:ap-northeast-1:YourOwnerId:datastore:namespace-0001:user:user-0001:data:dataObject-0001" // dataObjectId
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }

    // obtain changed values / result values
    const auto Future2 = Future->GetTask().Result()->Model();
    Future2->StartSynchronousTask();
    if (Future2->GetTask().IsError())
    {
        return Future2->GetTask().Error();
    }
    const auto Result = Future2->GetTask().Result();
    const auto FileUrl = Result->FileUrl;
    const auto ContentLength = Result->ContentLength;

```


---

### prepareDownloadByUserIdAndDataObjectName

他プレイヤーのファイルのダウンロード URL を取得する（ユーザーIDと名前で指定）<br>

他のプレイヤーのデータを、ユーザーIDとデータオブジェクト名を指定してダウンロードします。<br>
アクセス制御が適用されます。データが `public` であるか、リクエストしたプレイヤーがオーナーの許可リストに含まれている必要があります。<br>
カスタムレベルやリプレイデータなど、プレイヤー同士でデータを共有する場合に使います。

#### Request

|  | 型 | 有効化条件 | 必須 | デフォルト | 値の制限 | 説明 |
| --- | --- | --- | --- | --- | --- | --- |
| namespaceName | string |  | ✓|  |  ~ 128文字 | ネームスペース名<br>ネームスペース固有の名前。英数字および -(ハイフン) _(アンダースコア) .(ピリオド)で指定します。 |
| userId | string |  | ✓|  |  ~ 128文字 | ユーザーID |
| dataObjectName | string |  | ✓| UUID |  ~ 128文字 | データオブジェクトの名前<br>データオブジェクトを識別する一意な名前です。デフォルトでは UUID 形式で自動生成されます。ネームスペース内でアップロードされたデータの参照・管理に使用されます。 |

#### Result

|  | 型 | 説明 |
| --- | --- | --- |
| item | [EzDataObject](#ezdataobject) | データオブジェクト|
| fileUrl | string | ファイルをダウンロードするためのURL|
| contentLength | long | ファイルの容量|

#### 実装例




**Unity (UniTask)**
```csharp
    var domain = gs2.Datastore.Namespace(
        namespaceName: "namespace-0001"
    ).User(
        userId: "user-0001"
    ).DataObject(
        dataObjectName: "dataObject-0001"
    );
    var result = await domain.PrepareDownloadByUserIdAndDataObjectNameAsync(
    );
    var item = await result.ModelAsync();
    var fileUrl = result.FileUrl;
    var contentLength = result.ContentLength;

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Datastore.Namespace(
        namespaceName: "namespace-0001"
    ).User(
        userId: "user-0001"
    ).DataObject(
        dataObjectName: "dataObject-0001"
    );
    var future = domain.PrepareDownloadByUserIdAndDataObjectNameFuture(
    );
    yield return future;
    if (future.Error != null)
    {
        onError.Invoke(future.Error, null);
        yield break;
    }
    var future2 = future.Result.ModelFuture();
    yield return future2;
    if (future2.Error != null)
    {
        onError.Invoke(future2.Error, null);
        yield break;
    }
    var result = future2.Result;
    var fileUrl = future.Result.FileUrl;
    var contentLength = future.Result.ContentLength;

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Datastore->Namespace(
        "namespace-0001" // namespaceName
    )->User(
        "user-0001" // userId
    )->DataObject(
        "dataObject-0001" // dataObjectName
    );
    const auto Future = Domain->PrepareDownloadByUserIdAndDataObjectName(
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }

    // obtain changed values / result values
    const auto Future2 = Future->GetTask().Result()->Model();
    Future2->StartSynchronousTask();
    if (Future2->GetTask().IsError())
    {
        return Future2->GetTask().Error();
    }
    const auto Result = Future2->GetTask().Result();
    const auto FileUrl = Result->FileUrl;
    const auto ContentLength = Result->ContentLength;

```


---

### prepareDownloadOwnData

プレイヤー自身のファイルのダウンロード URL を取得する（名前で指定）<br>

ID の代わりにデータオブジェクト名を指定して、プレイヤー自身のデータをダウンロードするための便利な方法です。<br>
プレイヤーが自分のセーブデータやアップロード済みコンテンツを読み込むときに使います。<br>
一時的なダウンロード URL とファイルサイズが返されます。

#### Request

|  | 型 | 有効化条件 | 必須 | デフォルト | 値の制限 | 説明 |
| --- | --- | --- | --- | --- | --- | --- |
| namespaceName | string |  | ✓|  |  ~ 128文字 | ネームスペース名<br>ネームスペース固有の名前。英数字および -(ハイフン) _(アンダースコア) .(ピリオド)で指定します。 |
| dataObjectName | string |  | ✓| UUID |  ~ 128文字 | データオブジェクトの名前<br>データオブジェクトを識別する一意な名前です。デフォルトでは UUID 形式で自動生成されます。ネームスペース内でアップロードされたデータの参照・管理に使用されます。 |
| gameSession | GameSession | | ✓|  |  | GameSession |

#### Result

|  | 型 | 説明 |
| --- | --- | --- |
| item | [EzDataObject](#ezdataobject) | データオブジェクト|
| fileUrl | string | ファイルをダウンロードするためのURL|
| contentLength | long | ファイルの容量|

#### 実装例




**Unity (UniTask)**
```csharp
    var domain = gs2.Datastore.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).DataObject(
        dataObjectName: "dataObject-0001"
    );
    var result = await domain.PrepareDownloadOwnDataAsync(
    );
    var item = await result.ModelAsync();
    var fileUrl = result.FileUrl;
    var contentLength = result.ContentLength;

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Datastore.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).DataObject(
        dataObjectName: "dataObject-0001"
    );
    var future = domain.PrepareDownloadOwnDataFuture(
    );
    yield return future;
    if (future.Error != null)
    {
        onError.Invoke(future.Error, null);
        yield break;
    }
    var future2 = future.Result.ModelFuture();
    yield return future2;
    if (future2.Error != null)
    {
        onError.Invoke(future2.Error, null);
        yield break;
    }
    var result = future2.Result;
    var fileUrl = future.Result.FileUrl;
    var contentLength = future.Result.ContentLength;

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Datastore->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->DataObject(
        "dataObject-0001" // dataObjectName
    );
    const auto Future = Domain->PrepareDownloadOwnData(
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }

    // obtain changed values / result values
    const auto Future2 = Future->GetTask().Result()->Model();
    Future2->StartSynchronousTask();
    if (Future2->GetTask().IsError())
    {
        return Future2->GetTask().Error();
    }
    const auto Result = Future2->GetTask().Result();
    const auto FileUrl = Result->FileUrl;
    const auto ContentLength = Result->ContentLength;

```


---



### prepareReUpload

既存ファイルの再アップロード（上書き）を準備する<br>

既存のデータオブジェクトの内容を差し替えるための新しいアップロード URL を返します。<br>
以前のファイルは履歴に残るので、世代番号を指定して古いバージョンをダウンロードすることもできます。<br>
返された URL に新しいファイルをアップロードしたあと、DoneUpload を呼んで確定します。<br>

**再アップロードの流れ:** PrepareReUpload → 返された URL に PUT でファイル送信 → DoneUpload

#### Request

|  | 型 | 有効化条件 | 必須 | デフォルト | 値の制限 | 説明 |
| --- | --- | --- | --- | --- | --- | --- |
| namespaceName | string |  | ✓|  |  ~ 128文字 | ネームスペース名<br>ネームスペース固有の名前。英数字および -(ハイフン) _(アンダースコア) .(ピリオド)で指定します。 |
| gameSession | GameSession | | ✓|  |  | GameSession |
| dataObjectName | string |  | ✓| UUID |  ~ 128文字 | データオブジェクトの名前<br>データオブジェクトを識別する一意な名前です。デフォルトでは UUID 形式で自動生成されます。ネームスペース内でアップロードされたデータの参照・管理に使用されます。 |
| contentType | string |  | | "application/octet-stream" |  ~ 256文字 | アップロードするデータの MIME-Type |

#### Result

|  | 型 | 説明 |
| --- | --- | --- |
| item | [EzDataObject](#ezdataobject) | データオブジェクト|
| uploadUrl | string | アップロード処理の実行に使用するURL|

#### 実装例




**Unity (UniTask)**
```csharp
    var domain = gs2.Datastore.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).DataObject(
        dataObjectName: "dataObject-0001"
    );
    var result = await domain.PrepareReUploadAsync(
        contentType: "application/octet-stream"
    );
    var item = await result.ModelAsync();
    var uploadUrl = result.UploadUrl;

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Datastore.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).DataObject(
        dataObjectName: "dataObject-0001"
    );
    var future = domain.PrepareReUploadFuture(
        contentType: "application/octet-stream"
    );
    yield return future;
    if (future.Error != null)
    {
        onError.Invoke(future.Error, null);
        yield break;
    }
    var future2 = future.Result.ModelFuture();
    yield return future2;
    if (future2.Error != null)
    {
        onError.Invoke(future2.Error, null);
        yield break;
    }
    var result = future2.Result;
    var uploadUrl = future.Result.UploadUrl;

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Datastore->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->DataObject(
        "dataObject-0001" // dataObjectName
    );
    const auto Future = Domain->PrepareReUpload(
        "application/octet-stream" // contentType
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }

    // obtain changed values / result values
    const auto Future2 = Future->GetTask().Result()->Model();
    Future2->StartSynchronousTask();
    if (Future2->GetTask().IsError())
    {
        return Future2->GetTask().Error();
    }
    const auto Result = Future2->GetTask().Result();
    const auto UploadUrl = Result->UploadUrl;

```


---

### prepareUpload

新しいファイルのアップロードを準備する<br>

新しいデータオブジェクトを作成し、アップロード用の URL を返します。<br>
この API を呼んだあと、返された URL に HTTP PUT でファイルをアップロードし、DoneUpload を呼んで確定します。<br>
アクセス範囲（`public` または `protected`）や、ダウンロードを許可するユーザーを指定できます。<br>
`updateIfExists` を true にすると、同名のファイルが既にある場合はエラーにせず上書き更新します。<br>

**アップロードの流れ:** PrepareUpload → 返された URL に PUT でファイル送信 → DoneUpload

#### Request

|  | 型 | 有効化条件 | 必須 | デフォルト | 値の制限 | 説明 |
| --- | --- | --- | --- | --- | --- | --- |
| namespaceName | string |  | ✓|  |  ~ 128文字 | ネームスペース名<br>ネームスペース固有の名前。英数字および -(ハイフン) _(アンダースコア) .(ピリオド)で指定します。 |
| gameSession | GameSession | | ✓|  |  | GameSession |
| name | string |  | |  |  ~ 128文字 | データオブジェクトの名前<br>指定しなかった場合、自動的にUUIDが割り当てられます。 |
| scope | 文字列列挙型<br>enum {<br>&nbsp;&nbsp;"public",<br>&nbsp;&nbsp;"protected",<br>&nbsp;&nbsp;"private"<br>}<br> |  | | "private" |  | ファイルのアクセス権<br>このデータオブジェクトにアクセスできるユーザーを制御します。`public` は誰でもアクセス可能、`protected` は allowUserIds に指定されたユーザーIDのみアクセス可能、`private` はオーナー本人のみアクセス可能です。"public": 公開 / "protected": 指定したユーザーにのみ公開 / "private": 非公開 /  |
| contentType | string |  | | "application/octet-stream" |  ~ 256文字 | アップロードするデータの MIME-Type |
| allowUserIds | List&lt;string&gt; | {scope} == "protected" | | [] | 0 ~ 100 items | 公開するユーザーIDリスト<br>スコープが `protected` に設定されている場合に、このデータオブジェクトにアクセスできるユーザーを指定します。このリストに含まれるユーザーIDのユーザーのみが読み取りアクセスを許可されます。 |
| updateIfExists | bool |  | | false |  | 既にデータが存在する場合にエラーとするか、データを更新するか |

#### Result

|  | 型 | 説明 |
| --- | --- | --- |
| item | [EzDataObject](#ezdataobject) | データオブジェクト|
| uploadUrl | string | アップロード処理の実行に使用するURL|

#### 実装例




**Unity (UniTask)**
```csharp
    var domain = gs2.Datastore.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    );
    var result = await domain.PrepareUploadAsync(
        name: "dataObject-0001",
        scope: "public",
        contentType: "application/octet-stream",
        allowUserIds: null,
        updateIfExists: null
    );
    var item = await result.ModelAsync();
    var uploadUrl = result.UploadUrl;

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Datastore.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    );
    var future = domain.PrepareUploadFuture(
        name: "dataObject-0001",
        scope: "public",
        contentType: "application/octet-stream",
        allowUserIds: null,
        updateIfExists: null
    );
    yield return future;
    if (future.Error != null)
    {
        onError.Invoke(future.Error, null);
        yield break;
    }
    var future2 = future.Result.ModelFuture();
    yield return future2;
    if (future2.Error != null)
    {
        onError.Invoke(future2.Error, null);
        yield break;
    }
    var result = future2.Result;
    var uploadUrl = future.Result.UploadUrl;

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Datastore->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    );
    const auto Future = Domain->PrepareUpload(
        "dataObject-0001", // name
        "public", // scope
        "application/octet-stream" // contentType
        // allowUserIds
        // updateIfExists
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }

    // obtain changed values / result values
    const auto Future2 = Future->GetTask().Result()->Model();
    Future2->StartSynchronousTask();
    if (Future2->GetTask().IsError())
    {
        return Future2->GetTask().Error();
    }
    const auto Result = Future2->GetTask().Result();
    const auto UploadUrl = Result->UploadUrl;

```


---

### restoreDataObject

データオブジェクトの管理情報を修復する<br>

データオブジェクトのメタデータと実際のファイルの間の不整合を修正します。<br>
記録されているファイルサイズやバージョン番号が実際のファイルと一致しない場合（アップロードが中断された場合など）、メタデータを正しく修正します。<br>
通常は呼び出す必要はなく、アップロード中に問題が発生したときのリカバリ用です。

#### Request

|  | 型 | 有効化条件 | 必須 | デフォルト | 値の制限 | 説明 |
| --- | --- | --- | --- | --- | --- | --- |
| namespaceName | string |  | ✓|  |  ~ 128文字 | ネームスペース名<br>ネームスペース固有の名前。英数字および -(ハイフン) _(アンダースコア) .(ピリオド)で指定します。 |
| dataObjectId | string |  | ✓|  |  ~ 1024文字 | データオブジェクトGRN |

#### Result

|  | 型 | 説明 |
| --- | --- | --- |
| item | [EzDataObject](#ezdataobject) | データオブジェクト|

#### Error

このAPIには特別な例外が定義されています。<br>
GS2-SDK for Game Engine ではゲーム内でハンドリングが必要そうなエラーは一般的な例外から派生した特殊化した例外を用意することでハンドリングしやすくしています。<br>
一般的なエラーの種類や、ハンドリング方法は [こちら]() のドキュメントを参考にしてください。

| 型 | 基底クラス | 説明 |
| --- | --- | --- |
| InvalidStatusException | BadRequestException | DataObject が操作可能な状態ではありません |

#### 実装例




**Unity (UniTask)**
```csharp

try {
    var domain = gs2.Datastore.Namespace(
        namespaceName: "namespace-0001"
    );
    var result = await domain.RestoreDataObjectAsync(
        dataObjectId: "grn:gs2:ap-northeast-1:YourOwnerId:datastore:namespace-0001:user:user-0001:data:dataObject-0001"
    );
    var item = await result.ModelAsync();
} catch(Gs2.Gs2Datastore.Exception.InvalidStatusException e) {
    // DataObject is not in operable state.
}

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Datastore.Namespace(
        namespaceName: "namespace-0001"
    );
    var future = domain.RestoreDataObjectFuture(
        dataObjectId: "grn:gs2:ap-northeast-1:YourOwnerId:datastore:namespace-0001:user:user-0001:data:dataObject-0001"
    );
    yield return future;
    if (future.Error != null)
    {
        if (future.Error is Gs2.Gs2Datastore.Exception.InvalidStatusException)
        {
            // DataObject is not in operable state.
        }
        onError.Invoke(future.Error, null);
        yield break;
    }
    var future2 = future.Result.ModelFuture();
    yield return future2;
    if (future2.Error != null)
    {
        onError.Invoke(future2.Error, null);
        yield break;
    }
    var result = future2.Result;

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Datastore->Namespace(
        "namespace-0001" // namespaceName
    );
    const auto Future = Domain->RestoreDataObject(
        "grn:gs2:ap-northeast-1:YourOwnerId:datastore:namespace-0001:user:user-0001:data:dataObject-0001" // dataObjectId
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        auto e = Future->GetTask().Error();
        if (e->IsChildOf(Gs2::Datastore::Error::FInvalidStatusError::Class))
        {
            // DataObject is not in operable state.
        }
        return false;
    }

    // obtain changed values / result values
    const auto Future2 = Future->GetTask().Result()->Model();
    Future2->StartSynchronousTask();
    if (Future2->GetTask().IsError())
    {
        return Future2->GetTask().Error();
    }
    const auto Result = Future2->GetTask().Result();

```


---

### updateDataObject

データオブジェクトのアクセス設定を変更する<br>

アップロード済みのデータオブジェクトにアクセスできる範囲を変更します。<br>
スコープを `public`（誰でもダウンロード可能）と `protected`（指定ユーザーのみダウンロード可能）で切り替えたり、<br>
許可するユーザーIDのリストを更新したりできます。<br>
ファイルの中身は変更されません。ファイルを更新するには PrepareReUpload を使ってください。

#### Request

|  | 型 | 有効化条件 | 必須 | デフォルト | 値の制限 | 説明 |
| --- | --- | --- | --- | --- | --- | --- |
| namespaceName | string |  | ✓|  |  ~ 128文字 | ネームスペース名<br>ネームスペース固有の名前。英数字および -(ハイフン) _(アンダースコア) .(ピリオド)で指定します。 |
| gameSession | GameSession | | ✓|  |  | GameSession |
| scope | 文字列列挙型<br>enum {<br>&nbsp;&nbsp;"public",<br>&nbsp;&nbsp;"protected",<br>&nbsp;&nbsp;"private"<br>}<br> |  | | "private" |  | ファイルのアクセス権<br>このデータオブジェクトにアクセスできるユーザーを制御します。`public` は誰でもアクセス可能、`protected` は allowUserIds に指定されたユーザーIDのみアクセス可能、`private` はオーナー本人のみアクセス可能です。"public": 公開 / "protected": 指定したユーザーにのみ公開 / "private": 非公開 /  |
| allowUserIds | List&lt;string&gt; | {scope} == "protected" | | [] | 0 ~ 100 items | 公開するユーザーIDリスト<br>スコープが `protected` に設定されている場合に、このデータオブジェクトにアクセスできるユーザーを指定します。このリストに含まれるユーザーIDのユーザーのみが読み取りアクセスを許可されます。 |

#### Result

|  | 型 | 説明 |
| --- | --- | --- |
| item | [EzDataObject](#ezdataobject) | データオブジェクト|

#### 実装例




**Unity (UniTask)**
```csharp
    var domain = gs2.Datastore.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).DataObject(
        dataObjectName: "dataObject-0001"
    );
    var result = await domain.UpdateDataObjectAsync(
        scope: "public",
        allowUserIds: null
    );
    var item = await result.ModelAsync();

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Datastore.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).DataObject(
        dataObjectName: "dataObject-0001"
    );
    var future = domain.UpdateDataObjectFuture(
        scope: "public",
        allowUserIds: null
    );
    yield return future;
    if (future.Error != null)
    {
        onError.Invoke(future.Error, null);
        yield break;
    }
    var future2 = future.Result.ModelFuture();
    yield return future2;
    if (future2.Error != null)
    {
        onError.Invoke(future2.Error, null);
        yield break;
    }
    var result = future2.Result;

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Datastore->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->DataObject(
        "dataObject-0001" // dataObjectName
    );
    const auto Future = Domain->UpdateDataObject(
        "public" // scope
        // allowUserIds
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }

    // obtain changed values / result values
    const auto Future2 = Future->GetTask().Result()->Model();
    Future2->StartSynchronousTask();
    if (Future2->GetTask().IsError())
    {
        return Future2->GetTask().Error();
    }
    const auto Result = Future2->GetTask().Result();

```


---

### listDataObjectHistories

データオブジェクトのバージョン履歴を取得する<br>

データオブジェクトの過去のバージョン（世代）の一覧を取得します。<br>
PrepareReUpload でファイルを再アップロードするたびに、以前のバージョンが履歴に保存されます。<br>
各エントリにはファイルサイズと作成日時が含まれるので、いつ何が変わったかを確認できます。<br>
バージョン履歴画面の表示や、プレイヤーが古いセーブデータに戻す機能を実装する際に使います。

#### Request

|  | 型 | 有効化条件 | 必須 | デフォルト | 値の制限 | 説明 |
| --- | --- | --- | --- | --- | --- | --- |
| namespaceName | string |  | ✓|  |  ~ 128文字 | ネームスペース名<br>ネームスペース固有の名前。英数字および -(ハイフン) _(アンダースコア) .(ピリオド)で指定します。 |
| gameSession | GameSession | | ✓|  |  | GameSession |
| dataObjectName | string |  | ✓| UUID |  ~ 128文字 | データオブジェクトの名前<br>データオブジェクトを識別する一意な名前です。デフォルトでは UUID 形式で自動生成されます。ネームスペース内でアップロードされたデータの参照・管理に使用されます。 |
| pageToken | string |  | |  |  ~ 1024文字 | データの取得を開始する位置を指定するトークン |
| limit | int |  | | 30 | 1 ~ 1000 | データの取得件数 |

#### Result

|  | 型 | 説明 |
| --- | --- | --- |
| items | [List&lt;EzDataObjectHistory&gt;](#ezdataobjecthistory) | データオブジェクト履歴のリスト|
| nextPageToken | string | リストの続きを取得するためのページトークン|

#### 実装例




**Unity (UniTask)**
```csharp
    var domain = gs2.Datastore.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).DataObject(
        dataObjectName: "dataObject-0001"
    );
    var items = await domain.DataObjectHistoriesAsync(
    ).ToListAsync();

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Datastore.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).DataObject(
        dataObjectName: "dataObject-0001"
    );
    var it = domain.DataObjectHistories(
    );
    List<EzDataObjectHistory> items = new List<EzDataObjectHistory>();
    while (it.HasNext())
    {
        yield return it.Next();
        if (it.Error != null)
        {
            onError.Invoke(it.Error, null);
            break;
        }
        if (it.Current != null)
        {
            items.Add(it.Current);
        }
        else
        {
            break;
        }
    }

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Datastore->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->DataObject(
        "dataObject-0001" // dataObjectName
    );
    const auto It = Domain->DataObjectHistories(
    );
    TArray<Gs2::UE5::Datastore::Model::FEzDataObjectHistoryPtr> Result;
    for (auto Item : *It)
    {
        if (Item.IsError())
        {
            return false;
        }
        Result.Add(Item.Current());
    }

```


##### 値の変更イベントハンドリング




**Unity (UniTask)**
```csharp
    var domain = gs2.Datastore.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).DataObject(
        dataObjectName: "dataObject-0001"
    );
    
    // イベントハンドリングを開始
    var callbackId = domain.SubscribeDataObjectHistories(
        () => {
            // リストの要素が変化した時に呼び出される
        }
    );

    // イベントハンドリングを停止
    domain.UnsubscribeDataObjectHistories(callbackId);

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Datastore.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).DataObject(
        dataObjectName: "dataObject-0001"
    );
    
    // イベントハンドリングを開始
    var callbackId = domain.SubscribeDataObjectHistories(
        () => {
            // リストの要素が変化した時に呼び出される
        }
    );

    // イベントハンドリングを停止
    domain.UnsubscribeDataObjectHistories(callbackId);

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Datastore->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->DataObject(
        "dataObject-0001" // dataObjectName
    );
    
    // イベントハンドリングを開始
    const auto CallbackId = Domain->SubscribeDataObjectHistories(
        []() {
            // リストの要素が変化した時に呼び出される
        }
    );

    // イベントハンドリングを停止
    Domain->UnsubscribeDataObjectHistories(CallbackId);

```


{{% alert title="Warning" color="warning" %}}このイベントはSDKがもつローカルキャッシュの値が変更された時に呼び出されます。

ローカルキャッシュは SDK が持つ API の実行、または GS2-Gateway の通知を有効にした GS2-Distributor 経由でのスタンプシートの実行、または GS2-Gateway の通知を有効にした GS2-JobQueue の実行によって変化したもののみが対象となります。

そのため、これらの方法以外で値が変更されてもコールバックは呼び出されません。
{{% /alert %}}

---



