Persistent data (user preferences, savegames)

1. Storing user preferences locally (UserConfig)

To manage persistent data, like user preferences or a simple save game values, use CastleConfig unit with a UserConfig singleton inside. A simple example:

uses SysUtils, CastleWindow, CastleConfig;
 
var
  Window: TCastleWindow;
  MyParameter: string;
 
function MyGetApplicationName: string;
begin
  Result := 'my_game_name';
end;
 
begin
  { make sure application name is correct by setting OnGetApplicationName,
    this is used by UserConfig.Load to determine config file location. }
  OnGetApplicationName := @MyGetApplicationName;
 
  { load config from file }
  UserConfig.Load;
  // SoundEngine.LoadFromConfig(UserConfig); // load sound parameters (enabled, volume...)
  // InputsAll.LoadFromConfig(UserConfig); // load keyboard shortcuts configuration
 
  { load your own data like this: }
  MyParameter := UserConfig.GetValue('my_parameter', 'default_value');
 
  { ... do the main part of your program }
  Window := TCastleWindow.Create(Application);
  Window.OpenAndRun;
 
  { save your own data like this: }
  UserConfig.SetValue('my_parameter', MyParameter);
  // or like this:
  UserConfig.SetDeleteValue('my_parameter', MyParameter, 'default_value');
 
  { save config to file }
  // SoundEngine.SaveToConfig(UserConfig); // save sound configuration
  // InputsAll.SaveToConfig(UserConfig); // save keyboard shortcuts configuration
  UserConfig.Save;
end.

To load and save config values, you should use GetValue and SetValue (or SetDeleteValue) methods. See the TXMLConfig class documentation. These provide basic means to load/save integers, booleans and strings in a simple XML format.

We extend the standard TXMLConfig with more methods:

  • to load/save more types (floats, vectors, colors, URLs),
  • to load/save from an URL (not just a filename),
  • to encrypt/decrypt contents, which may be useful as a simple protection against cheaters (if you want this, just set the simple BlowFishKeyPhrase property).
  • to add "loader" functions (GetValue, GetVector3 etc.) that require the presence of given attribute in the XML file. They raise an exception when the attribute is missing or invalid. This is useful if you want to somewhat validate the XML file by the way (for example when it's a game model file that must contain given variables).

See the TCastleConfig for a documentation of our extensions.

Some engine components provide ready methods to load / save their configuration into a TCastleConfig instance (for example into the UserConfig). These include:

Note that the engine does not automatically call the load / save methods mentioned above. We used to call them automatically (in engine version <= 5.2.0), but this automatization was more trouble than gain. (It meant that UserConfig.Load could, often by surprise to the developer, override the sound parameters set by SoundEngine.ParseParameters or explicit SoundEngine.Enabled := false code.) So you're supposed to call them yourself (see example above) if you want to save these values as user preferences.

While you can load and save the config data at any time, you can also register your own load and save listeners using the TCastleConfig.AddLoadListener, TCastleConfig.AddSaveListener mechanism. This sometimes allows to decentralize your code better.

2. Storing user preferences in the cloud

On Android, our engine allows to easily upload and download the savegames using the Google Play Games "Saved Games" feature. To use this feature:

  1. Turn on the Google Play Games integration for your project.

  2. Create and initialize the TGooglePlayGames instance in your code. Be sure to pass parameter SaveGames as true to the TGooglePlayGames.Initialize call.

  3. Connect player to the Google Play Games at runtime, using TGooglePlayGames.RequestSignedIn method, and / or passing AutoStartSignInFlow as true to the TGooglePlayGames.Initialize call.

    You can wait for the sign-in to happen by the TGooglePlayGames.OnSignedInChanged event, or just observe the TGooglePlayGames.SignedIn property.

  4. Then load and save games using the TGooglePlayGames.SaveGameLoad and TGooglePlayGames.SaveGameSave methods. They represent the "savegame contents" as a simple string, and you can use the UserConfig.SaveToString and UserConfig.LoadFromString methods to trivially upload / download the UserConfig contents to the cloud!

  5. If you want to allow user to choose a "slot" where to save the game, or from which to load the game, you can use a ready dialog by calling TGooglePlayGames.ShowSaveGames.