Máquinas de Estado: Objeto de Estado versus verificação seqüencial: quais são os prós / contras?

8

Não sei muito sobre a máquina de estados finitos na IA ou sobre outros comportamentos do jogo, exceto este tutorial rápido com um Mineiro: http://www.ai-junkie.com/architecture/state_driven/tut_state1.html, que é orientado a objetos.

Realmente não sei se este tutorial descreve o padrão State ou não, o que você acha?

Não estou falando de outras coisas mais orientadas à aritmética, como direção, física, busca de caminhos ou colisões, mas sim lógicas de jogos, IA orientada a estados e coisas que envolvem muitos estados ife / ou switches simultâneos.

Quais são os prós / contras do uso de um padrão de estado ou uma verificação seqüencial de uma estrutura de estado simples como esta:

struct States
{
bool is_walking, is_running, holds_a_weapon, is_crouch;
int weapon_id, int id_team;
};

void HandleStates (States state)
{
//etc
}
jokoon
fonte
2
Eu acho que você pode precisar formular sua pergunta um pouco melhor, mas uma resposta rápida acima para que você possa fazer isso é que, em geral, o estado remove as verificações If. switch (state) {case blah} para criar uma tabela de salto, ou a minha maneira pessoal favorita de fazer as coisas, apontar funções ou delegar em uma pilha ou fila se a AI retornar ao que estava fazendo antes ou passar para a próxima. ..
James

Respostas:

10

Tentarei responder a isso da melhor maneira possível, mas há algumas "melhores práticas" nas quais não tenho certeza, mas tentarei decompô-lo da maneira mais limpa possível.

FSMs

Primeiramente, o tutorial do Miner é de Programming Game AI by Example por Mat Buckland (que eu recomendo que você obtenha como uma introdução ao AI). Ele usa uma enumeração para cada estado, NÃO uma estrutura. Com a estrutura no seu exemplo, você tem booleanos como estados, portanto, você pode ter qualquer número deles ao mesmo tempo. Isso pode levar ao comportamento desejado, mas na maioria das vezes com FSMs (Finite State Machines), leva a um comportamento indesejável.

Por exemplo:

enum
{
WANDER_AROUND,
ATTACK,
RUN_AWAY,
};

Em segundo lugar, essa não é a única maneira que ele descreve os estados. A maneira como eu pessoalmente prefiro (dependendo da situação) é criar uma classe abstrata chamada State que possui as funções Enter (), Exit () e Update (). Em seguida, crie meus estados como subclasses da classe State.

Como esta foto (encontrada na página 2 desse link, na verdade): texto alternativo

Padrão de Estado

Na minha opinião pessoal, o padrão de estado é apenas uma parte do design do software em que o software possui vários estados. A implementação é do desenvolvedor. Eu não acho que exista uma diferença adequada entre usar uma declaração de chave grande ou criar uma máquina de estado completa para executar todos os seus estados, como descrevi acima. Eles estão essencialmente fazendo a mesma coisa. Portanto, a esse respeito, a resposta para uma de suas perguntas é sim, acredito que essa página descreve o padrão de estado.

Prós e contras

Existem prós e contras em qualquer método usado para implementar um design controlado pelo estado.

Usando uma declaração If / Else ou Switch

Prós:

  • Muito fácil de adicionar e verificar as condições dos estados
  • Pode ser prototipado muito rapidamente

Contras:

  • Quando você tem vários estados, pode ficar muito feio, muito rapidamente.
  • Manter o controle de transições, efeitos quando o estado é inserido / encerrado ou qualquer coisa específica para o estado é difícil

Usando uma máquina de estado orientada a objetos

Prós:

  • Altamente extensível - a única coisa que você precisa fazer é criar um novo estado que herda a classe abstrata State
  • Manutenção fácil - Você não precisa se preocupar com código de aparência de espaguete, pois cada estado reside em sua própria classe. Você pode ver facilmente as condições associadas a esse estado sem se preocupar com os outros estados.
  • Intuitivo - Se você estiver trabalhando em um projeto de equipe com esse tipo de máquina de estado, será muito mais fácil para a pessoa ler o seu código. Eles não terão que ler linhas e linhas de código apenas para chegar a um determinado estado ("Programe sempre como se o programador que mantinha seu código fosse um psicopata que sabe onde você mora!" :))

Contras:

  • Curva de aprendizado leve - Esse design pode demorar um pouco para ficar completamente completo ao implementá-lo
  • Sinceramente, não consigo mais pensar nisso, pois prefiro assim, mas se alguém quiser adicionar, basta comentar e eu os adicionarei.

Espero que responda todas as suas perguntas. De fato, acabei de abrir minha cópia do Programming Game AI por Example e Mat menciona que a máquina de estados é conhecida como "padrão de design de estados". Pessoalmente, eu discordo, mas cada um na sua.

Espero que ajude :)

Ray Dey
fonte
11
+1 isto descreve essencialmente como eu criei minha Máquina de Estado. Está funcionando bem.
Kyle C
Você poderia argumentar que há um impacto no desempenho com o padrão "máquina de estado orientada a objetos" - por menor que seja?
Noob Saibot
@NoobSaibot Sim, mas você pode argumentar sobre isso. O if-else pode sofrer com uma previsão de ramificação ruim, o padrão de estado, conforme descrito acima, pode sofrer com a sobrecarga de consulta da tabela. Ambos são improváveis, a menos que você tenha muitos estados. Portanto, a verdadeira resposta para sua pergunta é "depende".
Ray Dey