Skip to content
This repository has been archived by the owner on Mar 25, 2020. It is now read-only.

Serialization

pointcache edited this page Jan 16, 2017 · 7 revisions

It is based on the idea that everything in the game is a prefab. By knowing the prefab id, we can represent entities as that id.

Serialization in URSA:

  • Saves entities transform info, as well as parenting (only to other entities and components, not gameobjects)
  • Saves components data located in their SerializedData

Since Entity is a abstracted composition of GameObjects and components, the need for parenting woes is reduced, thus URSA encourages you not to create complex hierarchical logic, but rather use hierarchy for scene organizational purposes, and "container" logic, like inventories, modular objects etc.

All serialization (with exception of Configs) happens in SaveSystem. It is responsible for saving scene state, PersistentData state and Blueprints

Components mix prefab data (variables that are directly in the body of the component, outside of data class) and SerializedData. Prefab data will always come from the prefab, ensuring that updates to the game will propagate to save files. SerializedData ensures that those updates wont overwrite vital object state, like weapon durability, etc.

When saving we use this data structure:

  • SaveObject
    • EntityObject
    • CompRefs
    • ComponentObjects

When serializing we collect all objects of interest and create a specialized data storage middleman for each type. We store them remembering id's of their parents. We store SerializedData from components as well.

On deserialization Entities are created from the database by their database_ID, and assigned their saved instance_ID. Components don't have instance id, they use their parent Entity id in conjunction with their unique id. So from the point of view of a component his id is Entity.Instance_ID + Component.ID So when deserializing the parenting mechanism and ref linker will first locate parent entity, and through it the target component.

SaveObject describes the whole bunch of target entities we want to save

[Serializable]
public class SaveObject
{
    public bool isBlueprint;
    public List<EntityObject> entities = new List<EntityObject>();
    public List<CompRef> comprefs = new List<CompRef>();
    /// <summary>
    /// entity id, (component persistent ID, component)
    /// </summary>
    public Dictionary<string, Dictionary<string, ComponentObject>> components = new Dictionary<string, Dictionary<string, ComponentObject>>();
}

EntityObject describes the root entity:

public class EntityObject
{
    public string database_ID;
    public string instance_ID;
    public string blueprint_ID;
    public string parentName;
    public string gameObjectName;
    public bool   parentIsComponent;
    public bool   parentIsEntity;
    public string parent_entity_ID;
    public string parent_component_ID;

    public Vector3 position;
    public Vector3 rotation;
    public Vector3 scale;
}

ComponentObject

[Serializable]
public class ComponentObject 
{
    public string component_ID;

    public SerializedData data;
}

SerializedData is directly injected into middleman, it's serialization is fully (with exception of CompRef) handled by FullSerializer

Clone this wiki locally