모듈 구조
Understand the structure of a Cloud Code module project and how it exposes endpoints.
읽는 시간 4분최근 업데이트: 14시간 전
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) { }}
ExampleChangeHaircut()그러면 개발자가 액세스 한정자를 통해 라이브러리 인터페이스를 선택할 수 있습니다. Cloud Code 모듈도 동일한 방식으로 작동하나, 대신using ModulesExample;class UsageExample{ public void GameLoop() { Example.ChangeHaircut("buzzcut"); // Compile error "Cannot access private method 'GetCheatCodes()' here" var cheatCodes = Example.GetCheatCodes(); }}
[CloudCodeFunction("ChangeHaircut")]C# 프로젝트
Cloud Code 모듈 프로젝트는 클래스 라이브러리 C# 프로젝트이며, 프로젝트는 솔루션의 일부가 될 수도 있습니다. 가장 단순한 프로젝트 구조는 다음과 같습니다.또는 솔루션 안에서는 다음과 같을 수 있습니다.├─ Main.csproj└─ Dependencies└─ HelloWorld.cs
솔루션에는 서로를 참조하는 여러 프로젝트가 포함될 수 있습니다. 이를 통해 테스트 프로젝트를 쉽게 추가하고 코드를 재사용할 수 있습니다. 아래 예시는 유효한 프로젝트 구조를 보여 줍니다.Sample.sln├─ Main.csproj └─ Dependencies └─ HelloWorld.cs
하지만 Cloud Code 함수는 메인 프로젝트에만 포함할 수 있습니다. Cloud Code 모듈의 유닛 테스트를 작성하는 방법을 자세히 알아보려면 유닛 테스트 작성을 참고하십시오. 적용되는 스토리지 제한 사항을 확인하려면 Cloud Code 제한을 참고하십시오.Sample.sln├─ Main.csproj └─ Dependencies └─ HelloWorld.cs├─ Tests.csproj └─ Dependencies └─ Tests.cs├─ Other.csproj └─ Dependencies └─ Class1.cs
메인 프로젝트
솔루션에 여러 C# 프로젝트가 포함될 수 있지만 메인 프로젝트는 모듈당 하나만 있을 수 있습니다. 메인 프로젝트에는 모든 모듈 진입점(CloudCodeFunction
메인 프로젝트는 Cloud Code 서비스에 배포하는 프로젝트이기도 합니다. 메인 프로젝트에서 Cloud Code 서비스에 대해 참조되지 않은 프로젝트와 종속성은 배포하지 않습니다.
메인 프로젝트의 이름을 Cloud Code 서비스에 배포하는 아카이브의 이름과 일치시켜야 합니다.
샘플 프로젝트
가장 단순한 모듈 프로젝트에는 다음 구조가 포함될 수 있습니다.아래 샘플은 문자열Sample.sln├─ Main.csproj └─ Dependencies └─ HelloWorld.cs
Hello World!Hellousing 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는 모듈에 포함할 수 있는 다음 두 패키지를 제공합니다.- : 이 패키지에는
com.Unity.Services.CloudCode.Core속성을 포함하여 Cloud Code의 핵심 기능이 포함되어 있습니다. 모든 Cloud Code 모듈에는 이 패키지가 필요합니다.CloudCodeFunction - : Cloud Code 서비스와 상호 작용하는 데 사용할 수 있는 Unity Gaming Services API가 포함된 선택적 패키지입니다. 이 패키지를 사용하여 Cloud Save 등 다른 Cloud Code SDK를 호출할 수 있습니다.
com.Unity.Services.CloudCode.Apis
코드 구조
다음 가이드라인을 따라 코드 구조와 관련된 문제를 피합니다.CloudCodeFunction 속성
메서드를 Cloud Code 함수로 표시하고 실행 가능한 Cloud Code 모듈 엔드포인트로 만들려면CloudCodeFunction메서드 서명
모듈 함수의 메서드 서명에 아래 구조를 사용합니다.[CloudCodeFunction("FunctionName")]public async Task<ReturnType> FunctionName(IGameApiClient gameApiClient, IExecutionContext ctx, string parameter1, string parameter2){ ...}
모듈에 싱글톤 패턴 사용
Cloud Code C# 패키지 및 외부 서비스 호출과 연동하기 위해 싱글톤 패턴을 사용할 수 있습니다. 싱글톤 패턴을 사용하면 Cloud Code의 성능과 확장성이 개선되며 동일한 오브젝트의 인스턴스를 여러 개 생성하지 않아도 됩니다. 종속성 삽입을 사용하여IGameApiClientIPushClient파라미터에서 전달
파라미터에서 모듈 함수에 전달할 수 있습니다.기본형 및 복합형
여기에는intstringboolfloatList<T>Dictionary<T>Dictionary<string, T>stringList<string>동일한 파라미터로 모듈 함수를 정의합니다.{ "params": { "parameter1": "a", "parameter2": ["b", "c"] }}
[CloudCodeFunction("SimpleParams")]public async Task SimpleParams(IExecutionContext ctx, string parameter1, List<string> parameter2){ return parameter1 + parameter2[0] + parameter2[1];}
커스텀 유형
모듈 프로젝트에서 정의한 커스텀 유형에서 전달할 수도 있습니다. 예를 들어 JSON 객체에서 모듈 오브젝트에 전달할 수 있습니다.모듈 프로젝트에서{ "params": { "player": { "name": "player", "health": 50, "stamina": 20, "inventory": { "count": 5, "weight": 20 } } }}
PlayerInventorypublic class Player{ public string Name { get; set; } public int Health { get; set; } public int Stamina { get; set; } public Inventory Inventory { get; set; }}public class Inventory{ public int Count { get; set; } public int Weight { get; set; }}[CloudCodeFunction("CustomParams")]public async Task<string> CustomParams(IExecutionContext ctx, Player player){ return $"{player.Name} has {player.Health} health and {player.Stamina} stamina and {player.Inventory.Count} items in their inventory with a total weight of {player.Inventory.Weight}";}
가용 인터페이스
Cloud Code 모듈은IGameApiClientIAdminApiClientIPushClientIExecutionContextICloudCodeSetupIGameApiClient 인터페이스
IGameApiClientIGameApiClient- 다음과 같이 인터페이스를 구현하는 클래스를 정의하고
ICloudCodeSetup를 싱글톤으로 추가합니다.GameApiClientpublic class ModuleConfig : ICloudCodeSetup{ public void Setup(ICloudCodeConfig config) { config.Dependencies.AddSingleton(GameApiClient.Create()); }} - 인터페이스를 함수 파라미터로 모듈 함수에 전달합니다.
IGameApiClient
IAdminApiClient 인터페이스
IAdminApiClientIAdminApiClient- 다음과 같이 인터페이스를 구현하는 클래스를 정의하고
ICloudCodeSetup를 싱글톤으로 추가합니다.AdminApiClientpublic class ModuleConfig : ICloudCodeSetup{ public void Setup(ICloudCodeConfig config) { config.Dependencies.AddSingleton(AdminApiClient.Create()); }} - 인터페이스를 함수 파라미터로 모듈 함수에 전달합니다.
IAdminApiClient
IPushClient 인터페이스
IPushClientIPushClient- 다음과 같이 인터페이스를 구현하는 클래스를 정의하고
ICloudCodeSetup를 싱글톤으로 추가합니다.PushClientpublic class ModuleConfig : ICloudCodeSetup{ public void Setup(ICloudCodeConfig config) { config.Dependencies.AddSingleton(PushClient.Create()); }} - 오브젝트를 함수 파라미터로 모듈 함수에 전달합니다.
PushClient
IExecution 컨텍스트
모듈 내에서 다른 UGS 서비스에 대한 호출을 생성하기 위해IExecutionContext- : 호출자가 인증을 받은 프로젝트 ID입니다.
ProjectId - : 스크립트를 실행한 플레이어 ID입니다. 참고: 서비스에서 스크립트를 호출하는 경우 플레이어 ID를 사용할 수 없습니다.
PlayerId - : 모듈의 환경 ID입니다.
EnvironmentId - : 모듈의 환경 이름입니다.
EnvironmentName - : 플레이어가 Cloud Code에서 인증하는 데 사용한 JWT(JSON 웹 토큰) 자격 증명입니다.
AccessToken - : 서비스 계정의 사용자 ID입니다. (참고: 서비스가 스크립트를 호출하는 경우 사용자 ID를 사용할 수 없습니다.)
UserId - : 발급자 또는 서비스 계정 토큰입니다. (참고: 플레이어가 스크립트를 호출하는 경우 발급자를 사용할 수 없습니다.) 예를 들어 Multiplay가 호출을 생성하는 경우 발급자는
Issuer입니다.multiplay - : Cloud Code 서비스 계정 JWT 자격 증명입니다.
ServiceToken - : 플레이어의 Analytics 사용자 ID입니다. (참고: 서비스가 스크립트를 호출하는 경우 Analytics 사용자 ID를 사용할 수 없습니다.)
AnalyticsUserId - : 플레이어의 Unity 디바이스 설치 ID입니다. (참고: 서비스가 스크립트를 호출하는 경우 Unity 설치 ID를 사용할 수 없습니다.)
UnityInstallationId
CloudCodeFunctionusing 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토큰 유형 | 출처 | 데이터 액세스 | 사용 |
|---|---|---|---|
| Authentication 서비스 에서 생성 | 인증된 플레이어만 | |
| Cloud Code에서 생성 | 크로스 플레이어 데이터 액세스 | |
AccessTokenAccessToken모든 플레이어의 데이터에 액세스하려면 다음과 같이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()); } }}
ServiceTokenplayerId두 토큰의 차이점에 대한 자세한 설명은 서비스 및 액세스 토큰 기술 자료를 참고하십시오.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()); } }}
Cloud Code 모듈 메타데이터
Cloud Code 모듈과 해당 메타데이터를 가져오기 위해GET{ "name": "string", "language": "CS", "tags": { "property1": "string", "property2": "string" }, "signedDownloadURL": "string", "dateCreated": "2022-04-05T09:12:13Z", "dateModified": "2022-04-05T09:12:13Z"}