Skip to content

Simplified scene and reflection serialization #4153

@AronDerenyi

Description

@AronDerenyi

What problem does this solve or what need does it fill?

Right now serialized scene files are too big and verbose. Take for example the scene example file:

[
  (
    entity: 0,
    components: [
      {
        "type": "bevy_transform::components::transform::Transform",
        "struct": {
          "translation": {
            "type": "glam::vec3::Vec3",
            "value": (0.0, 0.0, 0.0),
          },
          "rotation": {
            "type": "glam::quat::Quat",
            "value": (0.0, 0.0, 0.0, 1.0),
          },
          "scale": {
            "type": "glam::vec3::Vec3",
            "value": (1.0, 1.0, 1.0),
          },
        },
      },
      {
        "type": "scene::ComponentB",
        "struct": {
          "value": {
            "type": "alloc::string::String",
            "value": "hello",
          },
        },
      },
      {
        "type": "scene::ComponentA",
        "struct": {
          "x": {
            "type": "f32",
            "value": 1.0,
          },
          "y": {
            "type": "f32",
            "value": 2.0,
          },
        },
      },
    ],
  ),
  (
    entity: 1,
    components: [
      {
        "type": "scene::ComponentA",
        "struct": {
          "x": {
            "type": "f32",
            "value": 3.0,
          },
          "y": {
            "type": "f32",
            "value": 4.0,
          },
        },
      },
    ],
  ),
]

It takes 64 lines to describe 2 entities with a total of 4 components. It's also hard to read and understand with all the indentation. This is mostly because of the way reflected items are serialized so all of the above also apply to them.

What solution would you like?

Luckily the Rusty Object Notation (RON) has introduced named structs which can be used to merge the type and value into a single item like so:

changing

{
  "type": "glam::vec3::Vec3",
  "value": (1.0, 1.0, 1.0),
}

to

glam::vec3::Vec3(1.0, 1.0, 1.0)

This way we remove the "type" and "value" keys and also a layer of indentation. Applying all of this to the example file we get the following:

[
  (
    entity: 0,
    components: [
      bevy_transform::components::transform::Transform(
        translation: glam::vec3::Vec3(0.0, 0.0, 0.0),
        rotation: glam::quat::Quat(0.0, 0.0, 0.0, 1.0),
        scale: glam::vec3::Vec3(1.0, 1.0, 1.0),
      ),
      scene::ComponentB(
        value: alloc::string::String("hello"),
      ),
      scene::ComponentA(
        x: f32(1.0),
        y: f32(2.0),
      ),
    ],
  ),
  (
    entity: 1,
    components: [
      scene::ComponentA(
        x: f32(3.0),
        y: f32(4.0)
      )
    ],
  ),
]

This is only 28 lines long with a lot less indentation while keeping all of the information of the current file. This is subjective but to me it's just as if not more readable than the current one. And while we're at it we can further simplify by treating the scene as a map where each key is and entity and their corresponding values are lists of their components. Like so:

{
  0: [
    bevy_transform::components::transform::Transform(
      translation: glam::vec3::Vec3(0.0, 0.0, 0.0),
      rotation: glam::quat::Quat(0.0, 0.0, 0.0, 1.0),
      scale: glam::vec3::Vec3(1.0, 1.0, 1.0),
    ),
    scene::ComponentB(
      value: alloc::string::String("hello"),
    ),
    scene::ComponentA(
      x: f32(1.0),
      y: f32(2.0),
    ),
  ],
  1: [
    scene::ComponentA(
      x: f32(3.0),
      y: f32(4.0)
    )
  ],
}

I prefer the last version for the following reasons:

  • It's compact while still containing every bit of information
  • It more closely resembles the corresponding structs in rust
  • It's clear what each indentation level means (first: entities, second: components, third: component properties and so on)

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-ScenesSerialized ECS data stored on the diskC-UsabilityA targeted quality-of-life change that makes Bevy easier to use

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions