Puppo, O Corgi: Excesso de fofura com o Unity ML-Agents Toolkit

Construir um jogo é um processo criativo que envolve muitos passos desafiadores, incluindo definir o conceito e a lógica do jogo, construir ativos e animações, especificar comportamentos de NPCs, ajustar dificuldade e equilíbrio e, finalmente, testar o jogo com jogadores reais antes do lançamento. Acreditamos que o aprendizado de máquina pode ser usado em todo o processo criativo e no post do blog de hoje, vamos nos concentrar em um desses desafios: especificar o comportamento de um NPC.
Tradicionalmente, o comportamento de um NPC é codificado de forma rígida usando scripts e árvores de comportamento. Essas listas de regras (geralmente longas) processam informações sobre o ambiente do NPC (chamadas de observações) para ditar sua próxima ação. Essas regras podem ser demoradas para escrever e manter à medida que o jogo evolui. O aprendizado por reforço fornece uma estrutura alternativa promissora para definir o comportamento de um NPC. Mais especificamente, em vez de definir o mapeamento de observação para ação manualmente, você pode simplesmente treinar seu NPC fornecendo recompensas quando ele atinge o objetivo desejado.
Treinar um NPC usando aprendizado por reforço é bastante semelhante a como treinamos um filhote para buscar. Apresentamos ao filhote um petisco e então jogamos o graveto. No início, o filhote vagueia sem saber o que fazer, até que eventualmente pega o graveto e o traz de volta, recebendo imediatamente um petisco. Após algumas sessões, o filhote aprende que recuperar um graveto é a melhor maneira de ganhar um petisco e continua a fazê-lo.
É exatamente assim que o aprendizado por reforço funciona no treinamento do comportamento de um NPC. Fornecemos ao nosso NPC uma recompensa sempre que ele completa uma tarefa corretamente. Através de múltimas simulações do jogo (o equivalente a muitas sessões de busca), o NPC constrói um modelo interno de qual ação precisa realizar em cada momento para maximizar sua recompensa, resultando no comportamento ideal e desejado. Assim, em vez de criar e manter ações de baixo nível para cada observação do NPC, só precisamos fornecer uma recompensa de alto nível quando uma tarefa é concluída corretamente e o NPC aprende o comportamento de baixo nível apropriado.
Para mostrar a eficácia dessa técnica, construímos um jogo de demonstração, “Puppo (lido como ‘Pup-o’), O Corgi”, e o apresentamos em Unite Berlin. É um jogo móvel onde você busca com um adorável corgi. Jogue um graveto para Puppo deslizando na tela e Puppo o traz de volta. Enquanto a lógica do jogo de nível superior usa script tradicional, o corgi aprende a andar, correr, pular e buscar o graveto usando aprendizado por reforço. Em vez de usar animação ou comportamentos scriptados, os movimentos do corgi são treinados exclusivamente com aprendizado por reforço. Não só parece super fofo, mas o movimento do corgi é impulsionado exclusivamente pelo motor de física. Isso significa, por exemplo, que o movimento do corgi pode ser afetado por RigidBodies ao redor.
Puppo se tornou tão popular no Unite Berlin que muitos desenvolvedores nos perguntaram como o fizemos. É por isso que decidimos escrever este post no blog e liberar o projeto para que você possa experimentá-lo por conta própria.
Para começar, vamos cobrir os requisitos e o trabalho preliminar que você precisa fazer para treinar o corgi. Então, compartilharemos nossa experiência em treiná-lo. Finalmente, vamos revisar os passos que tomamos para criar um jogo com Puppo como seu herói.
Antes de entrarmos nos detalhes, vamos definir algumas noções importantes em aprendizado por reforço. O objetivo do aprendizado por reforço é aprender uma política para um agente. Um agente é uma entidade que interage com seu ambiente: A cada passo de aprendizado, o agente coleta observações sobre o estado do ambiente, realiza uma ação e recebe uma recompensa por essa ação. A política define como um agente age com base nas observações que percebe. Podemos desenvolver uma política recompensando o agente quando seu comportamento é apropriado.
No nosso caso, o ambiente é a cena do jogo e o agente é Puppo. Puppo precisa aprender uma política para que possa brincar de buscar conosco. Semelhante a como treinamos um cachorro de verdade com petiscos para buscar gravetos, podemos treinar Puppo recompensando-o adequadamente.
Usamos um ragdoll para criar Puppo e suas pernas são movidas por motores de junta. Portanto, para que Puppo aprenda a chegar ao alvo, ele deve primeiro aprender a girar os motores das articulações para que possa se mover.
Um cachorro de verdade usa a visão e outros sentidos para se orientar e decidir para onde ir. Puppo segue a mesma metodologia. Ele coleta observações sobre a cena, como a proximidade do alvo, a posição relativa entre ele e o alvo e a orientação de suas próprias pernas, para que possa decidir qual ação tomar a seguir. No caso de Puppo, a ação descreve como girar os motores das articulações para se mover.
Após cada ação que Puppo realiza, damos uma recompensa ao agente. A recompensa é composta por:
- Bônus de Orientação: Recompensamos Puppo quando ele está se movendo em direção ao alvo. Para fazer isso, usamos o método Vector3.Dot().
- Penalidade de Tempo: Damos uma penalidade fixa (recompensa negativa) a Puppo a cada ação. Dessa forma, Puppo aprenderá a pegar o bastão o mais rápido possível para evitar uma pesada penalidade de tempo.
- Penalidade de Rotação: Penalizamos Puppo por tentar girar demais. Um cachorro de verdade ficaria tonto se girasse demais. Para parecer real, penalizamos Puppo quando ele gira muito rápido.
- Recompensa por Chegar ao Alvo: Mais importante, recompensamos Puppo por chegar ao alvo.


Agora o Puppo está pronto para aprender. Levou-nos duas horas em um laptop para o cachorro aprender a correr em direção ao alvo de forma eficiente. Durante o processo de treinamento, notamos um comportamento interessante. O cachorro aprendeu a andar rapidamente em cerca de 1 min. Então, à medida que o treinamento continuava, o cachorro aprendeu a correr. Logo depois, ele começou a se virar quando tentava fazer uma curva repentina enquanto corria. Felizmente, o cachorro aprendeu a se levantar como um cachorro de verdade faria. Esse comportamento desajeitado é tão fofo que você poderia parar o treinamento neste ponto e usá-lo diretamente no jogo.
Se você estiver interessado em treinar o Puppo você mesmo, pode seguir a instrução no projeto. Inclui etapas detalhadas sobre como configurar o treinamento e quais parâmetros você deve escolher. Para um tutorial mais detalhado sobre como treinar agentes, visite o site de documentação do ML-Agents.
Para criar o jogo “Puppo, O Corgi”, precisamos definir a lógica do jogo que permite que um jogador interaja com o modelo treinado. Como o Puppo aprendeu a correr em direção a um alvo, precisamos implementar a lógica que muda o alvo para o Puppo dentro do jogo.
No modo de jogo, definimos o alvo como o bastão logo após o jogador tê-lo lançado. Quando o Puppo chega ao bastão, mudamos o alvo do Puppo para a posição do jogador na cena para que o Puppo devolva o bastão ao jogador. Fazemos isso porque é muito mais fácil treinar o Puppo para se mover em direção a um alvo enquanto definimos a lógica do fluxo do jogo com um script. Acreditamos que Aprendizado de Máquina e métodos tradicionais de desenvolvimento de jogos podem ser combinados para obter o melhor de ambas as abordagens. O projeto “Puppo, O Corgi” inclui um modelo pré-treinado para o corgi que você pode usar imediatamente e até implantar em dispositivos móveis.
Esperamos que este post no blog tenha esclarecido o que é possível alcançar com o ML-Agents Toolkit para desenvolvimento de jogos.
Quer se aprofundar no código deste projeto? Lançamos o projeto e você pode baixá-lo aqui. Para saber mais sobre como usar o ML-Agents Toolkit, você pode encontrar nossa documentação oficial e um guia para iniciantes passo a passo aqui. Se você estiver interessado em entender melhor a matemática, os algoritmos e as teorias por trás do aprendizado por reforço, há um Nanodegree em Aprendizado por Reforço que oferecemos em parceria com a Udacity.
Adoraríamos ouvir sobre sua experiência usando o ML-Agents Toolkit para seus jogos. Sinta-se à vontade para entrar em contato conosco em nossa página de problemas do GitHub ou nos enviar um e-mail diretamente.
Feliz criação!
