기술 자료

​
​

Development

User Acquisition

Monetization

산업 분야

Cloud Code

Open Unity Dashboard

Cloud Code

이 페이지는 선택한 언어로 제공되지 않습니다.
Cloud Code
​
​
Cloud Code 3.0.0 experimental features
  • Overview
  • Stateful Cloud Code
  • Local Cloud Code server
  • Develop Cloud Code modules in the Unity Editor
  • State serialization in Cloud Code
  • Timers in Stateful Cloud Code
  1. Cloud Code
  2. Cloud Code 3.0.0 experimental features

Timers in Stateful Cloud Code

Use timers in Stateful Cloud Code modules to schedule delayed function calls.
읽는 시간 6분
최근 업데이트: 23일 전

중요
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.
Use timers to schedule time-based game mechanics in your Stateful Cloud Code modules without managing infrastructure or maintaining persistent connections from game clients. A timer registers a one-off callback that executes a specified Cloud Code function after a defined time span elapses.
Timers are server authoritative and persist within the scope of your module. When a timer elapses, the Cloud Code runtime invokes the target function with the arguments you specified at registration.
Common use cases for timers include the following:
  • Turn timers: Enforce time limits for player turns in multiplayer games.
  • Cooldowns: Restrict how frequently players can perform certain actions.
  • Delayed events: Trigger in-game events after a specified duration.
  • Idle mechanics: Process offline progression or resource generation at intervals.
참고
Timer management in Stateful Cloud Code requires you to reference the following NuGet package versions in your modules:
  • com.unity.services.cloudcode.apis
    v0.0.26 or later
  • com.unity.services.cloudcode.core
    v0.0.4 or later
These samples use the timer method names introduced in core package 0.0.7. Before 0.0.7, the timer methods were named
Register()
and
Fetch()
.

Timer registration

To use timers, inject
ITimerService
into your module's constructor. The runtime provides the timer service automatically.
참고
The target Cloud Code function must be in the same Cloud Code module as the function that registers the timer.
using System;using System.Collections.Generic;using System.Threading.Tasks;using Unity.Services.CloudCode.Core;[StateScope(Scope.MultiplayerSession)]public class RegisterTimerExample{ private readonly ITimerService _timerService; public RegisterTimerExample(ITimerService timerService) { _timerService = timerService; } [CloudCodeFunction("PerformDelayedAction")] public async Task<bool> PerformDelayedAction(IExecutionContext context) { // Register a timer that calls "DelayedAction" after 30 seconds await _timerService.RegisterTimerAsync( TimeSpan.FromSeconds(30), "DelayedAction", new Dictionary<string, object> { { "action", "NOTHING" } } ); return true; } [CloudCodeFunction("DelayedAction")] public async Task DelayedAction(string action) { // Perform your action here }}
In this example, calling
PerformDelayedAction
registers a timer that automatically calls
DelayedAction
after 30 seconds.
PerformDelayedAction
also passes in the relevant argument (in this case,
action
) to the callback function.
You can also accept
ITimerService
as a parameter on an individual Cloud Code function instead of injecting it into the constructor. Use the constructor when more than one function in the module registers timers.
참고
Register
and
Fetch
still work in core package 0.0.7 and later, but they're obsolete. Migrate to
RegisterTimerAsync
and
GetTimerAsync
.

Timer parameters

The
RegisterTimerAsync
method accepts the following parameters:

Parameter

Type

Description

delay
TimeSpan
The duration to wait before the timer elapses.
functionName
string
The name of the Cloud Code function to call when the timer elapses.
arguments
Dictionary<string, object>
An optional dictionary containing arguments to pass to the target function.
Additionally, note the following parameters:
  • Register timers with a delay between 1 second and 24 hours.
  • A module can run up to 10 timers at the same time.

Turn timer implementation

You can implement recurring turn timers by having the function called by the timer register its own timer. This pattern is useful for turn-based games where each player has a fixed amount of time to act.
using System;using System.Collections.Generic;using System.Threading.Tasks;using Unity.Services.CloudCode.Core;[StateScope(Scope.MultiplayerSession)]public class TurnBasedGameExample{ public List<string> _players = new List<string>(); public int _currentPlayerIndex; public bool _gameActive; public string? _timerId; private readonly ITimerService _timerService; public TurnBasedGameExample(ITimerService timerService) { _timerService = timerService; } [CloudCodeFunction("StartGame")] public async Task<string> StartGame(List<string> playerIds) { _players = playerIds; _currentPlayerIndex = 0; _gameActive = true; // Start the first turn timer _timerId = await _timerService.RegisterTimerAsync( TimeSpan.FromSeconds(60), "OnTurnTimeout", new Dictionary<string, object> { { "playerId", _players[_currentPlayerIndex] } } ); return $"Game started. {_players[_currentPlayerIndex]}'s turn."; } [CloudCodeFunction("MakeMove")] public async Task<string> MakeMove(IExecutionContext context, string move) { if (_players[_currentPlayerIndex] != context.PlayerId) { return "Not your turn."; } if (_timerId != null) { var timer = await _timerService.GetTimerAsync(_timerId); timer.Cancel(); } // Process the move here // Advance to the next player and register a new turn timer _currentPlayerIndex = (_currentPlayerIndex + 1) % _players.Count; _timerId = await _timerService.RegisterTimerAsync( TimeSpan.FromSeconds(60), "OnTurnTimeout", new Dictionary<string, object> { { "playerId", _players[_currentPlayerIndex] } } ); return $"Move '{move}' processed. Next player's turn."; } [CloudCodeFunction("OnTurnTimeout")] public async Task<string> OnTurnTimeout(string playerId) { // playerId is the argument passed to the timer when it was registered if (!_gameActive || _players[_currentPlayerIndex] != playerId) { return "Timer no longer valid."; } // Handle timeout (skip turn, apply penalty, etc.) var skippedPlayer = playerId; // Advance to the next player and register a new turn timer _currentPlayerIndex = (_currentPlayerIndex + 1) % _players.Count; _timerId = await _timerService.RegisterTimerAsync( TimeSpan.FromSeconds(60), "OnTurnTimeout", new Dictionary<string, object> { { "playerId", _players[_currentPlayerIndex] } } ); return $"Player {skippedPlayer} timed out. Next player's turn."; }}
In this pattern, each call to
OnTurnTimeout
or
MakeMove
advances to the next player and registers a new timer. The timer chain continues until the game ends. Because each registration includes a
playerId
argument, the runtime passes it to
OnTurnTimeout
as the matching
string playerId
parameter. Each argument key you provide when you register a timer must match a parameter name on the target function.
팁
In turn-based flows, because a module can run up to 10 timers at the same time, only keep the active turn timer and cancel timers that are no longer needed.

Acting on timers

Sometimes, you might need to cancel a timer before it elapses, for example, when a player completes their turn before the timeout. You might also need to make checks based on a timer's remaining time.
To implement either of these scenarios, fetch the running timer by ID with
ITimerService.GetTimerAsync()
, then call methods on the returned timer. Save the timer ID when you register the timer.
using System;using System.Threading.Tasks;using Unity.Services.CloudCode.Core;[StateScope(Scope.MultiplayerSession)]public class TimerActionExample{ // Marked serializable so the timer ID persists between function invocations. [CloudCodeSerializeProperty] private string? _activeTimerId; private readonly ITimerService _timerService; public TimerActionExample(ITimerService timerService) { _timerService = timerService; } [CloudCodeFunction("StartAction")] public async Task<string> StartAction() { // Register returns a timer ID _activeTimerId = await _timerService.RegisterTimerAsync( TimeSpan.FromSeconds(30), "DoSomething" // Callback function not included below ); return "Action started. Complete within 30 seconds."; } [CloudCodeFunction("UserCompleteAction")] public async Task<string> UserCompleteAction() { // Cancel the timer since the action completed in time if (!string.IsNullOrEmpty(_activeTimerId)) { var timer = await _timerService.GetTimerAsync(_activeTimerId); timer.Cancel(); _activeTimerId = null; } return "Action completed successfully."; } [CloudCodeFunction("RemainingTime")] public async Task<TimeSpan> RemainingTime() { // Return how much time is left on the active timer if (string.IsNullOrEmpty(_activeTimerId)) { throw new InvalidOperationException("Cannot return remaining time because no timer is currently active."); } var timer = await _timerService.GetTimerAsync(_activeTimerId); return timer.RemainingTime(); }}
팁
Since a module can only run up to 10 timers at the same time, cancel completed or obsolete timers to free timer slots.

Copyright © 2026 Unity Technologies
법률 정보개인정보 처리방침쿠키Documentation Terms of Use개인 정보 판매 또는 공유 금지개인정보 보호 선택(쿠키 설정)

'Unity', Unity 로고 및 기타 Unity 상표는 미국 및 기타 지역 내 Unity Technologies 또는 그 계열사의 상표 또는 등록상표입니다(자세한 내용은 여기에서 확인하세요). 기타 명칭 또는 브랜드는 해당 소유자의 상표입니다.

일부 페이지는 편의를 위해 기계 번역되었으며 부정확한 내용이 있을 수 있습니다. 정보가 상충되는 경우, 영어 버전을 우선으로 참조하세요.

  • 보고 있는 페이지
    • Timer registration

      • Timer parameters

    • Turn timer implementation

    • Acting on timers


이 페이지의 문제 보고