Documentation

Cloud Code

Version: 3.0.0  
Unity 6.7 (6000.7)+
Open Unity Dashboard

Cloud Code

Version: 3.0.0  
Unity 6.7 (6000.7)+

RPCs in CloudBehaviours

Declare a remote procedure call (RPC), call it from your game, and inject services into it.
Read time 4 minutesLast updated 12 days ago

Important
This page describes an experimental feature that might change significantly before release. It's not recommended to use or rely on experimental features in production environments due to potential instability.
A remote procedure call (RPC) is a public method on a CloudBehaviour that runs in the cloud and that your game calls through the client bindings. The Unity Editor generates a matching method in the client bindings for each RPC. The method body never runs on a player's device, so put validation, secret logic, and anything that awards or spends resources in the method body.
Important
Every public method in the cloud script is a network endpoint that any client can call, including a malicious one. For guidance on restricting access to an RPC, refer to Multiplayer game security in CloudBehaviours.

Write a method your game can call

The Editor generates an RPC for each public, non-static, non-generic method on the cloud class. Methods marked
[SyncView]
are the exception, because they define per-player state views instead. The method can be synchronous or asynchronous (returning
Task
or
Task<T>
), and it can take parameters and return a value.
The following example declares three methods that your game can call, and one private method that stays in the cloud:
[StateScope(Scope.MultiplayerSession)]public class MatchState : CloudBehaviour{ public void EndTurn() { // Add your turn logic here. } public int SubmitScore(int score) { // Add your scoring logic here. return score; } public async Task<string> PlayTurn(string move) { // Add your move logic here. return "ok"; } // Private methods stay in the cloud. private void ResetRound() { // Add your reset logic here. }}
Parameters and return values serialize as JSON, so use serializable types, such as primitives, strings, and plain C# classes. Parameters marked
[CloudCodeService]
are the exception. The runtime injects these parameters, so Cloud Code never serializes them, and they don't appear on the client. Refer to Inject services into an RPC.
The Editor generates a data-only copy of concrete classes, structs, and enums that you define in the cloud assembly, with only their public fields and properties. Refer to Model types crossing the client boundary.
The following types cause a compile-time error instead:
  • Interfaces and abstract classes, because the runtime can't tell which concrete type to deserialize a value into.
  • Types that derive from a .NET type, such as a collection, or from a type injected with
    [CloudCodeService]
    .
  • Custom collection types. Use
    List<T>
    or an array instead.
  • Types with a public property that can be read but not assigned, such as a computed property or a property without a public setter.
  • Types declared in another assembly that references the Unity Engine or the Unity Editor, because that assembly can't run in the cloud.

Call an RPC from your game

The generated client bindings contain an awaitable method for each RPC. Every client-side call is asynchronous, even when the cloud method is synchronous, because each call goes over the network:
public async Task PlayAsync(){ var result = await matchStateClient.PlayTurn("rock"); Debug.Log(result);}
Each RPC response also carries the caller's synchronized state after the method runs. The client bindings apply that state before the call returns, so a client that calls an RPC doesn't need a separate hydration. In a
MultiplayerSession
scope, the other players receive the update as a push instead, unless you control synchronization manually.

Inject services into an RPC

To use a service inside an RPC, add the service as a parameter marked with
[CloudCodeService]
. For example, inject the generated interface to schedule a timer or call another CloudBehaviour. The runtime injects the service, and the Editor removes the parameter from the generated client method:
[StateScope(Scope.MultiplayerSession)]public class MatchState : CloudBehaviour{ public async Task StartTurn([CloudCodeService] IMatchState self) { await self.OnTurnTimeout().ScheduleAsync(TimeSpan.FromSeconds(30)); } [CloudCodeAccess(Access.Service)] public void OnTurnTimeout() { // Add your timeout logic here. }}
The generated client
StartTurn
method has no
self
parameter.

Register the generated interface

A generated
I{Behaviour}
interface resolves only if your module registers it. In the module's
ICloudCodeSetup
, call the generated
Add{Behaviour}Client()
extension method for each CloudBehaviour interface you inject:
using Unity.Services.CloudCode.Core;public class ModuleSetup : ICloudCodeSetup{ public void Setup(ICloudCodeConfig config) { config.AddMatchStateClient(); }}
If you inject an
I{Behaviour}
interface without registering it, the build fails with a generator error that names the missing
Add{Behaviour}Client()
call.
Note
Mark every injected service parameter with
[CloudCodeService]
. If an injected service or a generated
I{Behaviour}
interface parameter is missing the attribute, the build fails with
CCSG136
.
For the full timer scheduling pattern, refer to Timers in CloudBehaviours. To call another CloudBehaviour's endpoint, refer to Cross-behaviour calls in CloudBehaviours.

Additional resources