Improbable Icon

9.0 Feature Deep Dive: Snapshots

coming-soon

#1

Hey folks,

It’s that guy that keeps talking about 9.0, back to talk about 9.0 again.

Here at Improbable we’ve long had a vision of you - the users - being able to develop your world incrementally. That is to say, your world should have a history. Both during during play, and during development.

How worlds were created

Before SpatialOS 9.0, the recommended way of starting your world was to use a process called a World App. World Apps were able to spawn an initial set of entities via a special Scala API.

It was possible to save a ‘snapshot’ (i.e., a complete backup of the world state) of your world at any time, and re-launch a deployment later from it. This was useful when running long-running playtests and during production.

We had some tooling for modifying snapshots, but anyone that used it would tell you it was pretty janky.

Let’s rewrite history

In 9.0, persistence plays a much bigger role. We’ve introduced SDK APIs to create, load, and manipulate snapshots from C++ and C#.

Before 9.0, snapshots were useful for saving the state of your world in order to restart from a backup in the future. Now, they are used for much more.

Define your world without deploying

Using the new C++ or C# SDK APIs, you can easily create a new snapshot from which to start your world. It’s as simple as defining some entities, adding them to a snapshot, and saving it to disk.

Let’s take a super easy C# example and create a snapshot with a single tree at the center of the world. First, we define our tree:

var tree = new SnapshotEntity();
tree.Add(new Transform.Data(position = Vector3.zero, rotation = Quaternion.identity));

var acl = Acl.Build()
    .SetReadAccess(AclUtil.PhysicsOrClientPredicate)
    .SetWriteAccess<TransformState>(AclUtil.PhysicsOnlyPredicate)
tree.SetAcl(acl);

Then, we create a dictionary that represents our snapshot in memory. It maps from EntityId to SnapshotEntity. To create the snapshot, it’s a single API call!

var snapshotEntities = new Dictionary<EntityId, SnapshotEntity>()
{
    { new EntityId(0), tree }
};

Snapshot.Save("path/to/snapshot", snapshotEntities);

With our tree statically saved to the snapshot, we can now launch a local or cloud deployment from it and observe the entity.

Some advantages and ideas

  • Now that it’s easy to define a snapshot statically, you can build all sorts of useful tooling. I built a tool to generate an initial snapshot from a Unity scene, for example!
  • You can commit multiple snapshots to source control as ‘scenes’ from which to start your world when developing locally.
  • Easily build tools to analyse your snapshots.
  • No longer have to define magic World App process that hang around for the duration of your deployment.
  • Take a large production snapshot and ‘snip’ an area of the world out of it into a new snapshot. Then, debug that area of the world with production data locally!

Can’t wait to see what you all build with the new tools :smiley:


Introducing the "coming-soon" tag for version 9.0 :)