Documentation

Cloud Code

Cross-behaviour calls in CloudBehaviours

Call another CloudBehaviour's endpoint from inside your own, including across different scopes.
Read time 3 minutesLast updated 15 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.
Cloud Code generates an
I{Behaviour}
interface for every CloudBehaviour in your module. Inject the interface with
[CloudCodeService]
, then call a member on it to get back an unexecuted
ICall
. Run the
ICall
with
ForScope(scopeId)
to invoke another instance of that CloudBehaviour right now. An
ICall
does nothing until you run it. If you build one and never call
ForScope
or
ScheduleAsync
on it, the build fails with
CCSG133
.

Call another CloudBehaviour with ForScope

The following example shows a
MultiplayerSession
-scoped
MatchRoom
updating each player's
PlayerRecord
at the end of a match. A
PlayerRecord
is
Player
-scoped because it belongs to one player and outlives any single match:
[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
takes the scope ID of the target CloudBehaviour's own
[StateScope]
, not the caller's. In this example,
entry.Key
is a player ID, matching
PlayerRecord
's
Scope.Player
. Awaiting the call returns that endpoint's return value directly.

Get a scope ID

Read the scope ID to pass to
ForScope
from the CloudBehaviour's
Context
:

Target scope

Scope ID

Notes

Scope.Player
Context.PlayerId
The ID of the player making the current call. For the other players in a session, use
Context.Session.PlayerIds
.
Scope.MultiplayerSession
Context.Session.Id
Only available when the calling CloudBehaviour is
MultiplayerSession
-scoped.
Context.Session
is
null
otherwise.
Context.PlayerId
is
null
when a service calls the endpoint, such as a timer or another CloudBehaviour. In those calls, pass the scope ID as an endpoint argument instead.

Lock the target down

A cross-behaviour call arrives with no player identity. The player ID you pass to
ForScope
only selects which scope instance runs the endpoint. It doesn't make the call on that player's behalf. The target is still an endpoint that a client can call directly. Mark the target
[CloudCodeAccess(Access.Service)]
so no player can call it directly. Refer to Access control in CloudBehaviours.

Requirements

A cross-behaviour call has the following requirements:
  • Both CloudBehaviours must live in the same module. If the target is in another module, call it as a plain Cloud Code module instead.
  • Mark the injected parameter with
    [CloudCodeService]
    . Refer to Inject Cloud Code services.
  • Register the target's interface in your module's
    ICloudCodeSetup
    . In this example, call
    config.AddPlayerRecordClient()
    . Refer to Register the generated interface.
  • Name only the endpoint's real arguments. The generator strips every
    [CloudCodeService]
    parameter from
    I{Behaviour}
    , so there's no slot to pass a value into.
  • Class names must be unique within the module, even across namespaces.
Note
A timer always runs on the CloudBehaviour that scheduled it, so calling
ScheduleAsync
on another CloudBehaviour's
I{Behaviour}
fails the build with
CCSG132
. To defer work on another CloudBehaviour, schedule your own endpoint and call
ForScope
from inside it. Refer to Timers in CloudBehaviours.

Additional resources