モジュール構造

Cloud Code モジュールは、ゲームクライアントが呼び出すことのできるエンドポイントを公開する単純な .NET プロジェクトです。モジュールは、同様のパラダイムを .NET クラスライブラリとして採用します。例えば、標準の C# クラスは以下のようになる場合があります。

namespace ModulesExample;

public class Example
{
    private static string[] GetCheatCodes()
    {
        return new string[]
        {
            "LEAVEMEALONE",
            "ASPIRINE",
            "BIGBANG"
        };
    }

    public void ChangeHaircut(string haircutName)
    {

    }
}

コンパイルされると、クラス Example への参照は ChangeHaircut() メソッドのみを使用できます。

using ModulesExample;

class UsageExample
{
    public void GameLoop()
    {
        Example.ChangeHaircut("buzzcut");

        // Compile error "Cannot access private method 'GetCheatCodes()' here"
        var cheatCodes = Example.GetCheatCodes();
    }
}

これにより、開発者はアクセスモディファイアを通じてライブラリのインターフェースを選択できます。Cloud Code モジュールは同じ方法で動作しますが、代わりに [CloudCodeFunction("ChangeHaircut")] 属性を使用します。

Cloud Code モジュールでは、自己包含サーバー主導型ライブラリを作成できます。これにより、サーバーでゲームロジックを実行し、それをクライアントから呼び出すことができるため、ゲームロジックがクライアントからデタッチされ、セキュリティが向上します。モジュールは、コードの再利用を提供し、ゲームロジックの管理に使用できるインターフェースを提供します。

C# プロジェクト

Cloud Code モジュールプロジェクトは、クラスライブラリ C# プロジェクトです。プロジェクトは、ソリューションの一部にすることもできます。最も単純なプロジェクト構造は以下のようになります。

├─ Main.csproj
    └─ Dependencies
    └─ HelloWorld.cs

または、ソリューション内の場合は、以下のようになります。

Sample.sln
├─ Main.csproj
    └─ Dependencies
    └─ HelloWorld.cs

ソリューションには、相互に参照する複数のプロジェクトを入れることもできます。これにより、テストプロジェクトを簡単に追加でき、コードの再利用が可能になります。以下の例は、有効なプロジェクト構造を示します。

Sample.sln
├─ Main.csproj
    └─ Dependencies
    └─ HelloWorld.cs
├─ Tests.csproj
    └─ Dependencies
    └─ Tests.cs
├─ Other.csproj
    └─ Dependencies
    └─ Class1.cs

ただし、Cloud Code 関数を入れることができるのはメインプロジェクトだけです。

Cloud Code モジュールの単体テストの記述方法については、単体テストの作成 を参照してください。

適用されるストレージ制限を確認するには、Cloud Code 制限 を参照してください。

メインプロジェクト

ソリューションには複数の C# プロジェクトを追加できますが、メインプロジェクトはモジュールごとに 1 つだけです。メインプロジェクトには、すべてのモジュールエントリーポイント (CloudCodeFunction 属性がある関数) が含まれます。

重要: メインプロジェクトの外部で任意の関数に CloudCodeFunction 属性を設定した場合、Cloud Code サービスはそれらをエントリーポイントとして認識できません。

メインプロジェクトは、ローカルフォルダーに公開し、アーカイブに圧縮して Cloud Code サービスにデプロイするプロジェクトでもあります。メインプロジェクトで参照されていないプロジェクトと依存関係は Cloud Code サービスにデプロイしません。

メインプロジェクトの名前は、Cloud Code サービスにデプロイするアーカイブの名前と一致する必要があります。

Cloud Code モジュールのコンパイルとパッケージ化の方法については、パッケージコード を参照してください。

ノート: 複数のメイン Cloud Code モジュールプロジェクトを含むソリューションを作成できます。この場合、各メインプロジェクトは異なるモジュールに対応します。

サンプルプロジェクト

最も単純なモジュールプロジェクトは、以下の構造を持ちます。

Sample.sln
├─ Main.csproj
    └─ Dependencies
    └─ HelloWorld.cs

以下のサンプルは、文字列 Hello World! を返す単一の関数 Hello で Cloud Code モジュールを定義します。

using Unity.Services.CloudCode.Core;

namespace Sample;

public class HelloWorld
{
    [CloudCodeFunction("Hello")]
    public string PrintHello()
    {
        return "Hello World!";
    }
}

Cloud Code NuGet パッケージ

.NET プロジェクトとして、Cloud Code モジュールプロジェクトはパッケージ化されたコードを共有するために NuGet も使用します。

NuGet の詳細については、Microsoft のドキュメント を参照してください。

Cloud Code は、モジュールに追加できる 2 つのパッケージを提供します。

  • com.Unity.Services.CloudCode.Core: このパッケージには、CloudCodeFunction 属性など、Cloud Code のコア機能が含まれています。すべての Cloud Code モジュールに、このパッケージが必要です。
  • com.Unity.Services.CloudCode.Apis: これは、Cloud Code サービスを操作するために使用できる Unity Gaming Services API を含む任意のパッケージです。このパッケージを使用して、Cloud Save などの他の Cloud Code SDK を呼び出すことができます。

詳細については、Jetbrains Rider または Visual Studio でプロジェクト内の NuGet パッケージをインストールして使用する方法に関するドキュメントを参照してください。

ノート: モジュールプロジェクトで使用する外部 NuGet パッケージをインストールすることもできます。詳細については、外部サービスとのインテグレーション を参照してください。

コード構造

コード構造の問題を回避するには、以下のガイドラインに従います。

メソッドシグネチャ

モジュール関数のメソッドシグネチャには以下の構造体を使用します。

[CloudCodeFunction("FunctionName")]
    public async Task<ReturnType> FunctionName(IGameApiClient gameApiClient, IExecutionContext ctx, string parameter1, string parameter2)
    {
        ...
    }
  • async void パターンはエラーの原因になります。常に Task または Task<T> を返します。
  • Cloud Code では、静的メソッドはサポートされません。

モジュールでのシングルトンパターンの使用

シングルトンパターンを使用して、Cloud Code C# パッケージと外部サービス呼び出しを統合できます。シングルトンパターンは、Cloud Code のパフォーマンスとスケーラビリティを改善し、同じオブジェクトの複数のインスタンスを作成しないようにします。

重要: 複数のワーカーが存在する場合、API 呼び出しが同じワーカー対象にする保証はないため、モジュール関数呼び出し間の共有状態に依存しないでください。

重要: Cloud Code ワーカーには 256 MB のメモリ制限があります。この制限を超えたワーカーは、最終的にクラッシュします。

CloudCodeFunction 属性

メソッドを Cloud Code 関数としてマークし、実行可能な Cloud Code モジュールエンドポイントにするには、CloudCodeFunction 属性を使用します。Cloud Code 関数属性は、モジュールのメインクラスでのみ使用できます。関数を呼び出すには、属性の名前を呼び出す必要があります。

IGameClient インターフェース

IGameClientApi インターフェースは、Cloud Code C# SDK にアクセスする方法を提供します。依存性注入 を使用して、モジュールに IGameApiClient を挿入します。

  1. ICloudCodeSetup インターフェースを実装するクラスを定義し、GameApiClient をシングルトンとして追加します。
    public class ModuleConfig : ICloudCodeSetup
        {
            public void Setup(ICloudCodeConfig config)
            {
                config.Dependencies.AddSingleton(GameApiClient.Create());
            }
        }
  2. IGameClient インターフェースを関数パラメーターとしてモジュール関数に渡します。

IPushClient インターフェース

IPushClient インターフェースは、プレイヤーにプッシュ通知を送信する方法を提供します。依存性注入 を使用して、モジュールに IPushClient を挿入します。

  1. ICloudCodeSetup インターフェースを実装するクラスを定義し、PushClient をシングルトンとして追加します。
    public class ModuleConfig : ICloudCodeSetup
        {
            public void Setup(ICloudCodeConfig config)
            {
                config.Dependencies.AddSingleton(PushClient.Create());
            }
        }
  2. PushClient オブジェクトを関数パラメーターとしてモジュール関数に渡します。

Cloud Code からプッシュメッセージを送信する方法の詳細については、プッシュメッセージ を参照してください。

IExecution コンテキスト

モジュール内の他の UGS サービスを呼び出すには、IExecutionContext インターフェースを使用して、現在の呼び出しに関する追加の情報を取得できます。以下の値を使用して、サービス SDK にアクセスし、どのプレイヤーがリクエストを行うかを確認できます。

  • ProjectId: 呼び出し元が認証されたプロジェクト ID。
  • PlayerId: スクリプトを実行したプレイヤー ID。ノート: サービスがスクリプトを呼び出す場合、プレイヤー ID は使用できません。
  • EnvironmentId: モジュールの環境 ID。
  • EnvironmentName: モジュールの環境名。
  • AccessToken: プレイヤーが Cloud Code を認証するために使用した JSON Web Token (JWT) 認証情報。
  • UserId: サービスアカウントのユーザー ID。(ノート: サービスがスクリプトを呼び出す場合、ユーザー ID は使用できません。)
  • Issuer: 発行者またはサービスアカウントトークン。(ノート: プレイヤーがスクリプトを呼び出す場合、発行者は使用できません。) 例えば、Multiplay が呼び出す場合、発行者は multiplay です。
  • ServiceToken: Cloud Code サービスアカウント JWT 認証情報。
  • AnalyticsUserId: プレイヤーの Analytics ユーザー ID。(ノート: サービスがスクリプトを呼び出す場合、分析ユーザー ID は使用できません。)
  • UnityInstallationId: プレイヤーの Unity デバイスインストール ID。(ノート: サービスがスクリプトを呼び出す場合、Unity インストール ID は使用できません。)

実行コンテキストを使用してプレイヤー ID を取得し、異なる Unity Gaming Services を認証できます。クラスのコンストラクタと、CloudCodeFunction 属性を指定したメソッドの両方を通じて、実行コンテキストを取得できます。

例えば、実行コンテキストを使用して Cloud Save を呼び出し、プレイヤーキーを取得できます。

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Unity.Services.CloudCode.Apis;
using Unity.Services.CloudCode.Core;
using Unity.Services.CloudCode.Shared;

namespace Sample;

public class HelloWorld
{
    private static ILogger<HelloWorld> _logger;
    public CloudSaveSdkSample(ILogger<HelloWorld> logger)
    {
        _logger = logger;
    }

    [CloudCodeFunction("GetData")]
    public async Task<object> GetData(IExecutionContext context, IGameApiClient gameApiClient, string key)
    {
        try
        {
            var result = await gameApiClient.CloudSaveData.GetItemsAsync(context, context.AccessToken,
                context.ProjectId, context.PlayerId, new List<string> { key });
            return result.Data.Results.First().Value;
        }
        catch (ApiException ex)
        {
            _logger.LogError("Failed to get data from Cloud Save. Error: {Error}", ex.Message);
            throw new Exception($"Failed to get data for playerId {ctx.PlayerId}. Error: {e.Message}");
        }
    }

    public class ModuleConfig : ICloudCodeSetup
    {
        public void Setup(ICloudCodeConfig config)
        {
            config.Dependencies.AddSingleton(GameApiClient.Create());
        }
    }


}

トークン認証

AccessTokenServiceTokenIExecutionContext インターフェースの JWT とプロパティです。

これらのトークンを使用して、Cloud Code から他の Unity Gaming Services の呼び出しを認証できます。

トークンタイプ発生元データアクセス使用方法
accessTokenAuthentication サービス によって生成されます。認証されたプレイヤーのみ。AccessToken は、Cloud Code 呼び出しを認証するために使用する JWT です。他の UGS サービスにトークンを渡して、認証されたプレイヤーのデータにアクセスできます。
serviceTokenCloud Code によって生成されます。クロスプレイヤーデータアクセス。ServiceToken は、他の UGS サービスを呼び出し、クロスプレイヤーデータを操作するために使用するトークンです。

設定する アクセス制御 ルールは AccessToken に影響します。

以下のサンプルは、AccessToken を使用して、Cloud Save で認証されたプレイヤーのデータにアクセスする方法を示します。

using Microsoft.Extensions.DependencyInjection;
using Unity.Services.CloudCode.Apis;
using Unity.Services.CloudCode.Core;
using Unity.Services.CloudCode.Shared;
using Unity.Services.CloudSave.Model;

namespace TokenSample;

public class TokenSample
{
    [CloudCodeFunction("GetKeysForAuthenticatedPlayer")]
    public  Task<ApiResponse<GetKeysResponse>> GetPlayerKeys(IExecutionContext ctx, IGameApiClient gameApiClient)
    {
        try
        {
            // Using ctx.AccessToken to access the data for the player calling the function
            return gameApiClient.CloudSaveData.GetKeysAsync(ctx, ctx.AccessToken, ctx.ProjectId, ctx.PlayerId);
        }
        catch (ApiException e)
        {
            throw new Exception($"Failed to get keys for playerId {ctx.PlayerId}. Error: {e.Message}");

        }
    }

    public class ModuleConfig : ICloudCodeSetup
    {
        public void Setup(ICloudCodeConfig config)
        {
            config.Dependencies.AddSingleton(GameApiClient.Create());
        }
    }
}

すべてのプレイヤーのデータにアクセスするには、ServiceToken を使用し、playerId のパラメーターを渡すことができます。

using Microsoft.Extensions.DependencyInjection;
using Unity.Services.CloudCode.Apis;
using Unity.Services.CloudCode.Core;
using Unity.Services.CloudCode.Shared;
using Unity.Services.CloudSave.Model;

namespace TokenSample;

public class TokenSample
{
    [CloudCodeFunction("GetKeysForAnyPlayer")]
    public  Task<ApiResponse<GetKeysResponse>> GetPlayerKeys(IExecutionContext ctx, IGameApiClient gameApiClient, string playerId)
    {
        try
        {
            // Using ctx.ServiceToken to access the data for any player
            return gameApiClient.CloudSaveData.GetKeysAsync(ctx, ctx.ServiceToken, ctx.ProjectId, playerId);
        } catch (ApiException e)
        {
            throw new Exception($"Failed to get keys for playerId {ctx.PlayerId}. Error: {e.Message}");
        }
    }

    public class ModuleConfig : ICloudCodeSetup
    {
        public void Setup(ICloudCodeConfig config)
        {
            config.Dependencies.AddSingleton(GameApiClient.Create());
        }
    }
}

2 つのトークンの違いの詳細な説明は、サービスとアクセストークン のドキュメントを参照してください。

Cloud Code モジュールメタデータ

Cloud Code モジュールとそのメタデータを取得するには、Cloud Code サービスに GET リクエストを送信します。レスポンスは、以下の構造を持つ JSON オブジェクトです。

{
  "name": "string",
  "language": "CS",
  "tags": {
    "property1": "string",
    "property2": "string"
  },
  "signedDownloadURL": "string",
  "dateCreated": "2022-04-05T09:12:13Z",
  "dateModified": "2022-04-05T09:12:13Z"
}

タグ

タグは、Cloud Code モジュールにアタッチできるキーと値のペアです。モジュールのバージョン、作成者、バージョン管理を使用する場合のコミットハッシュなど、必要な任意の情報をタグに記録できます。

モジュールでは最大 10 個のタグを格納でき、タグキーとタグ値ごとに使用できる最大文字数は 128 です。

ノート: UGS CLI は、サポートタグを提供せず、それらを無視します。

署名付きダウンロード URL

署名付きダウンロード URL は、モジュールアーカイブをダウンロードするために使用できる一時的な URL です。