Cross-behaviour calls in CloudBehaviours
Call an endpoint on another CloudBehaviour from inside your own, in another scope instance or another module.
Read time 5 minutesLast updated 12 days ago
From inside a CloudBehaviour, you can call an endpoint on another CloudBehaviour. How you make the call depends on where the target runs:
Target | How to call it |
|---|---|
| A CloudBehaviour in another scope instance, in the same module | Use the generated interface and |
| A CloudBehaviour in another scope instance, in another module | Call it as a Cloud Code module endpoint. Refer to Call a CloudBehaviour in another module. |
| The same CloudBehaviour in the current scope instance | Call the method directly, the same as any other C# method. |
| A different CloudBehaviour in the current scope instance | You can't call it and wait for its result. Refer to Call the current scope instance. |
To run an endpoint on the same CloudBehaviour later instead of now, schedule a timer. Refer to Timers in CloudBehaviours.
Call a CloudBehaviour in another scope instance
The Unity Editor generates an interface for every CloudBehaviour in your module. Inject the interface with , then call a member on the interface to get back an that hasn't run yet. To run the , pass the target's scope ID to .
I{Behaviour}[CloudCodeService]ICallICallForScope(scopeId)An does nothing until you run it. If you create an and never call or on it, the build fails with .
ICallICallForScopeScheduleAsyncCCSG133The following example shows a -scoped that updates each player's at the end of a match. is -scoped because it belongs to one player and outlives any single match:
MultiplayerSessionMatchRoomPlayerRecordPlayerRecordPlayer[StateScope(Scope.Player)]public class PlayerRecord : CloudBehaviour{ public int MatchesPlayed; public int PersonalBest; [CloudCodeAccess(Access.Service)] public int RecordMatch(int score) { MatchesPlayed++; if (score > PersonalBest) PersonalBest = score; return PersonalBest; }}[StateScope(Scope.MultiplayerSession)]public class MatchRoom : CloudBehaviour{ [CloudCodeSerializeProperty] private Dictionary<string, int> _scores = new(); public async Task EndMatch([CloudCodeService] IPlayerRecord playerRecord) { foreach (var entry in _scores) { var best = await playerRecord.RecordMatch(entry.Value).ForScope(entry.Key); Logger.LogInformation("{PlayerId} personal best is now {Best}", entry.Key, best); } }}
ForScope[StateScope]entry.KeyScope.PlayerPlayerRecordForScopeContext.ScopeIdCCSG138Awaiting the call returns the endpoint's return value directly. The caller doesn't receive the target's synchronized state. If the call changes that state, Cloud Code pushes the new state to the clients in the target's scope, the same as after any other endpoint call, unless the target has turned off . In this example, each player receives their updated . For more information, refer to Control synchronization manually.
AutoSynchronizePlayerRecordGet a scope ID
Read the scope ID to pass to from the CloudBehaviour's :
ForScopeContextTarget scope | Scope ID | Notes |
|---|---|---|
| | The ID of the player making the current call. For the other players in a session, use |
| | Only available when the calling CloudBehaviour is |
When a service such as a timer or another CloudBehaviour calls the endpoint, is . In those calls, pass the scope ID as an endpoint argument instead.
Context.PlayerIdnullRestrict access to the target endpoint
A cross-behaviour call arrives with no player identity. The player ID you pass to selects only which scope instance runs the endpoint. The player ID doesn't make the call on that player's behalf.
ForScopeThe target is still an endpoint that a client can call directly. Mark the target so no player can call it directly. Refer to Access control in CloudBehaviours.
[CloudCodeAccess(Access.Service)]Call a CloudBehaviour in another module
The generated interface only reaches CloudBehaviours in the same module. To call a CloudBehaviour in another module, call its endpoint as a Cloud Code module endpoint, and pass the scope ID of the target scope instance. The target scope instance must be different from the one that's running your code. Refer to Call the current scope instance.
Call the current scope instance
A scope instance runs one call at a time. While your endpoint runs, any other call into the same scope instance waits for your endpoint to finish. How a call into the current scope instance fails depends on how you make the call:
- If you call through the generated interface with , the call fails immediately. If you pass
ForScope, the build fails withContext.ScopeId. If you pass another value that matches the current scope ID, the call throws anCCSG138at runtime.InvalidOperationException - If you call a Cloud Code module endpoint, including a CloudBehaviour in another module, nothing stops the call. The call waits for your endpoint, and your endpoint waits for the call, until the request fails with a error.
Gateway Timeout
To run code on the same CloudBehaviour in the current scope instance, call the method directly, the same as any other C# method. You can't call a different CloudBehaviour in the current scope instance and wait for its result.
To share logic between modules in the same scope, refer to Avoid calls into your own scope.
Requirements
To call another CloudBehaviour through its generated interface, you must do the following:
- Put both CloudBehaviours in the same module. If the target is in another module, refer to Call a CloudBehaviour in another module.
- Mark the injected parameter with . Otherwise, the build fails with
[CloudCodeService]. Refer to Inject services into an RPC.CCSG136 - Register the target's interface in your module's . In this example, call
ICloudCodeSetup. Refer to Register the generated interface.config.AddPlayerRecordClient() - Pass only the endpoint's own arguments. The Editor removes every parameter from
[CloudCodeService], so the call has no argument for the injected parameter.I{Behaviour} - Give each CloudBehaviour class in the module a unique name, even across namespaces.