# Serialization system

The serialization system is used to automatically serialize the instance attributes of the mini game framework into persistent data, and then deserialize the data into instance attributes.

The serialization system is used in many places, such as saving and loading components or resources, persistence of script components, displaying properties in the inspector window, configuration windows, etc.

# Script component

The developer uses the serialization system in the script component template created in the Project window.

@engine.decorators.serialize("Move")
export default class Move extends engine.Script {
  @engine.decorators.property({
    type: engine.TypeNames.String
  })
  public name: string = "myname"
}

serialize decorator, first, developers can use the serialize decorator to indicate that it is a serializable script, and set a globally unique name for the serialization type as an input parameter.

property decorator, the developer can add a property decorator to one of his properties to indicate that it is a serializable property, and use type to indicate what type of property it is.

# property decorator

After marking the attributes, the mini game framework knows how to deal with this sequenceable script, which is mainly reflected in two places.

  1. UI. Serialization displays this attribute in the Inspector window according to this type, and guarantees what you see is what you get. In the process of debugging in playback mode, the value of this attribute in memory will be updated to the Inspector panel in real time. Developers can also directly modify the value of this attribute through the panel. Support multiple selection and batch editing.

  2. Save and restore. The same script class can have different instances on different entities, and different instances can have different attribute values. Developers can directly modify the value of the property on the UI in the editing mode. When saving the Scene, the serialization system can know what type to save the property through the property decorator. When the Scene is opened again, the serialization system can also know how to restore this attribute to the previously saved value. So that the small game tool can realize the ability of visual editing of resources. However, in the playback state, the modification of attributes cannot be saved.

# Attribute Type

The property decorator provides a lot of types.

# Pure numeric type

Such as String, Boolean, Number, Object.

The Object type is special, it is a general JSON Object, but does not maintain the reference relationship. When saving, it is pure JSON.stringify(). When deserializing, JSON.parese will have multiple instances after instantiation. No UI is displayed. It is recommended to use nested types to achieve

# Array type

Developers can complete the definition by adding an array to the type. For example, type: [engine.TypeNames.String] means an array of indefinite length characters.

@engine.decorators.property({
  type: [TypeNames.String]
})
public names: string[] = ["myname"]

# Component type

Declared as a component type, which means that the attribute refers to a certain component. The developer first declares such a type, and then drags an entity into the corresponding property of the inspector in the Hierarchy window. The tool finds this type of Component on the entity, and then assigns the reference to the property. When saving, the serialization of the reference relationship will be specially handled to ensure that it can be restored the next time it is started. Developers can also use code to assign values ​​in the playing state, and the inspector will also update in real time.

@engine.decorators.property({
  type: TypeNames.Transform3D
})
public target: engine.Transform3D

The type does not have to be an enumeration value under engine.TypeNames, it can also be directly declared as the compoennt class of the small game framework.


@engine.decorators.serialize("Shoot")
export default class Shoot extends engine.Script {...}

@engine.decorators.serialize("Move")
export default class Move extends engine.Script {
  @engine.decorators.property({
    type: engine.Transform2D
  })
  public target: engine.Transform2D

  @engine.decorators.property({
    type: Shoot
  })
  public shootComp: Shoot
}

# Resource Type

Declaring it as a resource type means the reference relationship of an attribute to a resource singleton. For example, when the type type is a Texture2D, the developer can drag a texture2d image of the Project window to the properties of the Inspector window.

After saving the changes, the Scene or Prefab can be statically dependent on this resource. When used, it actually assigns the singleton of this resource to the attribute, so that developers don't need to load this resource by themselves.

@engine.decorators.property({
  type: TypeNames.Texture2D
})
public tex: engine.Texture2D

# Attribute nesting

Developers can create an ordinary class that uses a serialization system, not necessarily a script component, to implement complex properties nested in layers.


@engine.decorators.serialize("Rank")
export class Rank {
  @engine.decorators.property({
    type: [engine.TypeNames.String]
  })
  public rankNames: String[] = ['Bronze','Gold']
}

@engine.decorators.serialize("Soldier")
export default class Soldier extends engine.Script {
  @engine.decorators.property({
    type: Rank,
  })
  public rank: Rank = new Rank()
}

# Custom serialization and deserialization

In addition to indicating that the UI is visible is what you get, @property is also used to indicate how to persist in Prefab/Scene. If the default logic is used, the developer does not need to understand how the data is saved at all, but if some data is too complicated to use the default saving capability, the developer also customizes the serialization and deserialization functions.

Developers can define onDeserialized as a custom deserialization function, or onSerialized as a serialization function. The custom function is executed after the default logic is executed, and the result of the default processing is returned to the developer's code for post-processing.

@engine.decorators.serialize("Soldier")
export default class Soldier extends engine.Script {
  @engine.decorators.property({
    type: engine.TypeNames.String
  })
  public Name: String ='janzenzhang'
  // Custom deserialization logic
  onDeserialized(json) {
    this.Name = json.Name.toLowerCase()
  }
  // Custom serialization logic
  onSerialized(dataJson) {
    dataJson.Name = this.Name.toUpperCase()
  }
}

# Attribute configuration items

The @property decorator has many other configuration capabilities besides defining what type of attribute the type indicates.

interface IPropertyBaseConfig {
  deserialize?: boolean; // Whether to participate in deserialization
  serialize?: boolean; // Whether to participate in serialization
  required?: boolean; // can it be undefined
  visible?: boolean; // Is it visible in the tool, not displayed when === false
  tooltips?: string; // Property description
  placeholder?: string; // placeholder attribute of string type input box
  readonly?: boolean; // not editable when ===true
  animatable?: boolean; // When true, it means that this value can be controlled by animation (animationClip).
}

# Hot Update

In the editing mode, developers' modifications to the script can be hot-updated to the tool. After the script is edited, it will be compiled first, and injected into the environment after compilation, and all corresponding components on the field will be replaced with new ones, while retaining the previous data as much as possible.

点击咨询小助手