Então, me deparei com um problema no jogo em que estou trabalhando, mas parece ser uma coisa bastante fundamental que provavelmente aparece em muitos jogos.
Meu jogo exige que alguma função de jogabilidade ocorra em um momento muito específico durante uma animação de personagem. E assim, como diz o título, estou me perguntando quais são algumas boas técnicas e estratégias fundamentais para sincronizar eventos / funções / ações relacionadas à jogabilidade em pontos específicos da animação de um personagem.
Aqui estão alguns exemplos simples do que estou falando em vários tipos de jogos:
Seu personagem recarrega sua arma em um atirador . Seu personagem reproduz sua animação de 'recarga', mas é importante que a função que define a variável currentAmmo seja chamada apenas no momento exato após a troca da revista e a arma estar armada. Isso pode ser um ponto no meio da animação de recarga.
Em um RPG baseado em turnos, seus personagens ficam em uma linha de frente para uma linha de inimigos. Quando ordenado a atacar, um de seus personagens corre / pula para um dos inimigos e corta sua espada gigante antes de correr / pulando de volta ao seu lugar de pé. Você quer ter certeza de que o inimigo está danificado no momento exato em que a animação cortante é reproduzida - algum ponto entre subir e voltar.
Em um jogo furtivo , seu personagem pode se infiltrar e interagir com computadores e botões do mundo. Talvez haja um botão que apague a fonte de alimentação das luzes do posto avançado que você está se infiltrando. Quando o botão de ação é pressionado, seu personagem estende a mão e aperta o botão e, em seguida, retorna à posição inativa. Você deseja que as luzes se apaguem no ponto exato da animação 'push_button' quando o botão é pressionado.
É certo que meu caso particular é mais parecido com o segundo exemplo , no qual criei uma animação em que meu personagem baseado em turnos avança durante um ataque e quero que o dano seja aplicado no momento exato em que a animação parece estar fazendo contato . Porque meu jogo usando um sistema baseado em turnos (imagine algo como Final Fantasy ou Fire Emblem) eu quero o dano / cura / magia / etc. para ser aplicado no momento correto durante cada animação de personagem, mesmo que eu não esteja usando colisões / hitboxes.
Devo mencionar que estou criando meu jogo em um mecanismo de jogo popular, e que agora estou lidando com isso usando seus eventos de animação ou notificações para alcançar algo próximo aos resultados desejados - meu personagem executa um determinado comando e aciona um a animação específica do comando (ou seja: 'attack_command') e os recursos de animação de cada um dos meus comandos devem incluir um evento de animação / notificar 'callback' na função ExecuteCommand dos meus caracteres. Em outras palavras - o personagem diz à animação de ataque para executar e, em seguida, a animação de ataque emite um evento / notifica o retorno de chamada no personagem no momento exato da animação em que o dano deve ser causado.
Honestamente, isso funciona por enquanto, mas parece errado - como se eu estivesse perdendo parte de uma imagem maior aqui! Parte da razão pela qual esse método parece errado é que ele associa a lógica do jogo aos recursos de animação; se meu recurso de animação esquecer de incluir um evento / retorno de chamada ExecuteCommand (), o comando não será executado corretamente e será necessário um código extra para verificar se uma animação de comando foi concluída sem executar o comando. É uma bagunça e significa que minha jogabilidade tem uma estranha dependência de seus ativos. É claro que quero que o dano ocorra em um ponto específico durante minha animação de ataque, mas me sinto muito estranho ao chamar o código de jogo dentro dos recursos de animação.
Então, o que eu estou negligenciando aqui? Quais são algumas boas técnicas gerais para lidar com esses tipos de situações nas quais você deseja que certas ações importantes de jogabilidade ocorram em horários específicos durante as animações?
Editar: para esclarecer, esta não é uma pergunta específica de mecanismo nem estou procurando projetos / técnicas específicos de mecanismo. Estou interessado em técnicas gerais de sincronização de animação / jogabilidade que podem ser usadas em seus projetos de jogos, independentemente das tecnologias usadas.
fonte
Respostas:
Para a sincronização, você precisa decidir quem (seu código, animações ou nenhuma) é a autoridade de temporização - a "batida" em que todos os outros "dançam".
Arranjos diferentes combinam com jogos diferentes:
As animações são a autoridade de temporização (sua configuração atual)
O código do jogo pode acionar animações. Quando as animações atingem determinados pontos, elas geram eventos (por exemplo, recarregamentos concluídos) aos quais o código do jogo pode reagir (por exemplo, redefinir a munição disponível).
Se o tempo exato das animações (independentemente do estado do jogo) for uma parte importante do seu jogo, ou você desejar especificamente que seus animadores controlem o tempo, considere esta abordagem.
Ferramentas de animação O Blender (3D) e o Spine (2D) permitem que o animador defina eventos nos quais o código do jogo pode se inscrever.
Código é a autoridade de temporização
Inverso do que foi dito acima: Eventos que acontecem no mundo do jogo (por exemplo, o jogador que escolhe recarregar sua arma) fazem com que as animações sejam executadas e passadas pelos parâmetros (por exemplo, o tempo até a recarga ser concluída). Cada animação usa os parâmetros fornecidos para modificar sua aparência (por exemplo, executando a animação a uma velocidade apropriada, de modo que a "parte recarregada" ocorra quando especificada).
As animações também podem estar ouvindo eventos do jogo (por exemplo, o jogador cancela a recarga ou agacha-se ao recarregar) e modifica sua aparência de acordo.
Se suas animações podem se dar ao luxo de ser flexíveis quanto ao tempo, seu jogo depende muito de conteúdo gerado processualmente ou se você deseja especificamente que seus programadores controlem o tempo, considere esta abordagem.
Supercrescimento animações de personagens 's são em grande parte estruturado da seguinte forma: David Rosen explica em seu GDC 14 talk (ver especificamente as Movimento e movimento continuou segmentos).
Tempo implícito (autoridade externa)
Em jogos de ritmo ou outras situações em que o tempo é controlado a partir de uma fonte externa (em jogos de ritmo, a batida da faixa de música), pode fazer sentido modelar as coisas como tais. O código e as animações do jogo podem ler um registro de data e hora global e o estado do jogo, e se comportar de acordo, sem se comunicar.
Se o estado do seu jogo e as animações dependem amplamente de uma autoridade de tempo externa, considere esta abordagem.
É claro que você pode querer usar abordagens diferentes para sistemas diferentes no seu jogo. (Por exemplo, jogos de ritmo freqüentemente usam a batida da música como uma autoridade externa, mas as animações ainda ouvem os eventos de interação do jogador para cancelar ou alterar a aparência das notas mantidas.)
fonte
Li em algum lugar que quase todos os problemas de computação podem ser resolvidos com uma camada de abstração adicional, e não vejo seu caso diferente.
Para esse requisito, geralmente vejo uma camada para controlar o estado do personagem. Desta forma, o personagem terá uma animação atual e um estado atual. Cada um com sua própria responsabilidade.
A animação é responsável apenas pelo visual, e o estado lida com a lógica específica do jogo para essa ação.
No meu jogo de luta, o estado é um objeto que herda da classe BaseState e possui um método Update (). Cada personagem tem uma coleção de estados, mas apenas um pode ser atribuído por vez. E o método Update () do estado atual é chamado uma vez por quadro.
É dentro do Update () do estado em que eu faço toda essa lógica: defina a velocidade do caractere em um quadro específico, aumente / diminua a saúde, etc.
fonte