# Unity SDK のチュートリアル

> Use the Cloud Save Software Development Kit to save and load player data, game data, and files in your Unity project.

このチュートリアルは、Unity で Cloud Save SDK を使用してデータの保存とロードを行う方法を示しています。

> **Note:**
>
> **ノート**: これらの機能は、Cloud Save SDK のバージョン 3 から利用できます。

## Unity からの Cloud Save の使用##using-cloud-save-from-unity

Cloud Save SDK は、Unity 内で C# スクリプトから呼び出すことができます。

1. Unity 内で C# MonoBehaviour スクリプトを作成します。
2. Cloud Save との間でデータを保存/ロードするコードを追加します (以下の例を参照してください)。
3. 新しく作成したスクリプトをゲームオブジェクトにアタッチします。
4. **Play** (再生) を選択してプロジェクトを実行し、Cloud Save の動作を体験します。

Unity でのスクリプティングの詳細については、[スクリプトの作成と使用](https://docs.unity3d.com/Manual/CreatingAndUsingScripts.html) を参照してください。

### SDK サンプル##sdk-sample

SDK に含まれている `CloudSaveSample` スクリプトは、このチュートリアルで紹介している例を拡張したものです。このサンプルは、Unity で **Package Manager** > **Cloud Save** > **Samples** (サンプル) を選択すると見つかります。

## 認証の例##example-with-authentication

以下の例は、Authentication パッケージを使用して匿名認証でプレイヤーをサインインし、Cloud Save を初期化し、Cloud Save を使用してデータの保存とロードを行うメソッドを提供する方法を示しています。

```cs
using UnityEngine;
using Unity.Services.Core;
using Unity.Services.Authentication;
using Unity.Services.CloudSave;
using Unity.Services.CloudSave.Models;
using Unity.Services.CloudSave.Models.Data.Player;
using SaveOptions = Unity.Services.CloudSave.Models.Data.Player.SaveOptions;
using System.Collections.Generic;

public class CloudSaveSample : MonoBehaviour
{
    private async void Awake()
    {
        await UnityServices.InitializeAsync();
        await AuthenticationService.Instance.SignInAnonymouslyAsync();
    }

    public async void SaveData()
    {
        var playerData = new Dictionary<string, object>{
          {"firstKeyName", "a text value"},
          {"secondKeyName", 123}
        };
        await CloudSaveService.Instance.Data.Player.SaveAsync(playerData);
        Debug.Log($"Saved data {string.Join(',', playerData)}");
    }

    public async void LoadData()
    {
        var playerData = await CloudSaveService.Instance.Data.Player.LoadAsync(new HashSet<string> {
          "firstKeyName", "secondKeyName"
        });

        if (playerData.TryGetValue("firstKeyName", out var firstKey)) {
            Debug.Log($"firstKeyName value: {firstKey.Value.GetAs<string>()}");
        }

        if (playerData.TryGetValue("secondKeyName", out var secondKey)) {
            Debug.Log($"secondKey value: {secondKey.Value.GetAs<int>()}");
        }
    }
}
```

## プレイヤーデータ##player-data

プレイヤーのデータは、Unity Dashboard で表示、編集、削除できます。

### 項目を保存する##save-an-item

1 つ以上の項目を保存するには、`SaveAsync` メソッドを使用します。

```cs
public async void SaveData()
{
    var data = new Dictionary<string, object>{{"keyName", "value"}};
    await CloudSaveService.Instance.Data.Player.SaveAsync(data);
}
```

データを他のプレイヤーが読み取ることができるようにする場合は、そのデータを公開アクセスクラスで保存します。

```cs
public async void SavePublicData()
{
    var data = new Dictionary<string, object>{{"keyName", "value"}};
    await CloudSaveService.Instance.Data.Player.SaveAsync(data, new SaveOptions(new PublicWriteAccessClassOptions()));
}
```

### データをフェッチする##fetch-data

プレイヤーデータとして保存されているキーと値は、`LoadAsync` メソッドを使用して取得します。

```cs
public async void LoadData()
{
    var playerData = await CloudSaveService.Instance.Data.Player.LoadAsync(new HashSet<string>{"keyName"});
    if (playerData.TryGetValue("keyName", out var keyName)) {
        Debug.Log($"keyName: {keyName.Value.GetAs<string>()}");
    }
}
```

**公開** および **保護済み** アクセスクラスのデータのキーと値を取得できます。

```cs
public async void LoadPublicData()
{
  var playerData = await CloudSaveService.Instance.Data.Player.LoadAsync(new HashSet<string>{"keyName"}, new LoadOptions(new PublicReadAccessClassOptions()));
  if (playerData.TryGetValue("keyName", out var keyName)) {
      Debug.Log($"keyName: {keyName.Value.GetAs<string>()}");
  }
}
```

```cs
public async void LoadProtectedData()
{
  var playerData = await CloudSaveService.Instance.Data.Player.LoadAsync(new HashSet<string>{"keyName"}, new LoadOptions(new ProtectedReadAccessClassOptions()));
  if (playerData.TryGetValue("keyName", out var keyName)) {
      Debug.Log($"keyName: {keyName.Value.GetAs<string>()}");
  }
}
```

他のプレイヤーの **公開** アクセスクラスのデータは、プレイヤー ID を渡すことで読み取ることができます (ただし、書き込むことはできません)。

```cs
public async void LoadPublicDataByPlayerId()
{
  var playerId = "JE1unrWOOzzbIwy3Nl60fRefuiVE";
  var playerData = await CloudSaveService.Instance.Data.Player.LoadAsync(new HashSet<string>{"keyName"}, new LoadOptions(new PublicReadAccessClassOptions(playerId)));
  if (playerData.TryGetValue("keyName", out var keyName)) {
      Debug.Log($"keyName: {keyName.Value.GetAs<string>()}");
  }
}
```

### 項目を削除する##delete-an-item

項目を削除するには、`DeleteAsync` メソッドを使用します。

```cs
public async void DeleteData()
{
    await CloudSaveService.Instance.Data.Player.DeleteAsync("key");
}
```

### キーのリストを取得する##get-a-list-of-keys

キーのリストを取得するには、`ListAllKeysAsync` メソッドを使用します。

最後にキーが変更された日時などのメタデータをフェッチすることもできます。

```cs
public async void ListKeys()
{
    var keys = await CloudSaveService.Instance.Data.Player.ListAllKeysAsync();
    for (int i = 0; i < keys.Count; i++)
    {
        Debug.Log(keys[i].Key);
    }
}
```

**公開** および **保護済み** アクセスクラスのデータのキーのリストを取得することも可能です。

```cs
public async void ListKeys()
{
    var keys = await CloudSaveService.Instance.Data.Player.ListAllKeysAsync(
      new ListAllKeysOptions(new PublicReadAccessClassOptions())
    );
    for (int i = 0; i < keys.Count; i++)
    {
        Debug.Log(keys[i].Key);
    }
}
```

```cs
public async void ListKeys()
{
    var keys = await CloudSaveService.Instance.Data.Player.ListAllKeysAsync(
      new ListAllKeysOptions(new ProtectedReadAccessClassOptions())
    );
    for (int i = 0; i < keys.Count; i++)
    {
        Debug.Log(keys[i].Key);
    }
}
```

### プレイヤーデータに対してクエリを実行する##query-player-data

**公開** アクセスクラスのプレイヤーデータのインデックス化されたキーの値に対してクエリを実行できます。

> **Note:**
>
> インデックスの作成前に保存されたデータ (またはインデックスを作成するには大きすぎるデータ) はクエリで返されません。

```cs
public async void QueryPlayerData()
{
  var query = new Query(
    // The first argument to Query is a list of one or more filters, all must evaluate to true for a result to be included
    new List<FieldFilter>
    {
        new FieldFilter("indexedKeyName", "value", FieldFilter.OpOptions.EQ, true),
        new FieldFilter("anotherIndexedKeyName", "otherValue", FieldFilter.OpOptions.NE, true)
    },
    // The second (optional) argument is a list of keys you want to be included with their values in the response
    // This may include keys which are not part of the index, and does not need to include the index keys
    // If you don't specify any, you will still get back a list of IDs for Players that matched the query
    new HashSet<string>
    {
        "indexedKeyName"
    }
  );

  var results = await CloudSaveService.Instance.Data.Player.QueryAsync(query, new QueryOptions());

  Debug.Log($"Number of results from query: {results.Count}");
  results.ForEach(r =>
  {
      Debug.Log($"Player ID: {r.Id}");
      r.Data.ForEach(d => Debug.Log($"Key: {d.Key}, Value: {d.Value.GetAsString()}"));
  });
}
```

## ゲームデータ##game-data

プレイヤー固有でない **ゲームデータ** は、**カスタム項目** を使用して、保存およびロードを行うことができます。

> **Note:**
>
> ゲームクライアントが行うことができるのは、カスタム項目の読み取りのみです。カスタム項目の作成、変更、削除はできません。カスタム項目への書き込みは、Cloud Code、ゲームサーバー、HTTP API を使用するか、Unity Dashboard から行うことができます。

### データをフェッチする##fetch-data

カスタム項目のすべてのデータをフェッチするには、`LoadAllAsync` を使用します。

```cs
public async void LoadCustomItemData()
{
  var customItemId = 'my-custom-item';
  var customItemData = await CloudSaveService.Instance.Data.Custom.LoadAllAsync(customId);
  foreach (var customItem in customItemData)
  {
      Debug.Log($"Key: {customItem.Key}, Value: {customItem.Value.Value}");
  }
}
```

### カスタム項目に対してクエリを実行する##query-custom-items

**デフォルト** アクセスクラスのカスタム項目のインデックス化されたキーの値に対してクエリを実行できます。

> **Note:**
>
> インデックスの作成前に保存されたデータ (またはインデックスを作成するには大きすぎるデータ) はクエリで返されません。

```cs
public async void QueryCustomItems()
{
  var query = new Query(
    // The first argument to Query is a list of one or more filters, all must evaluate to true for a result to be included
    new List<FieldFilter>
    {
        new FieldFilter("indexedKeyName", "value", FieldFilter.OpOptions.EQ, true),
        new FieldFilter("anotherIndexedKeyName", "otherValue", FieldFilter.OpOptions.NE, true)
    },
    // The second (optional) argument is a list of keys you want to be included with their values in the response
    // This may include keys which are not part of the index, and does not need to include the index keys
    // If you don't specify any, you will still get back a list of IDs for Players that matched the query
    new HashSet<string>
    {
        "indexedKeyName"
    }
  );

  var results = await CloudSaveService.Instance.Data.Custom.QueryAsync(query);

  Debug.Log($"Number of results from query: {results.Count}");
  results.ForEach(r =>
  {
      Debug.Log($"Custom Item ID: {r.Id}");
      r.Data.ForEach(d => Debug.Log($"Key: {d.Key}, Value: {d.Value.GetAsString()}"));
  });
}
```

## プレイヤーファイル##player-files

[Cloud Save ファイル](/cloud-save/concepts/files.md) は、任意の形式のセーブファイル (最大 1 GB) を保存したり、複数のデバイス/プラットフォームからセーブゲームファイルにアクセスしたりする手段を提供します。

### プレイヤーファイルを保存する##save-player-file

デバイスにローカルに保存されているファイルを読み込み、Cloud Save に保存するには、`SaveAsync` メソッドを使用します。

```cs
public async void SavePlayerFile()
{
    byte[] file = System.IO.File.ReadAllBytes("fileName.txt");
    await CloudSaveService.Instance.Files.Player.SaveAsync("fileName", file);
}
```

### プレイヤーファイルを削除する##delete-player-file

プレイヤーファイルを削除するには、`DeleteAsync` メソッドを使用します。

```cs
public async void DeletePlayerFile()
{
    await CloudSaveService.Instance.Files.Player.DeleteAsync("fileName");
}
```

### プレイヤーファイルをリスト表示する##list-player-files

プレイヤーの全ファイルの名前のリストを取得するには、`ListAllAsync` メソッドを使用します。

```cs
public async void ListPlayerFiles()
{
    List<FileItem> files = await CloudSaveService.Instance.Files.Player.ListAllAsync();
    for (int i = 0; i < files.Count; i++)
    {
        Debug.Log(files[i]);
    }
}
```

### プレイヤーファイルをバイト配列として取得する##get-player-file-as-a-byte-array

プレイヤーファイルをバイト配列として取得するには、`LoadBytesAsync` メソッドを使用します。

```cs
public async void GetPlayerFileAsByteArray()
{
    byte[] file = await CloudSaveService.Instance.Files.Player.LoadBytesAsync("fileName");
}
```

### プレイヤーファイルをストリームとして取得する##get-player-file-as-a-stream

プレイヤーファイルをストリームとして取得するには、`LoadStreamAsync` メソッドを使用します。

```cs
public async void GetPlayerFileAsStream()
{
    Stream file = await CloudSaveService.Instance.Files.Player.LoadStreamAsync("fileName");
}
```

### プレイヤーファイルのメタデータを取得する##get-player-file-metadata

1 つのプレイヤーファイルのメタデータ (サイズ、最終変更日、最終作成日、キー、コンテンツタイプ、現在の WriteLock) を取得するには、`GetMetadataAsync` メソッドを使用します。

```cs
public async void GetPlayerFileMetadata()
{
    var metadata = await CloudSaveService.Instance.Files.Player.GetMetadataAsync("fileName");
    Debug.Log(metadata.Key);
    Debug.Log(metadata.Size);
    Debug.Log(metadata.ContentType);
    Debug.Log(metadata.Created);
    Debug.Log(metadata.LastModified);
    Debug.Log(metadata.WriteLock);
}
```

Unity Dashboard を使用すると、個々のプレイヤーのファイルにアクセスできます。これらのファイルは、Cloud Save モジュール内のプレイヤー詳細の下にあります。

## エラー処理##error-handling

エラー処理ロジックには、SDK がメソッドに対して返すエラーコードまたはエラータイプを使用します。

エラーメッセージは将来変更される可能性があるため、使用しないでください。
