Estrutura da unidade de jogo RTS

18

Eu quero uma maneira de criar muitas unidades diferentes sem precisar programar coisas como as ações moveTo e Attack mais de uma vez

Do jeito que eu vejo, existem 2 maneiras de fazer isso.

  1. Uma única classe de unidade genérica com sinalizadores que especifica o que pode / não pode fazer (crie instâncias em uma matriz estática e agarre-as quando necessário)
  2. Classe de unidade abstrata com métodos abstratos para ações específicas da unidade, como (Ataque, Colheita, Patrulha), que precisam ser implementadas nas subclasses , mesmo que a unidade não possa realmente coletar nada.

a primeira maneira de fazer isso parece a mais simples, mas eu acabaria tendo um monte de código não sendo usado para a maioria das unidades.

a segunda maneira também poderia funcionar. Mas se eu decidir ter duas unidades diferentes que podem coletar recursos, terei exatamente o mesmo código em duas classes diferentes, o que não parece ser o caminho certo para fazê-lo.

Essa é a abordagem correta para esse problema?
Em um jogo como AoE, todas as unidades têm, o que eu presumo, algum tipo de lista de ações / ordens, eu realmente gostaria de saber como obter algo semelhante a esse, onde eu possa apenas codificar cada ação / ordem uma vez, e depois, entregue-o a todas as unidades que precisam da referida ação.

Se não estiver claro (altamente plausível) ou se precisar de mais informações sobre o que exatamente estou procurando, pergunte-me em um comentário.

Daniel Holst
fonte

Respostas:

25

Uma abordagem comum é ter uma abordagem baseada em componentes em que a "Unidade" da classe base apenas implemente os aspectos mais básicos que todas as unidades têm em comum, enquanto cada unidade possui uma lista de vários objetos-componentes que dizem o que pode fazer e como faz.

Por exemplo, um tanque pode ter os componentes Mobile, Destructible, Attacker, um imóvel torreão única Destructible, Attackere uma colhedora Mobile, Destructible, Harvester. Essas classes incluiriam todo o código necessário para implementar esses comportamentos. Interações entre componentes (um Attackerpode danificar apenas o que é Destructible) podem ser implementadas solicitando que o componente verifique se a outra unidade possui o componente necessário e depois interaja diretamente com esse componente.

A vantagem sobre uma herança de classe clássica é que você pode combinar habilidades facilmente. Por exemplo, quando você deseja ter uma colheitadeira que também possa atacar, transportar infantaria e voar, basta adicionar os componentes necessários. Você também pode adicionar e remover facilmente novos recursos na forma de novos componentes sem precisar inchar a classe básica da unidade.

O Unity oferece suporte a essa arquitetura, porque todo o mecanismo já é baseado em componentes. Portanto, componentes lógicos do jogo como esses podem ser adicionados na forma de scripts.

Philipp
fonte
Então, na unidade, eu desabilitaria e habilitaria os componentes conforme necessário?
Daniel Holst
@DanielHolst Não, você os adicionaria e os removeria, conforme necessário. Você pode fazer isso no editor do Unity ou com scripts usando gameObject.AddComponente gameObject.RemoveComponent.
Philipp
ah tudo bem, mas diga para uma ação / ordem "moveTo". como a unidade saberia quando o pedido é feito? e como eu enfileiraria os pedidos?
Daniel Holst
2
@DanielHolst Eu acho que você entendeu algo errado. O Movingcomponente significa "esta unidade geralmente é capaz de se mover". O componente está permanentemente conectado a ele, independentemente de a unidade estar em movimento ou não. Isso não significa que está se movendo agora . Embora você também possa fazer isso dessa maneira, adicione um MoveOrdercomponente a ele e faça com que esse componente se remova da unidade quando o pedido for atendido ou cancelado.
Philipp
11
@DanielHolst Agora você está à deriva na direção da unidade AI, que é uma outra lata de minhocas. Uma abordagem possível seria ter uma biblioteca de componentes AIScript que pressupõem a presença de determinados componentes ou alteram seu comportamento, dependendo de quais componentes a unidade está tendo. Mas esse é realmente um tópico muito complexo para ser tratado em um comentário.
Philipp
4

Muitos jogos usam um sistema baseado em componentes para entidades, onde é possível adicionar vários comportamentos e habilidades a um tipo de unidade mais genérico, em vez de ser codificado como parte da classe da entidade (ou equivalente).

Ross Taylor-Turner
fonte
isso seria extremamente difícil de implementar?
Daniel Holst
Padrões como esse são usados ​​para facilitar a implementação em geral. Se você não pode decidir qual abordagem adotar, é uma boa ideia começar da maneira mais simples possível e aumentar sua escolha à medida que estiver com mais funcionalidade. Depois de ter mais noção do problema, você pode refatorar ou reescrever uma abordagem que se adapte melhor à sua situação.
Ross Taylor-Turner
11
@DanielHolst Percebo que sua pergunta tem a Unitybandeira. O Unity já possui um sistema de componentes embutido e favorece fortemente a composição sobre a herança . Um método simples seria criar um MonoBehaviourpara cada tipo de ação e anexar a cada tipo de unidade pré-fabricada as ações que ele pode executar (personalizar as instâncias de ação com detalhes por tipo, como valores e custos de danos). Isso mantém a criação da sua unidade orientada por dados, para que você possa criar facilmente muitos tipos de unidades personalizadas.
DMGregory
@DanielHolst Isso depende da sua definição de "extremamente difícil". Minha resposta entra em mais detalhes sobre como isso pode ser implementado.
Philipp