Maquinas de estados finitos
Autor: Caio Vinicius Marques Teixeira | Publicado: 2012-01-03T15:04:00-02:00



Passaram-se
seis meses desde o inicio de nosso projeto, e aqui estamos nós, firmes e fortes
iniciando uma nova fase, com certeza a mais difícil de todas: o
desenvolvimento. Durante os últimos meses trabalhamos toda a parte do
planejamento do game, fase esta que concluímos com sucesso. A partir de agora
entraremos na parte pratica, mostrando toda a evolução em relação a projeto e
aprendizado, este post mostra um dos primeiros conceitos utilizados em relação
à programação: A máquina de estados finitos.

Uma dos
principais problemas no desenvolvimento de um game, é como simular uma falsa
inteligência artificial, para isso utiliza-se vários métodos e algoritmos , um
deles é a FSM (Finite State Machine) ou maquina de estados finitos. As máquinas
de estados (não apenas a FSM, existem diversos tipos) são utilizadas em
diversos ramos desde matemática até a engenharia, e é muito utilizada no setor
de desenvolvimento de games.

Algumas das
vantagens de utilizar máquinas de estados finitos:

Simples e
rápidas de codificar: Implementar máquinas de estados finitos é fácil,
muito mais do que os métodos convencionais;
Fáceis de
debugar: Utilizando as FSM’s é muito mais encontrar e solucionar eventuais
problemas;
Não
exigem grandes recursos computacionais: Utilizar máquinas de estados também
ajuda na questão do desempenho, pois no geral, são leves e não exigem grande
volume de processamento;
São
intuitivas: É muito simples e intuitivo entender e estruturar uma máquina
de estados. Você entenderá como elas funcionam um pouco mais a frente;
São
flexíveis: Dependendo do método de implementação utilizado, é muito simples
expandir uma maquina de estados.






Mas afinal, o
que é uma máquina de estados finitos?

O conceito de
maquina de estados é um tanto extenso, portanto não entrarei em detalhes, e
farei uma descrição bem básica, mas suficiente para a utilização das mesmas.
Uma máquina de estados finitos consiste basicamente em decompor um objeto em um
numero determinado de estados (status atual do objeto) e transições (condições
de transição de um estado para outro). O conceito em si é simples, mas vejamos
alguns exemplos:

Pense em uma
lâmpada, ela basicamente pode ter dois estados: ligada e desligada. As
transições entre esses estados são determinados por um toque no interruptor.
Pode-se representar isso graficamente com um diagrama UML:



&nbsp;&nbsp; 


Podemos pensar
em outro exemplo clássico, que tal pensarmos em um jogo? Pacman, um clássico,
foi implementado utilizando o conceito de máquinas de estados finitos, pensemos
nos “fantasminhas”, eles basicamente possuem três comportamentos (estados): Patrulhando, Perseguindo e Fugindo. E
suas transições são simples, o estado inicial é Patrulhando onde fazem
movimentos aleatórios, quando o Pacman é avistado passa ao estado Perseguindo
onde o persegue, mas quando o Pacman come uma “pílula”, o estado passa a ser Fugindo,
neste momento um timer é ativado e quando terminado volta-se ao estado inicial.





De uma forma
mais geral, podemos dizer que uma FSM é uma espécie de “Sistema baseado em
regras”, onde regras pré-estabelecidas determinam qual vai ser o próximo passo.
Essas regras são dispostas em um conjunto no clássico estilo if...then...else. Portanto pode-se
imaginar que existem diversas maneiras de se implementar uma máquina de
estados, irei descrever dois deles, o básico com If...then...else/switch e
as state
patterns.

· If...Then...else/switch: É o método
mais simples de se fazer uma maquina de estados finitos, utiliza-se uma
estrutura switch básica, que testa as condições para passagem de estados.
Deve-se utiliza-la dentro de um método que execute continuamente, como o método
Update (apesar de por questões de desempenho seja recomendável utilizar uma
Coroutine);

· State Patterns: Um dos maiores
problemas de implementar uma FSM com estrutura switch, é que quando a
quantidade de estados tornar-se muito grande, o código ficará grande e confuso
dificultando a manutenção. Uma das soluções, é utilizar State Patterns, esse
método de implementação é baseado em herança e polimorfismo, fazendo com que
cada estado seja uma classe (que herda de uma classe abstrata), o que torna
muito mais fácil a manutenção da FSM e a adição de novos estados.



Exemplo prático

Para
aprendermos a utilização de maquinas de estados finitos em projetos reais, nada
melhor do que partir para a pratica. Decidimos utilizar um exemplo dado em uma
videoaula que vimos (referencias). Neste exemplo
simulamos o caso de um inimigo que tem dois estados: Patrulhando e Perseguindo,
no estado Patrulhando fica andando de um lado ao outro, no estado Perseguindo
persegue o inimigo até uma distância determinada. Observe o diagrama abaixo:



&nbsp; 

Implementamos
este exemplo utilizando os dois métodos de FSM’s já citados: Switch e State
Patterns. Pode–se perceber que visualmente não há diferenças, porém na questão
de organização de código a diferença é grande. Abaixo temos o exemplo jogavel
(é necessário ter o Unity Web Player instalado) e os links para download de
ambos os métodos de implementação.

Clique para testar  


Downloads
Projeto 1 - Switch
Projeto 2 - State Patterns

Referencias
Tese sobre maquinas de estados em jogos 
Tutorial sobre FSM's (em inglês)
Documento sobre FSM's
Slides interessantes sobre FSM's
Slides interessantes sobre Inteligencia Artificial
Videoaulas sobre FSM's no Unity3D