Estou trabalhando em um jogo com uma arquitetura baseada em componentes. Um Entity
possui um conjunto de Component
instâncias, cada uma com um conjunto de Slot
instâncias com as quais armazenar, enviar e receber valores. Funções de fábrica, como Player
produzir entidades com os componentes e conexões de slot necessários.
Estou tentando determinar o melhor nível de granularidade para componentes. Por exemplo, agora Position
, Velocity
e Acceleration
são todos os componentes separados, conectados em série. Velocity
e Acceleration
pode ser facilmente reescrito num uniforme Delta
componente, ou Position
, Velocity
, e Acceleration
poderia ser combinada juntamente com tais componentes, como Friction
e Gravity
em um monolítico Physics
componente.
Um componente deve ter a menor responsabilidade possível (ao custo de muita interconectividade) ou os componentes relacionados devem ser combinados em componentes monolíticos (ao custo da flexibilidade)? Estou inclinado para o primeiro, mas eu poderia usar uma segunda opinião.
fonte
Respostas:
Há uma linha entre a granularidade completa, levando a nenhum desperdício de código ou estado do tipo blob (e é por isso que as arquiteturas de componentes são favorecidas) e usabilidade.
Obviamente, as coisas podem ter um
Position
, mas não são necessariamente dinâmicas (então, por que têmVelocity
eAcceleration
?). No entanto, algo comVelocity
a será um objeto em movimento, por isso faz sentido também terAcceleration
agrupado.Você vai ter um caso em que v e um vai ser necessário, mas você não quer uma simulação de física para eles? Da mesma forma, haverá um ponto em
Gravity
que não sejam objetos de física?tl; dr Agrupe o que faz sentido.
fonte
Entity
temPosition
e alguns componentes que o fazemPosition
participar da física, entãoEntity
é de fato físico. Acho que o que posso fazer é adicionar alguns componentes para o agrupamento lógico e manter todos os componentes fundamentais em uma única responsabilidade. Assim, adicionando, digamos, umMovable
a umEntity
teria o mesmo efeito que a adição de umPosition
,Velocity
eAcceleration
.Para evitar a microgerenciamento de todas as variáveis que eu sugeriria, começando pesado, escolha divisões em torno da responsabilidade e refatorar quando a situação se apresentar logicamente. Você pode iniciar os primeiros desenhos no papel. Em algum momento, essas divisões brutas de responsabilidade se tornarão os blocos de construção de suas entidades.
Então, para um exemplo apressado, você tem o Game. O jogo é dividido em Ambiente + Estado. O ambiente é dividido em StaticWorld + MovingStuff. O estado é dividido em AIControlled + PlayerControlled. A idéia grosseira de Dano se divide em TakesDamage + GivesDamage.
E assim por diante.
Muito parecido com o conselho comum de "Construir jogos, não mecanismos!" para novos profissionais, recomendo "Construir jogos, não sistemas de componentes elaborados!" porque somente com experiência pessoal em um jogo em execução você saberá se é necessário um sistema elaborado de componentes em trabalhos futuros.
fonte
Meu palpite seria combinar componentes que tenham muita interação. No seu caso, eu manteria a posição em um único componente e manteria a velocidade e a aceleração juntas em um componente da física.
Mas isso depende muito de quais são os recursos do seu jogo (a menos que você esteja construindo uma estrutura sem nenhum jogo específico em mente).
fonte
Sei que essa é uma pergunta antiga, mas talvez alguém ache essa resposta útil.
eu acredito
Systems
isso ajudará você a entender melhor como construir componentes. Os sistemas existem em arquiteturas em que os componentes não contêm sua própria lógica, além de simples getter / setters e funções auxiliares. Os sistemas operam em entidades que atendem aos requisitos do componente. É por isso que é melhor separar os dados do componente, tanto quanto faz sentido que esses dados sejam processados sem os outros dados.Por exemplo, você pode ter um
MovementSystem
que atualize suas Entidades comPosition
base nas delesVelocity
. Isso pode ser para entidades simples no jogo. Mas, para o Jogador e Inimigos, você pode querer um movimento que possui oAcceleration
qual é processadoAcceleratedMovementSystem
. Mas para Obstáculos você pode quererFriction
. O Terreno também pode ter atrito, mas não terá um componente de velocidade. Mas que talGravity
? Apenas adicione Player, Inemy e Obstacle e crie umGravitySystem
para processá-lo.A linha inferior é que quanto mais dissociado seu
Components
for, mais extensível oEntities
será quando usandoSystems
.Edit: Tornou a última declaração mais clara.
Edit: Ok, eu tenho trabalhado no meu próprio sistema e chegou a essa conclusão. Um exemplo para dividir Position e Velocity é que manipular Velocity faz com que a Position mude com um MovementSystem. Como resultado, um 'InputMovementSystem' não precisa de uma posição para fazer com que o Player se mova da entrada do usuário porque o MovementSystem capta as alterações no Velocity para aplicar à posição. Concedido, ainda funcionaria bem para reuni-los, mas esse é um exemplo de por que não precisa ser.
Li recentemente um post no blog que dizia algo assim:
fonte