Player Saved Data
ISavedData
ISavedData
has the basic foundation for saving and loading any content. This interface includes the signatures for methods such as Load
, Save
, Delete
and Reset
.
ICloudSavedData
Any interface that inherits from ICloudSavedData
will be using the Beamable Serializer to save data as unstructured JSON.
Beamable Serializer
Beamable stores Player Saved Data, and the Beamable Serializer is responsible for the stored data.
BaseSavedData
This abstract class provides the basic functionality and its abstract methods must be overridden by each class that extends from it. This base class also provides implementations for Load
, Save
, Delete
and Reset
. As a result, any class related to ISavedData
can extend from the BaseSavedData class and use these implementations.
Note
Abstract method Deserialize()
should be implemented by each class that extends from BaseSavedData
.
Examples
An example for this is UserSavedData
How to Extend
The above diagram shows one of the potential ways of implementing a concrete player saved data class. Each class implements the corresponding interface by inheriting from its base class and implementing the additional members needed.
The following is a code example for extending from the existing StageSavedData class. A new Serialized Field _hasClaimedAscensionRewards
is introduced in this example. This implementation enables us to track whether the player has claimed the ascension rewards yet. As a result, it prevents the player from claiming the same reward multiple times if they do not finish the ascension sequence.
Step 1
Create the new class by extending from any necessary classes. Create constructors, and any new fields you want to introduce.
Note
Notice how the class is Serializable
, and any new fields we add are also SerializedField
.
[Serializable]
public class NewStageSavedData : StageSavedData
{
[SerializeField]
protected bool _hasClaimedAscensionRewards;
public bool hasClaimedAscensionRewards => _hasClaimedAscensionRewards;
protected NewStageSavedData()
{
//Empty
}
protected NewStageSavedData(string savedId, int numGoalSlots) : base(savedId, numGoalSlots)
{
//Empty
}
}
Step 2
Implement the Deserialize
method as each class is required to have their own version.
Note
Deserialize
is overridden in the NewStageSavedData class and it also keeps track of the new serialized field.
status
: True indicates that there is data to be deserialized.
protected override bool Deserialize(out ISavedData savedData)
{
NewStageSavedData deserialized = new NewStageSavedData();
bool status = _serializer.Deserialize(_savedId, ref deserialized);
if (status)
{
_hasStarted = deserialized.hasStarted;
_hasClaimedAscensionRewards = deserialized.hasClaimedAscensionRewards;
}
savedData = deserialized;
return status;
}
Step 3
Update the new serialized field where necessary, this step might require to override methods such as Reset
, or introduce new methods like ClaimAscensionRewards
.
Note
Notice how Reset
keeps updates the new serialized field and call the base method.
public override void Reset()
{
_hasClaimedAscensionRewards = false;
base.Reset();
}
public virtual void ClaimAscensionRewards()
{
_hasClaimedAscensionRewards = true;
Save();
}
The following is the final version:
[Serializable]
public class NewStageSavedData : StageSavedData
{
[SerializeField]
protected bool _hasClaimedAscensionRewards;
public bool hasClaimedAscensionRewards => _hasClaimedAscensionRewards;
protected NewStageSavedData()
{
//Empty
}
protected NewStageSavedData(string savedId, int numGoalSlots) : base(savedId, numGoalSlots)
{
//Empty
}
protected override bool Deserialize(out ISavedData savedData)
{
NewStageSavedData deserialized = new NewStageSavedData();
bool status = _serializer.Deserialize(_savedId, ref deserialized);
if (status)
{
_hasStarted = deserialized.hasStarted;
_hasClaimedAscensionRewards = deserialized.hasClaimedAscensionRewards;
}
savedData = deserialized;
return status;
}
public override void Reset()
{
_hasClaimedAscensionRewards = false;
base.Reset();
}
public virtual void ClaimAscensionRewards()
{
_hasClaimedAscensionRewards = true;
Save();
}
}