2017-01-15 19 views
1

Я пытаюсь обернуть голову вокруг систем сущности игры и использовать GamePlayKit. я борюсь со следующим сценарием:Должен ли GKEntity иметь свойства или методы доступа к функциям компонента?

  • RenderComponent является GKComponent, который ссылается на SKSpriteNode, чтобы показать свою сущность.
  • MetaDataComponent еще один компонент, который содержит различные биты информации об объекте (например, в моем случае, это будет содержать свойства, как MapX, MapY ...)

У меня есть CharacterEntity, производные от GKEntity.

Чтобы инициализировать объект, я передаю имя текстуры, используемой для спрайта. Это позволяет мне создать RenderComponent.

Для инициализации MetaDataComponent У меня есть три варианта, и мне интересно, считается ли одна из них лучшей практикой (а также, какая из них - худшая практика)?

  • Для каждого свойства в моем компоненте, добавьте параметр к init()
  • Expose свойств в Character класса, который будет обновлять свойства компонента.
  • Передайте объект модели моему объекту и инициализируйте компонент из этого.

Мои мысли:

  • Номер 1: Чем больше компонентов моя сущность, тем больше PARAMS я получаю ... это не мое предпочтение.
  • Номер 2: сущность должна быть «глупой» и не содержать никаких данных. В самой чистой форме объект - это всего лишь число. Добавление реквизита там «чувствует» неправильно.
  • Номер 3: наличие модельного объекта, такого как MetaData, мне кажется лучшим, но также избыточным, потому что данные тогда находятся в компоненте и в объекте модели. Может быть, компонент хранит объект модели вместо его свойств?

Чтобы привести другой пример: если я ожидаю, что у объекта будет RenderComponent, я могу запросить этот компонент и использовать его. Или я мог бы добавить метод к самой сущности, например setRenderPosition, которая проверяет наличие необходимого компонента и обновляет его. Опять вопрос: есть ли здесь право или не так?

+0

Отличный вопрос. Это «забытая» структура игровых WIP игр Apple, так же, как CAKeyFrameAnimation - это забытое средство анимации на платформах Apple. – Confused

ответ

1

Если вы ищете чистый Entity Component System то конструкция состоит из трех частей:

Entity: Вот, как вы говорите, просто номер. Ничего больше.

Component: Это всего лишь данные. Ничего больше.

System: Забытая часть. Здесь сидит логика. Вы можете наследовать от GKComponentSystem<GKComponent>, чтобы создать свои собственные системы в SpriteKit.

Это article и это supporting code помогло мне в понимании ECS. DemoBots example - это еще один пример для реализации, ориентированной на spriteKit.

Поскольку у SpriteKit есть своя реализация ECS и другие причуды, необходим какой-то компромисс. вам нужно отобразить узел, поэтому, если вам нужен SpriteComponent, вам нужно встроить узел в SpriteComponet или сделать что-то еще - я предпочел не иметь SpriteComponent, я создал VisualEntity, который наследует от GKEntity, но это я предпочитаю сосредоточиться на компонентах, которые имеют поведение, которое зависит от цикла запуска update.

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

guard let spriteComponent = entity?.component(ofType: SpriteComponent.self) else { 
    return 
} 

Важно быть гибким, вписываться в SpriteKit и быть в курсе компромиссов, которые вы делаете.

+0

Глядя на демонстрации Apple, я вижу функции в компонентах, и они используют системы для обновления компонентов в определенном порядке. Для меня это означает, что их подход не является традиционным или «чистым». Согласитесь? С вашими знаниями о ECS, не могли бы вы взглянуть на http://gamedev.stackexchange.com/questions/135259/how-to-add-the-concept-of-entities-and-components-into-an-isometric -tile-map тоже? – Krumelur

0

Опция для рассмотрения имеет расширения на GKEntity.

import SpriteKit 
import GameplayKit 

extension GKEntity { 
    var isSelected: Bool { 
     guard let component = self.component(ofType: SelectionComponent.self) else { 
      return false 
     } 

     return component.selectionLocation != nil 
    } 
} 

Это делает функциональность доступной для всех объектов.

if self.someEntity.isSelected { 
    // Handle 
} 

 Смежные вопросы

  • Нет связанных вопросов^_^