Формат описания Компонентов и Префабов (Entity) для ECS. Часть 1. Спецификация

ab912ce42d6bb160a314f2274968e162

Привет, читатель! В этой статье не будет практики, а только спецификация формата и примеры для его объяснения. Код парсера будет в следующей части статьи!

Что такое ECS

ECS — Entity Component System (Сущности Компоненты Системы), это распространённый паттер программирования игр, используемый для упрощения разработки. В этом паттерне есть 3 определения:

  • Entity (Сущность) — контейнеры, хранящие в себе Компоненты (Данные). Сами не хранят свойства.

  • Component (Компонент) — классы/структуры, хранящие в себе всевозможные данные, нужные для игровой логики (Систем).

  • System (Системы) — Логические ядра игры. Они манипулируют сущностями и данными внутри них. Чаще всего реализуются классами

Если же вы хотите разобраться в теме подробнее, предлагаю вам вот эту статью.

Хочу отметить, что в Формате будет возможно описывать только ПЕРВЫЕ два определения, так как для описания игровой логики нужен язык программирования, а это задача сложная.

Зачем?

«Зачем?» — задаст вопрос читатель. И я отвечу — упрощение. Вот пример объявления компонента во ECS-фреймворке BrokenBricksECS:

namespace ECSExample {
    [Serializable]
    public struct FloatComponent : IComponent {
        public float value;
 
        public FloatComponent(float value) {
            this.value = value;
        }
    }
 
    public class FloatDataComponent : ComponentDataWrapper { }
}

Сначала мы здесь должны создать структуру, внутри которой будет значения и конструктор. Потом мы создаем FloatDataComponent. Это обёрнутый в ComponentDataWrapper FloatComponent. Разве это нужно?

Решение

Для этого я предлагаю создать формат описания компонентов и прототипов сущностей (префабов). И все что мне пришло на ум, так только это.

@component Component1 {
  value: int,
}
@component Comp2(Component1) {
  value2: str = "default_value" # Будет иметь value: int и value2: str
} # Родитель - Component1

Используя ключевое слово @component, мы создаем новый компонент. Внутри фигурных скобок типы объявляются так: : , также можно указать дефолтное значение : =

Комментарии начинаются с символа решётки # Комментарий

Наследование компонентов?

Компоненты могут наследоваться друг от друга. Это делается так:

@component () {
  data_from_parent,
  ...,
  new_and_overriden_data
}
# Пример
@component Component1 {
  value: int,
}
@component Comp2(Component1) {
  value2: str = "default_value" # Будет иметь value: int и value2: str
} # Родитель - Component1

Множественного наследования формат не поддерживает, так как есть проблема ромба.

Прототипы сущностей (Префабы)

А тут, во время написания, мне приходит мысль? А почему бы и не добавить в формат описание сущностей! И я добавил их:

@entity Name {
  Component1(value=10)
}
@entity Name2(Name) {
  Comp2(10, 'default_value')
}
@entity Name3 { # Равен Name
  Component1(10),
  Comp2(value=10)
}

Используя ключевое слово @entity , мы создаем новый прототип сущности. Внутри фигурных скобок компоненты добавляются так: (, =)

Наследование же работает также, как у компонентов.

Итог

Итого, у нас есть вот такой example-файл:

@component Component1 {
  value: int,
}
@component Comp2(Component1) {
  value2: str = "default_value" # Будет иметь value: int и value2: str
} # Родитель - Component1
@entity Name {
  Component1(value=10)
}
@entity Name2(Name) {
  Comp2(10, 'default_value')
}
@entity Name3 { # Равен Name
  Component1(10),
  Comp2(value=10)
}

В следующей части я напишу парсинговый механизм для этого формата. Удачи!

© Habrahabr.ru