State serialization in Cloud Code
Understand how Stateful Cloud Code serializes module state, and how to control or customize serialization behavior.
Read time 2 minutesLast updated a month ago
Stateful Cloud Code automatically serializes and deserializes module class state between function invocations. Serialization allows class members to persist within the configured scope without manual storage management.
Understanding serialization behavior helps you design module classes and troubleshoot state persistence issues. Non-serialized fields and properties can still keep values in memory between invocations, but this behavior isn't guaranteed. Only serialized fields and properties persist reliably. The runtime can rehydrate object state from persisted data at any time.
Default serialization behavior
By default, the runtime serializes module state using the following rules:
- The runtime includes public fields and properties in the serialization.
- The runtime excludes private fields and properties in the serialization.
This default inclusion of public members aligns with common serialization library conventions, making it familiar to developers who know standard .NET serialization patterns.
using System;using Unity.Services.CloudCode.Core;[StateScope(Scope.Player)]public class PlayerProgress{ // Serialized: public field public int Level; // Serialized: public property public int Experience { get; set; } // Not serialized: private field private DateTime _lastCalculated; // Not serialized: private property private int CachedValue { get; set; } [CloudCodeFunction("GetProgress")] public string GetProgress() { return $"Level: {Level}, Experience: {Experience}"; }}
Serialization attributes
Use Cloud Code serialization attributes to explicitly control which members to include in the serialization.
Exclude public members from serialization
Apply to exclude a public field or property from serialization. Use this attribute for cached values, computed properties, or data that doesn't need to persist.
[CloudCodeIgnoreProperty]using System.Collections.Generic;using Unity.Services.CloudCode.Core;[StateScope(Scope.Player)]public class PlayerInventory{ public List<string> Items = new List<string>(); // Excluded from serialization despite being public [CloudCodeIgnoreProperty] public int CachedItemCount; [CloudCodeFunction("AddItem")] public void AddItem(string item) { Items.Add(item); CachedItemCount = Items.Count; // Recalculated anyway }}
Include private members in serialization
Apply to include a private field or property in serialization. Use this attribute to persist internal state while maintaining encapsulation.
[CloudCodeSerializeProperty]using System.Collections.Generic;using Unity.Services.CloudCode.Core;[StateScope(Scope.MultiplayerSession)]public class GameSession{ // Included in serialization despite being private [CloudCodeSerializeProperty] private List<string> _playerIds = new List<string>(); // Included in serialization despite being private [CloudCodeSerializeProperty] private string _currentTurnPlayerId; public int PlayerCount => _playerIds.Count; [CloudCodeFunction("JoinSession")] public string JoinSession(string playerId) { _playerIds.Add(playerId); if (_playerIds.Count == 1) { _currentTurnPlayerId = playerId; } return $"Player {playerId} joined. {PlayerCount} players in session."; }}
Custom serialization
For advanced scenarios, implement the interface to control how the runtime serializes and deserializes your module state. This interface enables you to do the following:
IStateSerializer- Use a specific serialization library or format.
- Handle complex types that require custom conversion logic.
- Optimize serialization for performance or payload size.
- Handle migration of persisted state after you deploy a new module version.
The IStateSerializer interface
The Cloud Code SDK provides the interface. Implement this interface on your module class to replace the default serializer with your own behavior. The interface declares the following two methods:
IStateSerializernamespace Unity.Services.CloudCode.Core{ public interface IStateSerializer { // Called to serialize the object state. byte[] OnSerialize(); // Called to deserialize and restore object state. void OnDeserialize(byte[] input); }}
Custom serialization example with a third-party serializer
The following example demonstrates custom serialization using to serialize a game session's player list.
Newtonsoft.Jsonusing System.Collections.Generic;using Newtonsoft.Json;using Newtonsoft.Json.Linq;using Unity.Services.CloudCode.Core;[StateScope(Scope.MultiplayerSession)]public class GameSession : IStateSerializer{ public List<string> _playerIds = new List<string>(); public string _hostPlayerId; public byte[] OnSerialize() { var json = JsonConvert.SerializeObject(this); return System.Text.Encoding.UTF8.GetBytes(json); } public void OnDeserialize(byte[] data) { var json = System.Text.Encoding.UTF8.GetString(data); var serializer = JsonSerializer.Create(); serializer.Populate(JObject.Parse(json).CreateReader(), this); } [CloudCodeFunction("AddPlayer")] public string AddPlayer(string playerId) { if (_playerIds.Count == 0) { _hostPlayerId = playerId; } _playerIds.Add(playerId); return $"Player {playerId} joined. Host: {_hostPlayerId}"; } [CloudCodeFunction("GetPlayers")] public List<string> GetPlayers() { return _playerIds; }}