Estou implementando um NPC para percorrer um espaço virtual, especificamente um gato. Eu tenho uma série de clipes curtos de animação (3-5 segundos). Meu primeiro instinto foi escolher uma animação aleatória quando a última terminou, mas percebi que ela não pareceria realista, pois mudaria de comportamento com muita frequência, mesmo que a próxima animação seja limitada a possibilidades fisicamente contingentes.
Minha solução pretendida é algo como uma árvore de comportamento ( http://www.gamasutra.com/blogs/ChrisSimpson/20140717/221339/Behavior_trees_for_AI_How_they_work.php ), em que cada animação tem uma lista ponderada das próximas animações. Ou seja, se o gato está andando, ele tem 80% de chance de continuar andando, 20% de sentar, 0% de dormir. Basicamente, usando um modelo markov para obter o próximo passo apropriado.
No entanto, não tenho idéia se essa é uma boa solução, nem sei como vou gerar o mapeamento da animação atual para a próxima animação potencial + probabilidade. 30 animações * 30 próximas animações = 900 ponderações. Isso é muito para calcular manualmente.
Às vezes, o gato reage se atingir um obstáculo, mas o problema do problema é escolher uma sequência realista de animações sem selecioná-las com antecedência. Na árvore, também haveria outras informações, como proximidade com uma pessoa, localização na sala, tempo desde a última vez que comi etc.
fonte
Respostas:
Geralmente você precisa dividir a lógica dos gatos das animações.
Agora, primeiro você precisa escrever a lógica dos gatos. Uma boa abordagem que encontrei é dividir a lógica em camadas.
Necessidades
O gato pode ter algum estado com alguns motivos / necessidades (comer, dormir etc.) que crescem lentamente ao longo do tempo e diminuem ao fazê-lo (pense nos Sims). Você pode escolher a tarefa atual que atenda à maior necessidade usando a lógica difusa, se desejar.
Tarefas
Agora, a cada momento, o gato tem uma tarefa (encontrar comida, encontrar cama para dormir, espaço para correr, etc. ficar inativo também é uma tarefa). Essas tarefas dizem ao gato para onde ir e o que deseja fazer.
Ações
Agora há a terceira camada - ações. Cada objetivo tem uma fila de ações a serem executadas (levantar-se, caminhar, agachar-se, comer etc.). Cada ação é responsável por sua execução. Por exemplo, a ação de andar deve verificar se há obstáculos e entregar o gato do ponto A ao ponto B, possivelmente contendo e executando sub-ações (pular obstáculos, agachar-se embaixo dos móveis e etc.).
Animações
Agora, quando o gato tiver necessidades, uma tarefa e uma ação, você poderá escolher a animação certa para essa ação. Conhecendo a animação atual e a próxima, você poderá fazer a transição de uma para outra. Por exemplo, se a tarefa diz que o gato deve deitar depois de caminhar até o travesseiro, as animações são colocadas em fila - ande, pare, sente e coloque.
O enfileiramento de animações pode ser feito de maneira eficaz se você os mapear em um gráfico como nós e conectar os nós entre animações transicionáveis (por exemplo, é possível andar para sentar, mas pular para mastigar - não). Em seguida, você pode enfileirar animações de cada uma delas usando A * neste gráfico.
Exemplo: o gato precisa descansar e comer. Deixe a tarefa "Descansar" encontrar um lugar para descansar, passear com o gato, deitar e descansar. Deixe a tarefa "Descansar" verificar as condições de vez em quando, se o ambiente ficar desconfortável - deixe a tarefa terminar. Verifique o que o gato quer agora mais, se ainda quiser descansar - repita a parte anterior. Quando o gato estiver descansado - escolha uma nova tarefa.
fonte
Eu acho que o que você está procurando é a máquina de estados finitos ou FSM. Em suma, é uma maneira de mudar o comportamento dos NPC: s de acordo com seu estado atual.
EDITAR:
É como uma árvore de comportamento, mas condensada em alguns "estados" de grupos aos quais o NPC retorna. Uma árvore de comportamento permite muito mais flexibilidade do comportamento, mas também precisa de mais dados para ponderar as probabilidades (uma maneira inteligente de automatizá-lo é com tags, como scriptin sugere em sua resposta). Ao usar estados, você decide um determinado conjunto de ações e probabilidades para essas ações no estado. Para alterar efetivamente, a ação atual pode ser enviesada com talvez 80% para manter a mesma ação. Se a ação for alterada, diferentes probabilidades serão usadas para selecionar a nova ação.
No seu caso, os estados podem ser (um pouco simplificados):
Cada estado pode ter probabilidades diferentes de mudar de estado, por exemplo, o estado de raiva ou cicatrização talvez não dure muito. Os diferentes estados também podem ter regras diferentes para o que é legal (mudar de "sonolento" para "brincalhão" pode ser ilegal, mas os gatos parecem não se importar com isso). Eventos diferentes podem acionar a alteração do estado.
Dê uma olhada ao pesquisar na Web por FSM e AI e você pode ver como ele funciona. Pode parecer complicado ao explicar, mas é realmente simples.
fonte
Você pode usar a marcação:
Pode haver marcas de movimento como "deitado", "sentado", "em pé", "andando" e "correndo". Em seguida, você pode eliminar combinações irreais de tags, por exemplo, "postura" -> "execução" (deve haver "posição de pé" no meio).
Outras tags podem descrever atividades: "dormir", "comer", "caçar" etc. Mais uma vez, "dormir" -> "caçar" é impossível sem estados intermediários.
Como animações como "em pé" são transitórias, pode ser uma boa ideia ter tags separadas para o início e o final de cada animação. Por exemplo, "levantar-se" pode ser uma transição de "sentado" para "ficar" etc.
Portanto, para cada animação, você pode ter algumas tags:
Com esses, você pode filtrar apenas as combinações possíveis, definindo restrições como "
A->B
só é possível sefinal_movement_tag(A) == initial_movement_tag(B)
", o que resultará em um número muito menor. Com essas combinações possíveis, você pode fazer o que descreveu - adicionar probabilidades. A adição de probabilidades pode ser baseada em tags de atividade, pois permanecer em uma mesma atividade é mais provável do que alterar atividades.Portanto, com as tags, é possível automatizar a criação de todas as transições na sua árvore FSM / comportamento e ajustá-las mais tarde, se você não estiver satisfeito com algumas combinações.
fonte
Se você deseja manter as ricas possibilidades das árvores de comportamento, pode adicionar um novo tipo de nó seletor composto: o nó seletor Markov.
Você precisaria implementar o nó do seletor Markov. Ele selecionará um de seus nós filhos aleatoriamente, dependendo do nó (filho) que teve sucesso (ou falhou) anteriormente.
fonte