Cloud Code + Game Server Hosting to do Allocation Management

So, I 'm making a card game with a special focus on PVP Competitive Gameplay. I’ve built a ranked system using matchmaker and all that, but now I’m in what the community really is looking for: Tournaments.
I’m trying to make the process streamlined for users, so they see a list of tournaments, join said tournaments, and then can monitor their progress, and join matches when their time to play comes.
In another part of the Game, I’ve already developped another way to match with players through lobbies. Players can make a match with custom rules (Ranked rules are always fixed / change each 24 hours), so the way I’m doing this is: a player chooses a custom ruleset, and this information is stored ina lobby that the player then joins. If said lobby has two players in it then the GAME CLIENT (I know, this is bad) creates an allocation for those two players and they join to play the custom game.

I’m planning on using this very same ystem to make tournament matches, but the injected rules will be injected by the tournament manager (Which I am developing with Cloud Code), instead of the game client,

As I’m sure yo u are aware, creating allocations on a gameclient creates a bunch of issues, such as exposing my API keys in the client and allowing the client code to have an entry point in which it can freely create allocations, where the code to be cracked open and hacked by someone.

For this reason I decided to go with the approach of letting Cloud Code manage Allocations along side with the standard Matchmaker. My question is: Do I have to use raw .Net to make API calls to the admin API and create the allocation, thus manually storing the API token inside my cloud code? Oris there a stub inside CloucCode.Apis nugget packages that would allow me to seamlessly do this in a much cleaner and faster way?. By the way, I ened to do this using lobby because a list of joinable tournament games musst be generated later for tournaments that are swiss rounds / round robin, so a work around using MatchMaker would be a possibility, but by no means ideal for this problem

I have been looking for this answer inside the doc for Cloud code but havent’found a way of creating allocations manually through Cloud Code. Thanks!

Hi ANLevant,

Currently yes, to create an allocation you’ll need to manually make an HTTP request to Multiplay as we don’t have a C# SDK for that service yet. However, you shouldn’t need to hardcode the API token or service account details: you can use the injected IExecutionContext.ServiceToken

Hope that helps; I’ll try to find some time to add Multiplay SDK support soon and will update this thread when it’s available

2 Likes

Hi,

I would like to add that the admin API specifications are public: Unity Services Web API docs
you can generate the code from it, using an Open API generator, I explained the details here: Server-side support for managing player economies

Cheers

1 Like

It did help! thank you a lot to you too!

It’s always something with cloud code man.

I went ahead and used httpClient to create an allocation and now I’m getting this error:

HttpException`1: (422) HTTP/1.1 422 Unprocessable Entity
  at Unity.Services.CloudCode.Internal.Http.ResponseHandler.HandleAsyncResponse (Unity.Services.CloudCode.Internal.Http.HttpClientResponse response, System.Collections.Generic.Dictionary`2[TKey,TValue] statusCodeToTypeMap) [0x00089] in .\Library\PackageCache\com.unity.services.cloudcode@2.5.1\Runtime\com.unity.services.cloudcode.internal\Http\ResponseHandler.cs:122
  at Unity.Services.CloudCode.Internal.Http.ResponseHandler.HandleAsyncResponse[T] (Unity.Services.CloudCode.Internal.Http.HttpClientResponse response, System.Collections.Generic.Dictionary`2[TKey,TValue] statusCodeToTypeMap) [0x00001] in .\Library\PackageCache\com.unity.services.cloudcode@2.5.1\Runtime\com.unity.services.cloudcode.internal\Http\ResponseHandler.cs:226
  at Unity.Services.CloudCode.Internal.Apis.CloudCode.CloudCodeApiClient.RunModuleAsync (Unity.Services.CloudCode.Internal.CloudCode.RunModuleRequest request, Unity.Services.CloudCode.Internal.Configuration operationConfiguration) [0x001fd] in .\Library\PackageCache\com.unity.services.cloudcode@2.5.1\Runtime\com.unity.services.cloudcode.internal\Apis\CloudCodeApi.cs:137
  at Unity.Services.CloudCode.CloudCodeInternal.GetModuleResponseAsync (System.String module, System.String function, System.Collections.Generic.Dictionary`2[TKey,TValue] args) [0x00082] in .\Library\PackageCache\com.unity.services.cloudcode@2.5.1\Runtime\CloudCode.cs:243
  at Unity.Services.CloudCode.CloudCodeInternal.GetRunModuleScriptResponse (System.String module, System.String function, System.Collections.Generic.Dictionary`2[TKey,TValue] args) [0x00047] in .\Library\PackageCache\com.unity.services.cloudcode@2.5.1\Runtime\CloudCode.cs:137
Rethrow as CloudCodeException: ScriptError
(422) HTTP/1.1 422 Unprocessable Entity
Unprocessable Entity
Invocation Error
ScriptRunner.Exceptions.InvalidModuleException: Could not load assemblies for module TripleWarringModule. Ensure that the zip file includes all necessary DLLs and is compiled for linux-x64

I am using the unity editor to zip and upload the library as usual. And before adding this specific peace of code, everything was working.

My code:

[CloudCodeFunction("CreateAllocationForBracketGame")]
    public async Task<string> CreateAllocationForBracketGame(IExecutionContext context, IGameApiClient gameApiClient, string code, int nodeId, string playerId)
    {
        _logger.LogInformation("Creating allocation for bracket game: " + code + ", for node: " + nodeId+ ", for player: "+playerId);
        TournamentDTO tournamentDto = await GetTournamentByCode(context, gameApiClient, code);
        //TournamentNode tournamentNode = SearchForTournamentNode(tournamentDto, nodeId);
      
        HttpClient client = new HttpClient();
        client.DefaultRequestHeaders.Add("Authorization", "Bearer "+ context.ServiceToken);
        string allocationId = Guid.NewGuid().ToString();
        string payload = "";
        //string payload = JsonConvert.SerializeObject(tournamentNode.rules);
        string url = $"https://multiplay.services.api.unity.com/v1/allocations/projects/{context.ProjectId}/environments/{context.EnvironmentId}/fleets/{FLEET_ID}/allocations";
      
        string queueAllocationRequest = $"{{\"allocationId\":\"{allocationId}\",\"buildConfigurationId\":{BUILD_CONFIGURATION_ID},\"regionId\": \"{REGION_ID}\", \"payload\":\"{payload}\"}}";
        var content = new StringContent(queueAllocationRequest, Encoding.UTF8, "application/json");
      
        HttpResponseMessage json = await client.PostAsync(url, content);
        _logger.LogInformation("Answer to creating allocation: " + json);
      
        return json.ToString();
    }

BTW sorry if I sound frustrated, but I am

Alright fixed this. The issue was: I used test libraries because someone here recommended me to use build unit tests using NUnit, but this thing made the assembly bigger than 10 MB so it couldn’tbe packaged. I deleted the NuGet poackage from the project, but it turns out the deployment with unity editor Never executed a dotnet clean, thus old assemblies where expecting the test package to be there. And it was’t

@ANLevant THanks for the feedback, will add a Rebuild option to the CloudCode Module from the editor to address this issue.

On the other hand, I was not aware cloudcode had a upper limit of binary size.
Could you please let me know what feedback, if any, the Deployment Window in the editor gave you when the size was too large?

1 Like

Hello! sorry, i just read this. It has been some weeks, and I have pretty much deleted all the code that dependencies that caused the issues. But I had added NUnit + Cloud Code dependencies and Cloud Code APIs + .net core http client library

1 Like

This is me, coming from the future. I was pissed at cloud code due to the lac of proper documentation. But after using it for a year, I’m quite happy with it. Yes it still needs to be worked on, but it is very VERY good, cost-effective and easy to use. It just demands you to be very careful with your error handling.

1 Like

As does any cloud service. Good point!

All too often I see cloud service code without try/catch at all, or omitting the catch using try/finally, or without any code in the catch, or with just logging in the catch, or combining multiple unrelated service calls in a single try/catch.

Hey!

Thank you for the feedback! We would like to know what specifically we can do to improve the documentation, we’d like to get it fixed!

Cheers!

1 Like

There is not a guideline or best practices on important software quiality things like how to implement Unit Tests to test your cloud code modules. On the same note, I’ve been trying to keep a proper package structure on my module, but it seems like the module can’t find his endpoints if it’s not exactly where unity generated it. If this is possible, I failed to find any documentation on how to configure the module. There’s also error handling, if an error occurs, the operation silently dies. It would be nice to at least see an error logged in the Cloud Code logs, explainig that the process either timed out or stopped with an exception, you get something ike that with Amazon lambda. You still get a stack trace as an answer to the client-side.

Another think I’d say helps a lot is to have an actual API for C# code (not just the REST API, because they often don’t match). somethind like this (example RestController (Spring Framework 6.2.1 API))

Most of the code is introduced through examples on the manuals instead of lining the APIs. And the code on the examples is many times spagetthi code which is poorly scalable. I’d prefer to build my own code from scratch than fix boiler plate spaghetti code (For a reference, check Battle Pass implementation guide:

https://docs.unity.com/ugs/en-us/solutions/manual/BattlePasses

All of this said, I know of no other gaming company that is undertaking the challenge of providing flexible, scalable, easily reusable and affordable infrastructure for videogames. Keep up the good work guys!

1 Like

Hey,

Thanks for all of the great feedback on Cloud Code!

Revisiting and expanding on our documentation and samples is absolutely on our to do list. We really want to refresh those old samples and make sure there are more resources for customers to see what’s possible with and best practice for Cloud Code C#. We’re also looking at providing better observability into what’s happening in your module through automatic logging of issues both within customer code and any give visibility into interesting scaling metrics.

In terms of the actual API for C# code, could you elaborate a bit on what you would like to see here, do you mean you would like docs for the APIs NuGet package (similar to our Rest API docs and JS SDK docs but for Cloud Code C#) or another way to access your C# code?

1 Like

Yeah, docs for the APIs nuget package would be nice. Lemme show you an example of what I mean by poor error handling. This thread I did it today. I could easily fix this myself, if I wasn’t getting a 422 error with message Unknown. That says nothing about the error and this, I’m forced to dig like a graverobber xD. You always get 422 for the majority of errors. Sometimes they come with an explanation, sometimes they don’t. Theres a bunch of stuff like this that would be too long to mention, but this is what I mean when I say that the tools are still missing some way to go.

Also, I don’t think that doing samples is the way to go. I’d prefer to have a robust and in detail API and then I can pretty much know how to implement things myself, instead of having to rely on examples that not always have the best coding standards. The samples’s code is not really reusable most of the times, you can’t put it in your project and make it work. You have rto read the sample and backwards engineer it into your project. Resulting in sloppy implementations.