Así que me encontré con un problema en el juego en el que estoy trabajando, pero parece ser algo bastante fundamental que probablemente surja en muchos juegos.
Mi juego requiere que alguna función de juego ocurra en un momento muy específico durante la animación de un personaje. Y así, como dice el título, me pregunto cuáles son algunas buenas técnicas y estrategias fundamentales para sincronizar eventos / funciones / acciones relacionadas con el juego con puntos específicos en la animación de un personaje.
Aquí hay algunos ejemplos simples de lo que estoy hablando en varios tipos de juegos:
Tu personaje recarga su arma en un tirador . Tu personaje reproduce su animación de 'recarga', pero es importante que la función que establece la variable CurrentAmmo solo se invoque en el momento exacto después de que se cambia el cargador y se arma el arma. Esto podría ser algún punto en el medio de la animación de recarga.
En un juego de rol por turnos, tus personajes se paran en una línea frente a una línea de enemigos. Cuando se le ordena atacar, uno de tus personajes corre / salta hacia uno de los enemigos y corta su espada gigante antes de correr / saltar de regreso a su lugar de pie. Debes asegurarte de que el enemigo esté dañado en el momento exacto en que se reproduce la animación de corte , en algún punto entre correr y retroceder.
En un juego de sigilo , tu personaje puede acercarse sigilosamente e interactuar con computadoras y botones del mundo. Tal vez hay un botón que apaga la fuente de alimentación de las luces del puesto avanzado en el que se está infiltrando. Cuando se presiona el botón de acción, tu personaje se extiende y presiona el botón y luego vuelve a su posición inactiva. Desea que las luces se apaguen en el punto exacto de la animación 'push_button' cuando se presiona el botón.
Es cierto que mi caso particular es muy parecido al segundo ejemplo , en el que he creado una animación en la que mi personaje por turnos se lanza hacia adelante durante un ataque y quiero que el daño se aplique en el momento exacto en que la animación parece estar en contacto. . Debido a que mi juego usa un sistema por turnos (imagina algo como Final Fantasy o Fire Emblem) quiero el daño / curación / magia / etc. para aplicar en el momento correcto durante la animación de cada personaje, aunque en realidad no estoy usando colisión / hitboxes.
Debo mencionar que estoy haciendo mi juego en un motor de juego popular, y que en este momento estoy manejando esto usando sus eventos de animación o notificaciones para lograr algo cercano a los resultados deseados: mi personaje ejecuta un cierto comando y activa un La animación específica del comando (es decir: 'ataque_comando') y los activos de animación para cada uno de mis comandos deben incluir un evento de animación / notificación de 'devolución de llamada' en la función ExecuteCommand de mis caracteres. En otras palabras, el personaje le dice a la animación de ataque que se reproduzca, y luego la animación de ataque emite un evento / notifica una devolución de llamada al personaje en el momento exacto durante la animación cuando se debe infligir el daño.
Honestamente, esto funciona por ahora, pero se siente mal , ¡como si me faltara una parte de la imagen más grande aquí! Parte de la razón por la que este método se siente mal es que combina la lógica del juego con los activos de animación; si mi activo de animación se olvida de incluir un evento / devolución de llamada ExecuteCommand (), el comando no se ejecutará correctamente y se necesita un código adicional para verificar si una animación de comando finalizó sin ejecutar el comando. Es desordenado y significa que mi juego tiene una dependencia extraña de sus activos. Por supuesto, quiero que el daño ocurra en un punto específico durante mi animación de ataque, pero me siento realmente extraño al llamar al código de juego dentro de los activos de animación.
Entonces, ¿qué estoy pasando por alto aquí? ¿Cuáles son algunas buenas técnicas generales para manejar este tipo de situaciones en las que quieres que ocurran ciertas acciones de juego importantes en momentos específicos durante las animaciones?
Editar: para aclarar, esta no es una pregunta específica del motor ni estoy buscando diseños / técnicas específicas del motor. Estoy interesado en las técnicas generales de sincronización de animación / juego que uno podría usar en sus proyectos de juego, independientemente de las tecnologías utilizadas.
fuente
Respuestas:
Para la sincronización, debe decidir quién (su código, animaciones o ninguna de las dos) es la autoridad de sincronización: el "ritmo" al que todos los demás "bailan".
Diferentes arreglos se adaptan a diferentes juegos:
Las animaciones son la autoridad de sincronización (su configuración actual)
El código del juego puede activar animaciones. Cuando las animaciones alcanzan ciertos puntos, provocan eventos (por ejemplo, recarga realizada) a los que puede reaccionar el código del juego (por ejemplo, restablecer la munición disponible).
Si la sincronización precisa de las animaciones (independientemente del estado del juego) es una parte importante de su juego, o si desea específicamente que sus animadores controlen la sincronización, considere este enfoque.
Las herramientas de animación Blender (3D) y Spine (2D) permiten al animador definir eventos a los que se puede suscribir el código del juego.
El código es la autoridad de tiempo
Inverso de lo anterior: los eventos que suceden en el mundo del juego (por ejemplo, el jugador que elige recargar su arma) hacen que se ejecuten animaciones y se pasen parámetros (por ejemplo, el tiempo hasta que se complete la recarga). Cada animación utiliza los parámetros suministrados para modificar su aspecto (por ejemplo, ejecutar la animación a una velocidad adecuada de modo que la "parte recargada" ocurra cuando se especifique).
Las animaciones también pueden estar escuchando los eventos del juego (por ejemplo, el jugador cancela la recarga o el jugador se agacha mientras se recarga) y modifica su aspecto en consecuencia.
Si sus animaciones pueden permitirse ser flexibles con respecto al tiempo, su juego depende en gran medida del contenido generado por procedimientos, o si desea específicamente que sus programadores controlen el tiempo, considere este enfoque.
Las animaciones de los personajes de Overgrowth se estructuran en gran medida de esta manera: David Rosen lo explica en su charla GDC 14 (ver específicamente lossegmentos Movimiento y Movimiento Continuado ).
Tiempo implícito (autoridad externa)
En juegos de ritmo u otras situaciones donde el tiempo se controla desde una fuente externa (en juegos de ritmo, el ritmo de la pista de música), puede tener sentido modelar cosas como tales. El código del juego y las animaciones pueden leer una marca de tiempo global y un estado del juego, y luego comportarse en consecuencia sin comunicarse.
Si el estado del juego y las animaciones dependen en gran medida de una autoridad de sincronización externa, considere este enfoque.
Por supuesto, es posible que desee utilizar diferentes enfoques para diferentes sistemas en su juego. (Por ejemplo, los juegos de ritmo con frecuencia usan el ritmo de la canción como una autoridad externa, pero las animaciones aún escuchan los eventos de interacción del jugador para cancelar o cambiar el aspecto de las notas retenidas).
fuente
He leído en alguna parte que casi todos los problemas de computación pueden resolverse con una capa de abstracción adicional, y no veo que su caso sea diferente.
Para este requisito, generalmente veo una capa para controlar el estado del personaje. De esta manera, el personaje tendrá una Animación actual y un Estado actual. Cada uno con su propia responsabilidad.
La animación es responsable solo de lo visual, y el estado maneja la lógica específica del juego para esa acción.
En mi juego de lucha, el estado es un objeto que hereda de la clase BaseState y tiene un método Update (). Cada personaje tiene una colección de estados, pero solo se puede asignar uno a la vez. Y el método Update () del estado actual se llama una vez por cuadro.
Está dentro de la Actualización () del estado donde hago toda esa lógica: establecer la velocidad del personaje en un marco específico, aumentar / disminuir la salud, etc.
fuente