Transcripciones
1. Introduccion: combate y los videojuegos pueden parecer desalentadores y una
característica difícil de implementar Este curso te
proporcionará todas las herramientas y
conocimientos que
necesitarás para crear un sistema de combate escalable y dinámico en Gado. Descompondremos el sistema de
combate en mecánicas
individuales
y las combinaremos para crear un sistema robusto de combate de
acción que se puede personalizar
para satisfacer tus necesidades. Aprenderás a combinar animaciones de
combate y movimiento. Sincronice cajas de golpes
con animaciones de ataque, implemente marcos oculares
en animaciones de esquivar, Bloquear a los enemigos Dispara proyectiles desde un arma
arreglada y controla a los enemigos
con guiones de IA Si necesitas ayuda, nuestro servidor de
discordia está lleno de otros estudiantes y desarrolladores de
juegos que pueden responder cualquier
duda que puedas tener Haz clic en el enlace del sitio web
en mi perfil para unirte. Voy a estar usando un proyecto de inicio
hecho en God versión 4.3 que está disponible en mi GitHub usando activos gratuitos
de él punto IO. Pero puedes seguir junto con tu propio proyecto usando
diferentes activos. Para aprovechar al máximo
este curso, necesitarás una escena
en tu proyecto con un personaje que el jugador pueda controlar y al menos un enemigo. También es posible que desee tener un sistema de
inventario y equipo capaz de equipar a los personajes con un arma y un escudo Para más información
sobre estos temas, consulta mi curso anterior. El combate no tiene que
ser una batalla cuesta arriba. Dibujemos nuestras armas y rompamos a través del combate juntos.
2. Configuración: Hola, amigos. Antes de que
empecemos, deberías tener un proyecto con un personaje jugador que pueda moverse en un entorno, y algunos enemigos
para que peleen. También es posible que desee
tener un menú de inventario capaz de equipar artículos, incluyendo al menos
un arma mala, un arma arreglada y un escudo A lo largo de este curso,
agregaremos controles, mecánicas y animaciones a nuestro proyecto
para bloquear un objetivo, atacar, esquivar, bloquear
y disparar proyectiles
3. Lock On: Para nuestra primera lección, permitiremos que el jugador
se bloquee en un enemigo. Comencemos agregando un mapeo de entrada para
alternar el candado Abrir la configuración del proyecto, cambiar a la pestaña de mapa de entrada. Podemos agregar un
evento de entrada llamado Toggle Lock. Desplazándose hacia abajo para encontrar
el nuevo evento de entrada, uniré la tecla Q en el teclado y el botón
derecho del stick en mi controlador a este evento En el guión de
manejo de entrada del jugador, necesitaremos referencias
al personaje, el brazo de
resorte y la cámara, todo listo usando add on ready. Durante la función de entrada, después de verificar la pausa, abrir o cerrar
el menú de inventario, y si el
control del jugador ha sido desactivado. He dividido el resto
de la entrada en cámara y controles de
personajes para una mejor organización. Actualmente, el único control de la
cámara es girar el brazo de resorte que sujeta la cámara
usando el mouse. Comprobemos también si se presionó el botón de
bloqueo de palanca. Esta será una entrada
sensible al contexto con múltiples funciones
posibles diferentes. Tendremos que saber si el jugador está actualmente bloqueado
en un objetivo. Entonces, declaremos una
variable para mantener el
objetivo actualmente bloqueado como un nodo tres D, por lo que cualquier objeto tres D en nuestro mundo de juego podría
potencialmente bloquearse en. Primero podemos dividir
las funciones
del botón de bloqueo de palanca en
dos categorías posibles, si el valor de target
es nulo o no, que podemos acortar
a solo si target Empecemos en el bloque s donde el jugador no está actualmente
bloqueado a nada. Aquí, tendremos que
asignar el valor del objetivo para que sea el objetivo
más visible, y podemos delegar la
responsabilidad de
averiguar cuál es el objetivo
visible más cercano a la cámara En el caso de que
no haya un objetivo visible más cercano, el objetivo seguirá siendo nulo. En muchos juegos de acción y aventuras, al presionar el
botón de bloqueo de go, pero no hay nada en
lo que bloquear. Luego, la cámara se restablece para estar
detrás del personaje del jugador, que será una función
del brazo de resorte Si el jugador
ya está bloqueado en un objetivo y presiona
el botón de bloqueo de Togo, también
hay varios casos
a considerar. Si hay múltiples objetivos
visibles, el jugador se bloqueará en el siguiente objetivo
visible más cercano, además del que está
actualmente bloqueado. Podemos reutilizar
la misma función de la cámara para encontrar
el objetivo más cercano Pero esta vez también proporcionamos el objetivo actual
como argumento, y vamos a escribir el algoritmo
para ignorar este objetivo. En el caso de abajo, aún
podemos pasar el objetivo actual ya que
su valor es nulo, por lo que
no tendremos nada que ignorar. Si no hay múltiples objetivos
visibles, esta función también devolverá null y el bloqueo se
desactivará Independientemente de si
hay o no múltiples objetivos, si el jugador
también está presionando hacia abajo, mayoría de los juegos desconectarán el
bloqueo en ese caso. Podemos determinar si la
dirección de entrada que se da es similar a abajo usando un
producto de punto de los dos vectores, y comprobando si
es mayor que 0.75. Esto cubrirá cualquier
dirección cercana a abajo, pero no llegando
hasta las diagonales Queremos tener la
capacidad de alternar el bloqueo desde fuera
del script, por lo que sería una buena idea
convertirlo en una función pública. Vamos a llamarlo toggle
lock y darle un parámetro opcional para forzar bloqueo con un valor
predeterminado false. El valor de target se
establecerá null si está siendo forzado a salir. De lo contrario, se puede ajustar
al objetivo visible más cercano
según lo determine la cámara, ignorando el
objetivo actual si hay uno Los tres de estos
casos anteriores ahora pueden llamar a Toggle lock
con solo la necesidad especificar que el bloqueo
se está forzando en el caso de que también se le dé la
dirección de entrada hacia abajo, y otros scripts también pueden forzar al jugador a que se encienda
o apague por cualquier motivo. Cambiar a la secuencia de comandos del brazo de
resorte. Supongamos que el jugador presiona el botón de bloqueo de palanca, pero no hay objetivos visibles. Queremos que el
brazo de resorte coloque la cámara detrás del personaje. Entonces necesitaremos una referencia al personaje
al que está unido el
brazo de resorte, que en mi caso siempre
va a ser el nodo padre
del brazo de resorte. Si está utilizando una estructura de nodos
diferente, es posible que desee
exportar esta variable en su lugar y establecer su valor
en el panel del inspector. Para rotar la cámara detrás del personaje
gradualmente con el tiempo, usaremos una
variable de premezcla de tipo tween Sería una buena
idea exportar una variable por la
duración de la preadolescentes Voy a usar un cuarto
de segundo. También podríamos querer un valor para la rotación x preferida
para restablecer la rotación de los
brazos del resorte dos. Usaré 0.5 radianes negativos, posicionando la cámara
ligeramente por encima del personaje, mirando hacia adelante y
ligeramente hacia abajo en ángulo También declaremos
una variable para mantener la rotación del objetivo de los tweens
como un vector tres e inicializarlo para que
sea un vector tres con la
rotación de reset x como su valor x, pero cero para las rotaciones
y y z Dando
una definición a la función, también
podemos aceptar un
parámetro opcional para la duración de la preadolescentes usando esto como su valor predeterminado para
que pueda ser sobrescrito Para rotar la cámara
detrás del personaje, podemos llamar a una nueva función
privada para interponer la rotación de los
brazos de resorte Especificando que queremos que
la rotación y sea la rotación de plataformas de caracteres más una media rotación
representada como radianes Pi A continuación, escribamos
la función privada que preteje la rotación de los brazos de
resorte, aceptando una
rotación objetivo y como flotante, así
como una duración
para la premezcla con
un valor predeterminado de la duración
exportada Comenzaremos estableciendo
la propiedad y de la rotación objetivo
para que sea la rotación objetivo y aceptada
como parámetro. Pero para asegurar que
la rotación siempre tome el camino más corto
alrededor del personaje, debemos envolver su
valor para
estar siempre entre el punto de
rotación actual y menos una media rotación y el punto de rotación actual
y más una media rotación. Si una preadolescente ya
existe y se está ejecutando, entonces deberíamos matarla
antes de crear una nueva Luego podemos interponer la rotación de los brazos del
resorte
a la rotación del objetivo a
lo largo de la duración A continuación, dejemos que la cámara
detecte objetivos visibles. Mi cámara aún no tiene ningún comportamiento
con guión, así que agreguemos un nuevo guión y lo
pongamos en la carpeta de
scripts de reproductores Necesitaremos una función
pública para obtener el objetivo visible más cercano, aceptando un
parámetro opcional
del objetivo actual con
un valor predeterminado de null, por lo que potencialmente podemos ignorarlo. Esto devolverá un nodo tres D, y el caso predeterminado
será devolver nulo si no pudimos
encontrar un objetivo visible. Para determinar cuál de los
objetivos visibles es el más cercano, necesitaremos mantener una lista de todos los objetivos visibles. Declaremos otra
variable para contener todos los objetivos visibles como
una matriz de nodos tres Ds. Inicializado para estar vacío. Una manera fácil de saber
qué objetivos son visibles es adjuntar un nodo
D de área tres a la cámara. Vamos a llamarlo rango objetivo. Esta zona estará monitoreando cualquier cosa en la capa de
colisión 11, que he elegido para
representar a los enemigos. Asegúrate de que tus enemigos tengan
su capa de colisión establecida la misma capa que está siendo enmascarada por el bloqueo al apuntar También necesitaré
restablecer las áreas transformadas para posicionarla
en el origen de la cámara. El nodo D del área tres
necesita una forma de colisión, y podemos poblar el recurso de forma
con un polígono convexo Usando un polígono convexo, podemos definir la
forma como una pirámide, que copia exactamente el campo de visión de la
cámara, pero con un rango limitado Dado que el
campo de visión de la cámara, tomará la forma de
una pirámide de cuatro lados, podemos definirla con
cinco puntos siendo
el primer punto el
mismo que la posición de las cámaras. Los otros cuatro se
posicionarán a lo largo del eje Z, la distancia máxima
de nuestro rango de bloqueo. Utilizaré una
distancia máxima de 15 metros. Cambiando a la vista ortogonal superior y ocultando el
entorno por un momento, simplemente
ajustaré rápidamente las posiciones de cada punto de la pirámide para que coincidan
aproximadamente con el campo de visión de
las cámaras, 11.4 metros a la
izquierda y a la derecha Asimismo, en vista
ortogonal izquierda, ajustando los valores y de
los puntos de la pirámide, 6.4 metros arriba y abajo. Hasta que tengamos forma de pirámide, coincidiendo con el
campo de visión de las cámaras, que alcanza los 15 metros. Luego volveré
a la vista en perspectiva y hablaré
de la visibilidad del entorno nuevamente. Cada vez que un cuerpo ingresa a esta área, conectando la
señal ingresada al cuerpo al guión de la cámara, podemos anexar el cuerpo a nuestra
matriz de objetivos visibles Asimismo, cada vez que un
cuerpo sale de esta área, el cuerpo puede ser borrado
de la matriz Cualquier
cuerpo de colisión de tres D en la capa 11, que exista dentro de esta área ahora se considerará
un objetivo visible. En mi script de spring arm, necesitaré cualquier etiqueta para usar
la función get parent. Ejecutando el juego y cambiando
al árbol de escenas remoto, podemos seleccionar la cámara y ver sus propiedades
en el inspector, incluyendo la matriz
de objetivos visibles. A medida que la cámara se
mueve por la escena, la matriz de objetivos visibles se
actualiza automáticamente para agregar y eliminar a cada enemigo a medida que entran o salen
del campo de visión. Al presionar el botón de bloqueo de palanca en realidad
no
apuntará a nada todavía, pero podemos ver cómo
reposiciona la cámara detrás del personaje Antes de permitir el
bloqueo a un objetivo, posible que también
queramos verificar
si la línea de
visión del jugador hacia el objetivo está
obstruida por el terreno También agreguemos un nodo de tres D de rayos emitidos a
la cámara,
y asígnele el nombre de línea de visión. Después agarra una referencia a
ella en el guión de la cámara. Para encontrar el
objetivo visible más cercano con nuestra cámara, si la matriz está vacía, su tamaño es cero, entonces no hay objetivos
visibles a considerar, y
deberíamos simplemente regresar. Si hay
objetivos visibles a considerar, tendremos que comparar
las distancias de cada uno con la cámara para encontrar
cuál es la más cercana. Para ello, necesitaremos
una variable para mantener la distancia desde
el objetivo actual a la cámara como a flote La distancia más cercana como a flote, y el índice del objetivo
visible más cercano como un entero Estableceremos la distancia
más cercana a infinita usando la palabra clave I NF, y el
índice más cercano a negativo
para significar que no es un índice válido Si después de iterar a través de toda
la matriz de objetivos
visibles, el índice más cercano
sigue siendo negativo, entonces ningún objetivo visible se
consideró válido, y deberíamos devolver null De lo contrario, podemos devolver el objetivo visible en
el índice más cercano. Si el objetivo visible en el índice
I es el objetivo actual, podemos saltarlo con
la declaración continuada. Para cualquier otro objetivo visible, necesitaremos calcular su
distancia con respecto a la cámara. Podemos usar la distancia al cuadrado ya que es matemáticamente
más eficiente Si la distancia actual es menor que la distancia
más cercana, entonces tendremos que
verificar si la línea de visión hacia este
objetivo está obstruida Primero, tendremos que restablecer cualquier rotación que tenga actualmente la línea
de visión. Luego establece la posición objetivo
del rayo proyectado a la posición
global del objetivo menos
la posición global de la cámara y
obligarla a actualizarla. Pero la posición de los personajes
suele estar en el suelo, que es fácilmente obstruido
por pequeños trozos de terreno y no siempre es un buen
indicador de línea de visión Vamos a sumar también 1 metro arriba. Si la línea de visión
choca con algo y ese algo
es el objetivo visible,
entonces la línea de visión
no está obstruida por nada, lo que convierte a este objetivo en
el objetivo visible más cercano que
hemos encontrado hasta ahora Podemos establecer la distancia más cercana
a la distancia actual
y el índice más nerest a I antes de pasar por
el resto de la matriz Esto ahora devolverá nulo
o el
objetivo visible más cercano a la cámara La línea de visión también
estará colisionando con la capa 11, buscando enemigos, pero también capa uno para ser
obstruida por También sería bueno
hacerle saber al jugador en
qué está encerrado con
el indicador de objetivo. Agreguemos un nodo Sprite three
D como hijo del controlador de entrada
del reproductor y
renombrémosle el indicador de destino Para la textura, usaré el puntero en blanco de la barra de
desplazamiento. Pero cambia su
configuración de entrada para activar Alpha
pre multiplicado para que
se vea un poco más suave. Y escalarlo a una
cuarta parte de su tamaño. Después expandiendo la sección de bandera, pondré su
bandera de cartelera para
habilitarla, así que siempre va
a mirar hacia la cámara. Y la bandera de prueba de no profundidad siempre
dibujará el sprite sobre todo lo demás independientemente de su posición en el espacio tres D
relativo a la cámara El indicador de objetivo
puede ser invisible por defecto ya que el jugador inicia sin un
objetivo para indicar. Agarrando una referencia
al indicador de objetivo
usando add on ready Entonces tendremos que
colocarlo sobre el objetivo bloqueado. Entonces después de determinar en
qué está
encerrado el jugador , si
hay un objetivo. Una manera fácil de hacer que el indicador de
objetivo siga el objetivo es
repararlo a ese objetivo. Luego podemos moverlo unos
metros hacia arriba para colocarlo sobre la cabeza del objetivo y establecer su propiedad
visible en true. Si no hay un
objetivo que indicar, podemos reparar el indicador de
nuevo a este nodo y volver a establecer su propiedad
de visibilidad en caídas para ocultarlo. Vamos a probarlo. Cuando presionamos el botón de bloqueo de
palanca, el enemigo más cercano es el objetivo, y el indicador se coloca
sobre la cabeza del objetivo. Al presionar nuevamente el botón de
bloqueo de palanca, interruptor está al
siguiente enemigo más cercano. mantener presionado y presionar el botón de bloqueo de palanca, se
fuerza el bloqueo. Si solo hay
un objetivo visible que ya estamos bloqueados, bloqueo también se desactiva. Ahora tenemos al jugador encerrado
a los enemigos en nuestro juego. En la siguiente lección, cambiaremos el comportamiento de la cámara y del personaje
mientras están bloqueados. Te veré en la siguiente lección.
4. Strafe: Hola, amigos. En
la lección anterior, agregamos un
botón de bloqueo de palanca
sensible al contexto a nuestro juego. En esta lección,
cambiaremos la forma en que se comportan
los nodos del jugador mientras se
bloquean en un objetivo. Comenzando en el guión del jugador, una
vez que
se ha bloqueado un objetivo, emitamos una señal para
que cualquier otro guión pueda escuchar y reaccionar al
valor del cambio de objetivo, especificando lo que fue
objetivo como parámetro. Usando un setter,
podemos emitir la señal cada vez que
se cambia el valor del objetivo por cualquier motivo Ahora los tres
personajes, el brazo de resorte y la cámara pueden conectarse
a la señal, usándola para establecer sus
propias variables privadas para lo que se está apuntando. No importa cuál sea el
valor de target en el script de
manejo de entrada del jugador, todos los demás nodos
también tendrán la misma información, incluso si se establece en null. Escribir una función simple
para cada uno que establezca una variable objetivo local todos
puedan
acceder fácilmente a ella. Una vez que nuestro personaje se haya
fijado
a un objetivo, esperaríamos que se enfrentaran hacia el objetivo en lugar de mirar en la dirección en la
que se mueven. En mi guión,
la rotación del personaje se está haciendo
en el proceso de física, que es decirle al
personaje que mire hacia la dirección
de la entrada de movimiento. Vamos a declarar una nueva variable
en la parte superior del guión, quiere enfrentar
la dirección como un tres. Y reemplace la dirección de entrada con quiere orientarse hacia la dirección
en la llamada a la función. Entonces antes de esta llamada a la función, podemos verificar si el carácter
está bloqueado en un objetivo. Si están encerrados
a un objetivo, la dirección que
van a querer enfrentar será hacia el objetivo, que podemos determinar fácilmente
restando sus posiciones
globales Si no están bloqueados,
entonces querrán enfrentar la dirección de
entrada de movimiento, igual que antes. Ahora el personaje se enfrenta
al objetivo bloqueado, pero sus
animaciones de movimiento locales no se ven muy bien, ya que solo se
mezclan en función de la
rapidez con la que se mueve el personaje
y no en la dirección. En la máquina de estado del
árbol de animación del personaje, están en el estado de salto inactivo porque no hay
piso en la escena. El estado de movimiento loco es
un espacio de mezcla unidimensional, mezcla las
animaciones de marcha y carrera inactivas basadas en la velocidad de movimiento del
personaje. Eliminemos este estado y lo
reemplacemos por
otra máquina de estado. Reconectando las transiciones
a los otros estados, comenzando con una
transición de inicio a locomoción para
convertirlo en el estado predeterminado Tenía
habilitada la transición
al arranque en salto con un
peso cruzado de 0.3 segundos. Y saltar tierra a
locomoción cambiando al final con un
destino cruzado de 0.67 segundos Omitiré la transición
de locomoción a saltar inactivo temporalmente mientras trabajo en la máquina del estado de locomoción, por lo que el personaje permanecerá en el estado de locomoción y
puedo ver los resultados Presionando el botón de reproducción
forzará al personaje a entrar en el
estado de locomoción y
se pondrá porque actualmente está vacío Dentro del estado de locomoción, necesitaremos tener
dos conjuntos diferentes de animaciones de locomoción para
cuando el personaje está bloqueado en un objetivo
y cuando
no lo están y poder hacer una
transición entre El valor por defecto será el
mismo que antes, un espacio rubio unidimensional. Vamos a llamarlo no encerrado. Entonces también podemos agregar un espacio rubio
bidimensional. Vamos a nombrar a este encerrado. Agregar una transición
de inicio a no bloqueado hace que
esta sea la predeterminada. Entonces podemos hacer la transición
entre no bloqueado a bloqueado si el valor
de target no es nulo, que podemos acortar a solo target y darle
un corto desvanecido cruzado Y volver de nuevo
a no bloqueado, si no objetivo con
el mismo fundido cruzado. Dentro del espacio de mezcla no bloqueado
. Podemos recrearlo
exactamente como era antes, con un valor mínimo
de cero mezclando animaciones inactivas, caminando y corriendo basadas en la velocidad de
movimiento del personaje Con eso hecho, usa las migas de pan para
subir un nivel a la máquina del estado de locomoción
y presiona el botón de reproducción en la máquina de estado bloqueada para forzar al personaje
a ese estado Dentro del espacio
de mezcla bloqueado, combinaremos
las animaciones en función qué dirección se
mueve el personaje en relación con su dirección hacia
adelante, que es hacia su objetivo. Voy a establecer el ajuste de la cuadrícula a incrementos de uno para
facilitar las cosas Si posicionamos nuestra visión para
estar detrás del personaje e imaginamos que están bloqueados en un objetivo frente
a ellos, entonces el eje y
representa la rapidez la que el personaje se mueve hacia
o lejos del objetivo. El eje x representa la
rapidez con la que el personaje se mueve
hacia la izquierda o hacia la derecha,
agachándose alrededor del objetivo Empecemos por poner la animación
ociosa en el medio. Para el eje x,
vamos a querer poner una animación de strafing left en
el lado izquierdo y una animación el lado izquierdo y una strafing right
en el lado derecho Para el eje y, podemos poner una animación de ejecución en
la posición delantera, que generará
triángulos en el espacio de mezcla mostrando cómo se
mezclarán las
diferentes animaciones se
mezclarán Y agregando una animación caminando
hacia atrás en la posición y negativa, también
agregaremos más triángulos Si cambiamos la posición de mezcla, podemos ver cómo se verá el
personaje mientras damos entrada de movimiento
en cualquier dirección. Dependiendo de los
activos que estés usando, también
puedes tener animaciones de
movimiento diagonal para agregar a este espacio de mezcla. En ocasiones esta vista previa
no
simula con precisión cómo se
comportará el personaje mientras se ejecuta el
juego. Y siempre debes
probarlo jugando
el juego para asegurarte de que se
ve bien en el juego. Pero antes de hacer
eso, volvamos al nivel raíz de
la máquina
estatal y agreguemos la transición de
locomoción a saltar inactivo bajo la condición que el personaje no
esté en el piso Solía cruzar el tiempo de fundido de 0.3 segundos para esta transición. También necesitamos actualizar
la parte de nuestro guión, que establece la
posición de mezcla del espacio de mezcla,
que en el guión de mi personaje está sucediendo en la física del suelo. Seleccionando el árbol de animación, podemos copiar la
ruta de propiedad de la posición de
mezcla no bloqueada y actualizada
en la función set. Pero esto solo necesita establecerse si el personaje no está
bloqueado en un objetivo. Si están bloqueados
en un objetivo, tendremos que establecer
la posición de mezcla del espacio
de
mezcla bloqueado en su lugar. La posición de mezcla bloqueada es un vector dos con
tanto una x como una y, que necesitaremos calcular. Así que vamos a declarar una variable para mantenerla llamada bloqueada en blend. Para evitar repetir los mismos
cálculos varias veces, también
declararé
otra variable para almacenar la velocidad
relativa del personaje, que será su velocidad x z
dividida por su velocidad de carrera. Después de calcular este valor, la posición
de mezcla del espacio de
mezcla no bloqueado se puede establecer
a la longitud de este vector. Si el personaje está
bloqueado en un objetivo, podemos encontrar el valor x de
la posición de mezcla usando el producto de
punto del vector base global de plataformas x con su velocidad relativa El producto punto de dos
vectores da como resultado un número que representa cuán
similares o diferentes son. Entonces estamos comprobando cuán similar es
la velocidad
relativa del personaje a un vector que apunta
directamente a su derecha. Dependiendo de cómo esté configurado tu
personaje, qué dirección se
considera hacia adelante, es posible
que necesites
multiplicar este valor por uno negativo para revertirlo. La posición de mezcla y también
se puede determinar usando
el mismo método, pero usando el vector z
delantero del personaje. A continuación, mientras
está bloqueada en un objetivo, la cámara debe mirar
al objetivo, no al personaje del
jugador. En la función de
proceso de la cámara, ignorando a Delta, si
hay un objetivo, podemos decirle
a la cámara que mire al objetivo y sumando 1 metro hasta que
no mire sus pies Al establecer el
valor de objetivo, si el objetivo se establece en nulo, entonces podemos restablecer la rotación de la
cámara para volver a la
misma que su nodo padre, el brazo de resorte, ajustando
su rotación al vector 30 También podríamos querer
activar la función de bloqueo si el objetivo actual sale de
nuestro límite de rango visible. éter se bloquea o cambia
automáticamente
a un objetivo más cercano. Entonces, agreguemos una señal para cuando el objetivo actual
salga del rango y emitamos si el cuerpo que salió del área es
el objetivo actual Entonces podemos conectar esta señal al guión de
manejo de entrada del jugador. Llamando a la función
de bloqueo de palanca. Dependiendo de si
desea que el comportamiento
cambie al objetivo más cercano o simplemente se bloquee, es posible que desee vincular
un argumento verdadero para la fuerza del parámetro. En el guión del brazo de resorte, mientras está bloqueado en un objetivo, vamos a querer que el brazo de resorte apunte
siempre
lejos del objetivo para mantener tanto el objetivo como el personaje
del jugador a la
vista de la cámara. Vamos a agregar una nueva variable para mantener esa dirección
como un vector tres. Entonces, cuando se está estableciendo
el valor
del objetivo , si no es nulo, entonces podemos establecer el valor de la dirección del objetivo para
que sea la diferencia en nuestra posición global menos la posición global del
objetivo. Esto dará como resultado
un vector apuntando desde el objetivo de nuevo
al personaje del jugador. Entonces podemos volver a usar la función de rotación de
tween, pero se espera un parámetro float
que represente una rotación y Podemos obtener la rotación y, que apuntará
en esta dirección usando la función de trigonometría, A t dos, dándole los valores x y z de
nuestra Una vez que se ha establecido el objetivo, el brazo de resorte girará
la cámara alrededor para estar en la dirección opuesta
al objetivo detrás del jugador. Pero queremos que se quede ahí. En la función de proceso, si
se ha establecido el valor de target y entre paréntesis, si o bien la tween no
existe o no se está ejecutando, es
decir, la tween ha terminado y el brazo de resorte
está en posición, entonces podemos realizar
los mismos cálculos, pero simplemente establecer el
valor de rotación
y directamente en lugar de hacer Esto mantendrá el brazo de resorte apuntando lejos del objetivo, mientras está bloqueado en el objetivo, manteniendo el objetivo
y el
personaje del jugador a la vista de la cámara. Por último, en el guión
de manejo de entrada del jugador, queremos evitar que
el jugador
gire el brazo de resorte
mientras está bloqueado en un objetivo. Esto está sucediendo en dos lugares
diferentes en mi script, uno para controles de PC
usando el mouse, y otro para
soporte de controlador con el stick derecho. Así que simplemente envolveré ambos en una
declaración if para no permitir
estas entradas mientras están bloqueados en un objetivo. Vamos a probarlo. Cuando nos fijamos en un enemigo, la cámara
enfoca el objetivo, mientras que el brazo de resorte gira para posicionar la cámara en
la dirección opuesta. Al mover al personaje,
rotan para enfrentar al enemigo y animar
movimientos fluidos en todas las direcciones El brazo de resorte mantiene la posición de la cámara de
estar detrás del personaje, apuntando lejos del objetivo, mientras la cámara continúa mirando
al objetivo. Los controles normales de la
cámara del jugador se
han desactivado
mientras están bloqueados. Si el objetivo bloqueado
está fuera de rango, entonces cambiará
automáticamente
al objetivo más cercano o se
bloqueará si no hay
uno en el que bloquearse. Si forzamos a bloquear, entonces la cámara vuelve a enfocar el personaje del jugador, se
reanuda el control
normal del brazo de
resorte y las
animaciones de locomoción de los personajes vuelven a Ahora tenemos nuestros nodos de
jugadores adaptando sus comportamientos para estar
bloqueados en un objetivo. En la siguiente lección, haremos que el personaje jugador
realice ataques. Te veré en la siguiente lección.
5. Ataque: Hola, amigos. En
la lección anterior, cambiamos el comportamiento de los nodos del jugador mientras
estaban bloqueados en un objetivo. En esta lección, agregaremos animaciones de
ataque para que los personajes puedan
atacarse entre sí. Comencemos abriendo
la configuración del proyecto, la pestaña del mapa de entrada y agregando un nuevo
evento de entrada para atacar. Usaré el botón izquierdo del ratón y el
botón del hombro derecho en mi mando. Luego en el script del controlador de
entrada del jugador, podemos verificar si se presionó el botón de
ataque al verificar las entradas de control de
caracteres Si
se presionó el botón de ataque este fotograma, entonces deberíamos decirle al
personaje que ataque. Pero, ¿y si el
personaje está ocupado? Podrían estar saltando o
realizando alguna otra acción y quizá no queramos
que puedan atacar en este
momento. Requerir que el jugador
espere hasta que sea
posible atacar antes de
presionar el botón sería bastante frustrante La mayoría de los juegos modernos
considerarán que
la pulsación es válida por un corto tiempo
después de presionar el botón, lo que se conoce como búfer
de entrada Agreguemos un tiempo o nodo al controlador
de entrada del jugador. Denle el nombre buffer de entrada y establezca su
propiedad one shot en true, por lo que solo contará
atrás una vez a la vez. Agarrando una referencia a este temporizador de búfer de entrada
usando add on ready, podemos iniciar el temporizador después de decirle al
personaje que ataque, luego esperar su señal de tiempo de espera. Después de que el temporizador haya
contado atrás a cero, entonces le diremos
al personaje cancele la instrucción
que se le dio para atacar. Por lo que en cualquier momento mientras el
temporizador está contando atrás, el personaje intentará
atacar cuando esté listo. El tiempo de espera predeterminado para
el temporizador es de 1 segundo, que es una cantidad razonable de tiempo para el búfer de
entrada de ataque. Otra entrada que podríamos
querer almacenar en búfer es la entrada de salto. Siguiendo el
mismo patrón que la entrada de ataque, podemos iniciar el temporizador, esperar su señal de tiempo de espera, luego cancelar la entrada de salto. En el guión del personaje, comencemos por crear una
nueva región de código para el combate. Luego mueve la
función objetivo del jugador a esta región. Necesitaremos una función pública
para decirle al personaje que ataque y otra para decirle que cancele
la instrucción. La función de salto también necesitará una función de coincidencia y cancelación de
salto dos. El propósito principal
de estas funciones es establecer variables que serán verificadas por
el árbol de animación que sepa a qué
estados viajar. En la parte superior del guión, agregaremos más
variables para indicar intenciones
del personaje de
lo que quiere hacer a continuación, entradas
Buffered como Booleanos, ya sea que quieran
saltar o quieran atacar Entonces la función de ataque
establecerá la
variable wants to attack en true y cancel attack volverá a
establecerla en false. Dado que la entrada está
siendo almacenada en búfer, ya no
necesitamos
exigir que el personaje pueda
moverse o estar en el piso, y podemos delegar
esa responsabilidad a la máquina de estado de
árboles de animación. Y tampoco necesitamos decirle a reproducción de
la máquina de
estado del árbol de animación que viaje al estado de inicio de
salto. Haremos esta transición automática si se cumplen las
condiciones. Pero no queremos que ambas variables sean ciertas
al mismo tiempo. El personaje querrá saltar o atacar, no ambos. Entonces, cada vez que una
entrada en búfer se establece en true, todas las demás se establecerán false, anulando
la instrucción En la
escena del personaje, seleccionando el árbol de animación y cambiando al panel del árbol de
animación, podemos ver la máquina de estado. Cambiemos la
transición que lleva de locomoción a inicio de
salto para que sea automático bajo la
condición de que el personaje esté en el piso y pueda
moverse y quiera saltar Ahora el personaje saltará
automáticamente tan pronto como puedan dentro de 1 segundo después de
presionar el botón de salto. Esto es particularmente útil para encadenar saltos
uno tras otro, ya que el jugador
podrá presionar el botón de salto antes de
golpear el suelo Pero mirando la máquina de estado de
salto, consideremos cómo incorporar
las animaciones de ataque. Podríamos pasar
de la locomoción al ataque y volver de nuevo. Pero las animaciones
quedarían mal si
queremos que el personaje pueda
moverse mientras ataca. No permitiría que el personaje
atacara mientras saltaba. En cambio, sería mejor
separar las animaciones que implican mover al personaje de las de
realizar acciones. Si su
máquina de estado aún no se ha guardado como
recurso de proyecto, haga clic en el menú desplegable junto a Raíz de
árbol y seleccione Guardar como. Ya guardé el mío
en la
carpeta de escenas de personajes y lo llamé animaciones de
personajes. Pero voy a cambiarle el nombre
a movimientos de personajes. Con la máquina de estado guardada, eliminémosla del árbol de animación del
personaje
y, en su lugar, la reemplacemos con
un árbol de mezcla de nodos de animación. El panel del árbol de animación
ahora muestra un gráfico, que contendrá nuestro árbol de mezcla, lo que nos permite combinar cualquier
cantidad de animaciones juntas. Pulsando con el botón derecho en
el espacio vacío, selecciona cargar. Después navega por los recursos de tu
proyecto para encontrar tu máquina de estado de
movimiento de personajes. La máquina de estado que estábamos usando anteriormente ahora es un nodo
en el gráfico de árbol Blend, y el resultado de la máquina de
estado
se emitirá por el pin
en su lado derecho. Si conectamos la salida de la máquina de estado a la
salida del árbol de mezcla, entonces la animación
funcionará tal como lo hacía antes. Pero el propósito
del árbol de mezcla es mezclar múltiples
animaciones juntas. Desconectemos el pin. Después haga clic derecho y
agregue un nodo blend two. El nodo blend two
comenzará con la animación
conectada a su pin de
entrada y se fusionará en un porcentaje de la animación conectada a su pin de entrada de
fusión. El resultado de esta mezcla se
emitirá desde el pin
en el lado derecho, que podemos conectar a
la salida de los árboles de mezcla. La animación que queremos mezclar con los
movimientos del personaje
serán las acciones del personaje, es
decir, sus ataques. Podemos agregar otra máquina de
estado al árbol
de mezcla y darle el
nombre de acción. Luego conecte su salida al pin de entrada
de mezcla de dos nodos de
mezcla de mezcla. A continuación, abriremos la máquina de estado de
acción e iniciaremos el personaje
en la animación inactiva. Transición de inicio a
inactivo para convertirlo en el estado de acción
predeterminado A continuación, necesitaremos una vista de nuestro personaje y para iniciar
tanto las máquinas de estado de movimiento como de
acción
haciendo clic en el botón de reproducción en sus
respectivos estados de inicio. Luego regresa a la raíz
del árbol de mezcla. Nuestro personaje todavía
parece estar en la
animación de salto inactivo porque el porcentaje de
la animación de acción que se mezcla en ella
es actualmente cero. Si arrastramos el
mango sobre uno, podemos ver que la animación cambia
gradualmente de
salto inactivo a inactivo. A continuación, haga clic en el botón de
editar filtros y active habilitar filtrado. Alejemos la ventana para que podamos
ver
a nuestro personaje a medida que
filtramos huesos individuales, decidiendo a qué huesos se
deben aplicar
nuestras animaciones de acción y cuáles no. Enciende todos los huesos que componen la parte superior del cuerpo del
personaje. Ahora la parte inferior del cuerpo del personaje, incluida su posición, está siendo afectada por
el estado de movimiento. Salta inactivo, mientras
su parte superior del cuerpo está siendo controlada por
su estado de acción inactivo. Esto nos permite combinar estas animaciones de tres
maneras diferentes. Si el personaje se mueve pero
no realiza ninguna acción, entonces la
cantidad de mezcla será cero, usando solo la salida de
la máquina de estado de movimiento. Si el personaje está realizando
una acción pero no se mueve, entonces la
cantidad de mezcla será uno, y los filtros se apagarán, usando solo la salida de
la máquina de estado de acción. Si el personaje se está moviendo
y realizando una acción, entonces los filtros se
encenderán. Usando la salida de la máquina de estado de
movimiento para la parte inferior del cuerpo del personaje y la salida de la máquina de
estado de acción para
su parte superior del cuerpo. Vamos a nombrar a esta mezcla dos
nodos inferior más superior, ya que está fusionando las animaciones de la
parte superior del cuerpo
en las animaciones de la parte inferior del cuerpo. Pero si la
cantidad de mezcla es cero o uno, entonces las animaciones en una de las máquinas de estado no se
ejecutarán para ahorrar en tiempo de procesamiento, lo que puede resultar en
algunos problemas si estamos confiando en ellas para establecer
propiedades o llamar métodos. Puede ser útil tener siempre ambas máquinas de estado
funcionando en todo momento, aunque el personaje no esté realizando ninguna acción
o no se mueva. Para asegurar que ambas
máquinas de estado estén siempre activas, podemos establecer la cantidad de
mezcla en 1%, y al realizar una acción, aumentarla a 99%. Podemos suponer que debe comenzar con una cantidad de mezcla de 1% ya que el personaje no estará realizando ninguna acción
cuando se cargue por primera vez. De vuelta en el guión del personaje, dado que el árbol de animación
va a volverse
mucho más complejo, sería una buena idea abstraer sus comportamientos
en su propio guión. Podemos eliminar la variable de reproducción
de la máquina de estado del script de caracteres y agregar un nuevo script
al árbol de animación. Lo guardaré en la carpeta de scripts de
caracteres. En los
árboles de animación nuevo guión, nuestro principal objetivo es crear las tres
mezclas de animación que acabamos de mencionar. En la función process, necesitaremos establecer el parámetro de cantidad de
mezcla como hicimos con
los espacios de mezcla. Copiar la ruta de propiedad y
especificar una cantidad de mezcla. Hagamos que la
cantidad de mezcla sea una variable
flotante privada con un valor
predeterminado de 1%, y pasemos esto como argumento. Entonces tendremos que cambiar
el valor de la cantidad de mezcla en
función de si el
personaje está
realizando o no una acción. Almacenemos la
reproducción de las máquinas de estado de
acción en una variable. Esta vez, usando
la palabra clave self, ya que este script se
adjunta al árbol y usando la ruta de propiedad para la reproducción de la máquina de estado de
acción. Entonces en la función de proceso, podemos verificar en qué nodo se encuentra actualmente
la reproducción del estado de acción. Y si está en el estado inactivo, entonces eso significa que el personaje
no está realizando ninguna acción, y podemos establecer la cantidad de
mezcla en 1%. De lo contrario, están realizando una acción y
podemos fijarla al 99%. Pero esto será un cambio
instantáneo que podría parecer un poco nervioso Entonces, en lugar de establecer la
variable directamente en 1% o 99%,
vamos a moverla hacia ese número en una pequeña
cantidad a lo largo del tiempo. Usando la función mover hacia, podemos partir de lo que es actualmente la
variable, moviéndola hacia lo que
queremos que sea por Delta. Esto hará que la
transición tome 1 segundo, lo que es un poco largo. Así que vamos a multiplicar Delta por una nueva variable para
mantener la velocidad de mezcla, que voy a dar un valor
predeterminado de cuatro. La transición tomará
un cuarto de segundo. Para activar o desactivar los filtros, necesitaremos acceder directamente al nodo
blend two. Entonces declarando una
variable para mantenerla, que es de tipo
animación nodo mezcla dos Podemos acceder a él a partir de la raíz del árbol de árboles de animación, usando la función get node. Esta función acepta
un nombre de cadena, que podemos especificar como
el mismo nombre que le dimos al nodo en el
gráfico de árbol de mezcla, inferior más superior. Ten cuidado de que la
ortografía sea exactamente igual. No se nos permite activar o
desactivar los filtros mientras se procesa el
árbol de animación. Entonces hagamos una función pública para dejar que el
guión del personaje haga esto por nosotros, diciéndole al árbol de animación si el
personaje se está moviendo o no. Si el personaje se mueve, entonces los filtros deben
estar habilitados para mezclar las acciones de
la parte superior del cuerpo con los movimientos de
la parte inferior del cuerpo. Si el personaje está estacionario, entonces los filtros se pueden desactivar para usar solo las animaciones de
acción. Mientras estamos aquí, agreguemos también dos funciones más para
establecer las cantidades de mezcla de los espacios
de
mezcla de locomoción para mantenerlos abstraídos del guión
del personaje Establecer bloqueado en mezcla, aceptando un
parámetro de vector dos para la cantidad de mezcla, estableciendo el parámetro
de
cantidad de mezcla del espacio de fusión bloqueado en. Y establecer no bloqueado en la mezcla, aceptando un parámetro de flotación
para la cantidad de mezcla, estableciendo el parámetro
de
cantidad de mezcla del espacio de fusión no bloqueado
en. De vuelta en el script de caracteres, podemos ver que
las rutas de propiedad a las cantidades de mezcla ya no
son válidas, ya que no hacen referencia a
la máquina de estado de movimiento. Resumiendo estas
funciones, mantendremos cualquier cambio en el árbol de
animación contenido dentro de su propio guión En el proceso normal de física, también
tendremos que decirle
al árbol de animación si el personaje
se está moviendo o no actualmente. Sin embargo, ahora estamos asumiendo
que cada personaje debe tener este guión adjunto
a su árbol de animación, y que están usando
el mismo árbol de animación. Así que vamos a guardar nuestro
nuevo árbol de animación como recurso de proyecto. Lo pondré en la carpeta de escenas de
personajes, junto con la máquina de estado de
movimiento de personajes. Después actualice cada uno de los
otros personajes para usar el nuevo árbol de animación y
adjuntarle el guión, que todos funcionen
de la misma manera. Solo estoy usando el Bárbaro y los esqueletos en este proyecto, pero el mago nocturno y el pícaro también
deberían actualizarse
si los estás Sin embargo, esto crea
un nuevo problema. Si cada carácter comparte el
mismo recurso de árbol de mezcla, entonces cambiar la propiedad enable
filters para un carácter la cambiará
para todos los caracteres. Podemos sortear esto dando a cada personaje su propia copia
única del árbol de mezcla. Para evitar tener que replicar cada cambio en el árbol de
mezcla de cada personaje cada vez, usaré un simple atajo En el script del árbol de animación, durante la función ready, estableceré la propiedad
raíz del árbol para que sea un duplicado
del árbol de mezcla. Pasar true como argumento también
duplicará cualquier subrecurso que este
recurso esté utilizando. Desde el árbol de mezcla, este árbol de
animación está usando ya que su raíz ya no es la misma que se le asignó
originalmente. Tendremos que
asignar los valores de la reproducción
del estado de acción y el nodo blend two
después de esta duplicación. Ahora cada vez que se carga un
personaje, harán su
propia copia única del árbol de mezcla y
podrán cambiar su comportamiento de
filtrado sin afectar a
otros personajes. Volvamos a la máquina de estado de
acción de personajes. Nuestro personaje aún no tiene
ningún objeto equipado, así que vamos a hacer la transición
a ídolos desarmados Por ahora, hagamos que
la condición para esta transición sea si están apuntando
a un enemigo
o si quieren atacar usando un
corto desvanecedor cruzado, y pueden hacer la transición de
regreso si no están apuntando a un enemigo y
no quieren atacar. Entonces para mantener las cosas organizadas. También agregue otra máquina de estado
llamada ataques desarmados, y haga la transición a
la máquina de estado si el personaje
quiere atacar Luego pueden hacer la transición de nuevo a ídolo
desarmado al final
de la animación de ataque Edición de la máquina de
estado desarmada. Empecemos con un golpe de ataque
masculino desarmado A. Esto hará la transición
al final o al golpe de ataque masculino
desarmado B al final de
la animación en función si el personaje
quiere o no volver a atacar Podemos repetir este patrón
haciendo la transición a una patada de ataque masculina final
o desarmada
al final de la animación, en
función de si el personaje
quiere o
no atacar una vez más. Y podemos crear un combo de ciclismo
sin fin haciendo la transición de nuevo al primer golpe
siempre y cuando el jugador siga
presionando el botón de ataque Cuando dejan de presionar
el botón de ataque, la máquina de estado
pasará a terminar, lo que
volverá a estar inactivo desarmado También podríamos querer restringir
cómo se mueve el jugador
mientras ataca. Por ejemplo, no tendría ningún
sentido que el personaje se moviera en absoluto
durante la animación de patada, ya que sus pies deberían estar ocupados. Acercaré la pantalla de la pista de
animación para ajustarme mejor a la longitud
de estas animaciones. Agreguemos una función pública al script de caracteres
para restringir
el movimiento, aceptando un parámetro booleano para saber si el
personaje puede moverse o no Luego estableceremos el valor de la variable move
para que sea lo contrario. En la animación de
patada del personaje. Podemos agregar una pista de método de llamada llamando a un método en el nodo raíz del
personaje. Llamar a la función de restricción de
movimiento al inicio de la animación, pasando true como argumento, restringiendo el
movimiento del personaje mientras patea Y otra clave al final
de la animación puede restaurar la capacidad del personaje para moverse cambiando el
argumento a falso. Pero para que esto funcione,
necesitamos regresar
al árbol de mezcla y
agregar funciones a los
filtros blend two nodes para que si el personaje se está moviendo
y realizando una acción, se
llamará a las funciones actions. L et's pruébalo.
Nuestras animaciones parecen estar funcionando
como lo hacían antes. En cuanto le decimos al
personaje que ataque, hacen la transición
al estado inactivo desarmado antes de realizar un ataque Si seguimos ciclando,
seguirán atacando repetidamente, recorriendo en
bicicleta las diferentes animaciones de ataque
desarmado Incluso es posible moverse
o saltar mientras ataca, y el personaje utilizará las animaciones adecuadas para su parte superior e inferior del cuerpo, pero no se le permite
moverse o saltar mientras patea Si nos bloqueamos en un objetivo, el personaje pasa
al estado inactivo desarmado y bloqueando las transiciones de
regreso al ídolo normal Ahora tenemos a nuestro personaje
realizando ataques desarmados. En la siguiente lección, agregaremos animaciones de ataque con
armas. Te veré en la siguiente lección.
6. Arma: Hola, amigos. En
la lección anterior, mezclamos las acciones de la parte superior del cuerpo
con los movimientos de la parte inferior del cuerpo, permitiendo que nuestro personaje
realice ataques desarmados En esta lección, también agregaremos una variedad de
animaciones de ataque con armas. Empecemos en el árbol de
animación de personajes donde
ya tenemos ataques inactivos
y desarmados desarmados Siguiendo este
patrón, agregaremos la animación inactiva a dos manos. En este paquete de activos,
no hay animaciones inactivas de una sola mano o de dos
ruedas Pero solo podemos
agregar dos nuevas copias de la animación inactiva
y cambiarles el nombre. A partir de cada una de estas animaciones
inactivas, entonces
podemos conectarnos a máquinas de
estado de ataque que funcionan
igual que los ataques desarmados Conectando desde cada una
de las animaciones inactivas a los ataques si el
personaje quiere atacar, y regresando al
final de la animación. Solo necesitamos una forma de decirle
al personaje qué conjunto de animaciones usar
en función de su arma equipada. En este proyecto, tenemos
un guión llamado enums, contiene todas nuestras enumeraciones, a las que agregaremos
otro tipo de arma Comenzando con desarmado
como predeterminado, luego enumerando cada uno de los diferentes tipos de armas que necesitan diferentes animaciones, mala con
una mano, mala a dos manos
y doble rueda Es importante saber que la enumeración es
solo una lista numerada, por lo que cada uno de estos valores
son en realidad números, comenzando por ser cero
desarmado, una mano es una,
dos manos es dos, y doble rueda es tres En el
script de caracteres, agregaremos otra variable llamada
attack animation con un tipo de nuestra
nueva enumeración Podemos exportar esta variable con
fines de prueba. L et's cambian la animación de ataque del
personaje a otra cosa que no sea desarmada Usaré cuerpo a cuerpo a dos manos. De vuelta en la máquina de
estado de acción, podemos establecer la
condición de transición para pasar de inactivo a inactivo desarmado para ser si la
animación de ataque del personaje es cero, que está desarmada en
nuestra enumeración, y también al menos una de las otras condiciones
poniéndolas La condición de retorno será
entonces también lo contrario. O la
animación de ataque no es cero, o se cumplen las otras dos
condiciones. Al agregar transiciones a cada uno de
los diferentes estados de inactividad, podemos establecer sus condiciones para que sean las mismas que inactivas desarmadas, solo usando un valor diferente
para la animación de ataque Voy a dar a cada uno de ellos el
mismo tiempo de fundido cruzado también. Después haciendo la transición de nuevo al ralentí bajo las condiciones lógicamente
opuestas Dentro de cada una de las máquinas de estado de
ataque, podemos usar las
animaciones de ataque de la misma manera que hicimos con
los ataques desarmados Hay cuatro diferentes ataques con
una sola mano, creando un ciclo de
diferentes animaciones siempre y cuando el personaje
quiera seguir atacando. Repitiendo el mismo proceso
para los ataques a dos manos, que sólo tiene tres ataques
diferentes. Y la máquina
estatal de doble rueda también sólo tiene tres ataques Podemos
probar esto en el juego, ya que la
animación de ataque de los personajes está establecida en dos manos,
utilizan las animaciones de
ataque a dos manos. Podemos decirles que usen animaciones de ataque
con una mano
o animaciones de doble rueda
también Ahora, solo necesitamos cambiar la variable al equipar
elementos al personaje En los recursos personalizados, necesitaremos una clase más
específica para describir un arma que
hereda del equipo Dándole el nombre de clase arma, podemos agregar una variable
exportada extra para almacenar el tipo
de arma que es, y podemos usar la misma
enumeración que el Entonces cualquiera de los
recursos de ítem en el proyecto que son armas pueden ser
reclasificados como armas, dándoles un valor
por su tipo de arma, por lo que el personaje sabrá qué animaciones usar
al equiparlos Para fines de demostración,
actualizaré la x para que sea un arma con
una sola mano. Recuerde repoblar
los campos que no
se traspasen al
cambiar el script de recursos El grado como arma a
dos manos, y la daga como arma de
doble rueda. En el guión int o en el que
sea que estés
usando para equipar objetos, necesitaremos una excepción para si el objeto que se está
equipando es un arma Y si es
un arma a dos manos
o un arma de doble mano, entonces tendremos que quitar cualquier cosa que el personaje tenga equipado
en su ranura fuera de la mano C agitando primero si el archivo, el conjunto de equipos de
progreso tiene algo equipado en
la ranura de mano Luego lo usaré para
indexar los botones del ítem en el inventario del jugador y quitaré la E para equipar
del botón. Luego, también establezca el valor de las matrices
de
equipos en negativo uno o vacío. Entonces le diré al
personaje que dof cualquier equipo en su
toma de mano En el guión
del personaje, el personaje necesitará saber qué tiene
en sus manos. Agreguemos variables de tipo nodo tres D para sostener su mano principal y su equipo
fuera de mano. Nuestro personaje que se ponga un
arma también puede tener algo de lógica adicional agregada para
si el objeto es un arma El objeto de la mano principal del personaje se
puede asignar entonces
a esta arma, y las animaciones de ataque de los personajes
se pueden configurar
para que coincidan con
las del arma que se está equipando. Si el objeto es un arma tipo
rueda doble, también
agregaré otra copia
duplicada del arma en la toma de mano del
personaje. Y asignarlo a la variable
off hand. Al quitarse una
pieza de equipo, si ese equipo se está
quitando de la mano principal del
personaje, entonces podemos establecer la variable de mano
principal null y también verificar si actualmente
son de doble Si es doble empuñando, le diré al personaje que haga el artículo también
en su mano apagada Y luego configuraré la
animación de ataque a desarmada. Asimismo, si el socket que se
está quitando es el off hand, entonces deberíamos establecer la variable
offhand Ya no necesitamos exportar
la animación de ataque, ya que ahora la establecerá
el arma equipada. Ahora el personaje comienza a
usar ataques desarmados. Pero cuando está equipado con
un arma de una mano cambia a usar ataques con
una sola mano. Podemos equiparlos con un escudo, luego cambiar a un arma a
dos manos, y el escudo se eliminará
automáticamente. El personaje ahora usa animaciones de ataque
a dos manos. Cambiando a las dagas de
doble rueda, el personaje tiene una
daga en ambas manos y usa las animaciones de ataque de doble rueda Un equipando las dagas, el personaje vuelve a
usar ataques desarmados Lo último que
necesitan nuestros ataques son cajas de cadera. Áreas de colisión para detectar si el ataque realmente golpea a un
enemigo e inflige daño. Al abrir las escenas de armas, podemos agregar cajas de golpes
a cada una de ellas. Usar un nodo D de área tres, que no será monitoreado
o monitoreable por defecto, ni tendrá ninguna capa de colisión o máscara de
colisión hasta que se
les indique que lo hagan Dado que estos
modelos de personajes tienen extremidades
cortas y armas pequeñas, sus ataques no
llegan muy lejos. Entonces voy a ser muy
generoso con sus cajas de cadera, haciéndolas más grandes que
las armas reales. Crear un nuevo guión para las armas,
heredando del ítem Reemplazaré el
script adjunto
al nodo raíz de armas
y lo abriré para editarlo. Podemos decirle al
arma que agarre o haga referencia a su
caja de impacto usando add on ready. Luego agrega funciones para establecer la
máscara de colisión de cajas de impacto en un nuevo número entero. Y otro que
activará o desactivará el hit box configurando
su propiedad de monitoreo El personaje que sostiene
esta arma
ahora puede especificar en qué capa de
colisión están
sus enemigos y
activar la caja de impacto al
balancear el arma. El modelo de personaje también
necesitará una caja de cadera para ataques desarmados Al igual que las
armas, no
necesita ser monitoreada,
monitoreable, ni tener una capa de colisión o
máscara de colisión y
tendrá una forma de
colisión sobredimensionada Pero no necesitamos
posicionarlo ahora mismo y podemos delegar esa responsabilidad en
las animaciones. En el
guión del personaje, podemos tomar una referencia a la caja de
cadera desarmada usando add on ready Recuerda agregar una
caja de cadera a cada personaje o usar la
función get node o null para evitar errores. También exportemos una capa de física de
tres D para contener la capa de colisión de los enemigos de
este personaje. Esto agregará una cuadrícula de números en el
inspector al igual que las capas de colisión en el área tres propiedades de notas D. De esta manera, podemos especificar
que este personaje estará tratando de golpear cosas en la capa de colisión
enemiga Hurt, que he dicho
que es la capa 18. Mientras tanto, los enemigos que usan
el mismo guión pueden establecer su capa de colisión enemiga para que sea la capa de
colisión HRT del jugador Durante la función ready, podemos configurar la máscara de colisión de
la caja de cadera desarmada para que sea
la capa de colisión del enemigo De igual manera, cada vez que se equipa un
arma, podemos establecer su máscara de colisión para que sea la capa de
colisión del enemigo, así sabrá qué capas
enmascarar independientemente de
quién la sostenga. Entonces necesitaremos
algunas funciones en el guión del personaje
para activar y
desactivar las cajas de cadera de las armas durante
las animaciones de ataque, aceptando un parámetro booleano para especificar si la caja de cadera se está activando o desactivando y un entero Y le voy a dar un valor por defecto de uno para significar la mano principal. Usando una declaración de coincidencia, podemos crear tres casos
separados, activando la caja de cadera
para ataques desarmados, ataques mano
principal
o ataques fuera de la mano Si está desarmado, podemos activar la propiedad de monitoreo de la caja de cadera
desarmada Si es mano principal o de mano, entonces podemos decirle al arma active o desactive
su caja de impacto Nuestras animaciones de personajes
pueden entonces tener pistas agregadas a ellos para activar y
desactivar los hit boxes Yo sólo voy a demostrar con
un ataque de cada tipo, comenzando con un ataque
masculino de una mano chuleta. Al agregar una
pista de método de llamada a esta animación, generalmente
esperaríamos que el hit box se active justo después de
que comience a balancearse. Añadiendo una clave en este momento, podemos cambiar el
argumento booleano a true para activar el hit box del arma principal del
personaje. Después se desactivó al final
del swing cambiando
el argumento a false Esto evitará que los enemigos
entren en el arma cuando no se mueve
se vean perjudicados por ella, y solo inflige daño cuando el personaje realmente está
balanceando el arma con fuerza El proceso es el mismo a la hora empuñar un arma en las manos. Al agregar una pista, luego se llama a la función de encuadre de
teclas para activar el cuadro de aciertos al inicio del swing del arma y desactivarlo
al final del Al empuñar doble,
necesitaremos especificar qué caja de cadera
se está activando, ya sea la
mano principal o la mano apagada, cambiando también el parámetro
entero a dos, si la caja de cadera
que se activa o desactiva pertenece
al arma off hand Y al desarmarnos, no solo necesitaremos
activar la caja de cadera, sino también posicionarla para que esté
en la ubicación correcta Usando una pista de propiedad para enmarcar la propiedad de
posición de cajas de cadera. Luego cambiaremos el
argumento entero en las llamadas
a la función a cero para indicar que
queremos usar el hip box desarmado Es una buena idea
asegurarse de que la caja de cadera esté en posición al menos un cuadro
antes de activarlo. Ayuda a usar
vistas ortogonales para posicionar la caja de cadera exactamente en el puño del personaje desde
al menos dos ángulos diferentes. A continuación, haga clic en el icono de
clave para enmarcar esta posición
en la animación. No podremos probar
estas cajas de cadera hasta la siguiente lección cuando agreguemos cajas
lastimadas para que las golpeen. El hip box no sólo se
activará con la animación, sino que luego también seguirá
el puño del personaje. Recuerda que
necesitarás completar este proceso para cada animación de
ataque. Ahora tenemos a nuestro
personaje atacando con diferentes animaciones
para cada tipo de arma. En la siguiente lección, permitiremos que los personajes se
lastimen y sufran daños. Te veré en la siguiente lección.
7. Golpe: Hola, amigos. En
la lección anterior, agregamos cajas de golpes a nuestras
armas y animaciones de ataque. En esta lección
agregaremos cajas de Hurt a nuestros personajes para que
puedan ser golpeados por ataques. A personajes Hurt box es sólo
otra zona tres nodo D. Vamos a añadir a
los modelos de personajes. No estarán monitoreando, sino que serán monitoreables
por las casillas de impacto Existirán
ya sea en la capa de caja
Hurt de jugadores o
en la capa de caja
de corazón del enemigo apropiadamente. Pero no es necesario enmascarar nada ya que no están
monitoreando de todos modos. Para la forma de
colisión de cajas Hert, otra cápsula es muy común, pero suele ser más pequeña que la forma de
colisión del cuerpo del personaje y completamente contenida dentro
del modelo de personaje No le parecería justo
al jugador ser golpeado por algo que no
parece hacer contacto. Ten en cuenta que
las armas están usando cajas de cadera de gran tamaño, por lo que las cajas hert también serían razonables, pero haré que las mías se ajusten a la cabeza y al cuerpo del
personaje Luego copiaré y pegaré la misma caja hert en las escenas de mis personajes
enemigos, cambiando su capa de colisión a la
capa de HRT enemiga Entonces en nuestras escenas de armas, usaré el hacha como ejemplo. Tendremos que conectar
la señal
ingresada en el área del hit box al guión del arma. Si esta caja de golpe de armas entra en la caja de daño de
un personaje, entonces necesitaremos esta arma para infligir daño a
ese personaje Por ahora, agreguemos una variable pública para
este daño armamentístico. Cuando ocurra la colisión, necesitaremos una referencia al personaje
al que pertenece la caja
Hurt. En mi proyecto, ese
siempre será el
nodo padre de la caja Hurt. Entonces podemos decirle al
personaje que tome daños, pasando como argumento el
daño de las armas. También podría ser agradable saber la dirección de la que proviene el
daño. Entonces podemos usar la
diferencia entre sus
posiciones globales normalizadas. Para mantener toda la
información de nuestras armas en un solo lugar, su daño debe agregarse
al archivo de recursos como
una variable exportada, y le daré un
valor predeterminado de dos daños. Cada archivo de
recursos de arma diferente puede
especificar entonces cuánto daño infligirá
esa arma Recuerda conectar también la señal
ingresada por el área para cada escena de
arma. De igual manera, la caja de cadera
desarmada de nuestro personaje también necesita una conexión de señal para decirle
al personaje que
inflija daño desarmado Conseguir a los padres de la Caja
Hurtada y decirles que sufran un daño y proporcionarles
la dirección normalizada. Luego en el guión del personaje, cuando creamos la instancia de
arma, podemos establecer su daño para que sea el mismo número
del recurso. I. Mientras estamos aquí, escribamos también la función de tomar daño en
la región de combate. Aceptando una
cantidad de daño a tomar, así
como
la dirección de la que proviene el daño, dándole un
valor predeterminado de vector 30. Para recibir daños, nuestros personajes necesitarán salud. Voy a añadir una categoría de exportación
para las variables de combate. Después declararé uno
para los caracteres salud
máxima como un entero, que estableceré en cinco. Y su salud actual
también como un entero, que podemos establecer a su salud
máxima
usando add on ready. También declaremos un par de parámetros
booleanos para saber si el personaje está muerto
o no, y si el daño que se está tomando
se entregó desde atrás, y también tomemos una referencia al cuadro rt
del personaje
usando add on ready Al recibir daño, la salud actual del
personaje se
reducirá por la
cantidad de daño recibido, pero no queremos permitir
que vaya por debajo de cero. Entonces podemos usar la
función max para configurarla
a este cálculo o a
cero, lo que sea mayor El
booleano de detrás se puede
establecer entonces en true si el producto de
punto de la dirección de daño con
el vector
base de plataformas de caracteres hacia adelante es un Si la salud
actual del personaje después recibir daño es cero,
entonces morirán. De lo contrario, serán golpeados. Si bien la animación de muerte
será automática, la animación de golpe puede ser manejada por el guión de árboles de
animación, y le diremos
si el daño recibido estuvo por debajo o
por encima de cierto umbral. De esta manera, podemos cambiar la animación de golpe en función de la
cantidad de daño recibido. También es posible que queramos rastrear la salud de
un personaje
o cuándo muere. Sería una buena idea
transmitir ambos de esos
eventos como señales. Declarando una señal para cada vez que cambia la
salud del personaje, podemos usar un porcentaje
de salud restante como argumento y otra señal para cuando muere el personaje Después emiten la señal de salud
cambiada si reciben daño y la señal de dado
si muere el personaje. Para calcular su porcentaje
de salud restante, simplemente dividimos su
salud actual por su salud MX. Pero como ambos
valores son enteros, el resultado
también será un número entero, por lo que sólo alguna vez
resultará en cero o uno Habrá que lanzar al
menos uno de ellos a flote primero antes de
realizar la división, por lo que el resultado
también será a flote Si ya no queremos que los personajes
muertos se vean impactados por colisiones, también
podemos establecer su capa de
colisión en cero, su máscara de colisión en uno, lo que solo se
verán afectados por el terreno
y establecerán su propiedad
monitoreable H rtbach También es posible
que un personaje pueda ser golpeado o asesinado mientras
realiza una acción. Por lo que también debemos hacer un seguimiento
de qué acciones que se interrumpen pueden causar problemas y corregirlos en
una función privada. Por ejemplo,
probablemente deberíamos apagar todas
sus cajas de cadera si se interrumpieron sus
ataques, lo que también podemos hacer en
una función separada, verificando si existen referencias a cada una antes de
apagarlas. En el árbol de
animación de personajes, vamos a querer que el personaje
muera o sea golpeado para interrumpir y anular
todas las demás animaciones. Dado que este árbol de mezcla
ya está guardado como recurso, podemos eliminarlo
del árbol de animación y reemplazarlo con
una máquina de estados. En el mismo nivel raíz
de la máquina de estado, comenzaremos con nuestras animaciones de muerte de
personajes, ya que esas tendrán la máxima prioridad
absoluta sobre todas las demás animaciones. Después agrega otra máquina de estado
para las animaciones de hit. Pasaremos de golpe a muerte A si el
personaje está muerto. Con un corto fundido cruzado. O alternativamente
a la muerte B si también
fueron golpeados
por detrás dando esta prioridad poniéndola a cero. Puede que no sea necesario que nuestro personaje
vuelva a pasar de estar muerto, pero no está de más
agregar la transición con la condición de
que no estén muertos. Dentro de la máquina de estado hit, haremos algo similar con las animaciones de hit y agregaremos nuestro árbol de mezcla como la animación
predeterminada aquí. Habilitando las transiciones a las animaciones de éxito y volviendo al árbol de mezcla al final de sus animaciones. Con un fundido cruzado tanto
dentro como fuera de las animaciones de
éxito, Con la máquina de
estado del árbol de animación actualizada, guardaremos como
un recurso del proyecto. Le voy a nombrar animaciones de
personajes. Y por última
vez, cada personaje puede actualizarse para usar
la nueva máquina de estado. En el guión Árboles de animación, necesitaremos una referencia
a la reproducción del estado hit. Además, dado que actualizamos
el formato del árbol, necesitaremos actualizar todas estas rutas
de propiedad. Ahora accederemos
al nodo blend obteniendo el nodo hit, luego el nodo blend tree, y finalmente, el nodo blend two inferior
más superior. Dando una definición a la
función get hit, podemos recibir el parámetro
booleano como si el personaje
está recibiendo o no un golpe ligero Después dígale
al estado de golpe que viaje ya sea al golpe A si fueron golpeados a la ligera o golpe B si fueron golpeados más fuerte. Vamos a probarlo. Si
golpeamos el esqueleto, reaccionan al ser golpeados a la ligera, equipando un hacha y
atacándolos de nuevo. Ellos son golpeados más fuerte. Un
tercer golpe y mueren, cayendo hacia atrás ya que
fueron golpeados desde el frente. Podemos equipar el gran hacha, que he configurado para
tener un daño de cinco y matar a otro
esqueleto por detrás, y caen
hacia adelante a medida que mueren. También sería
bueno poder
rastrear la salud del personaje del jugador en la interfaz de usuario. Agreguemos un nodo de control
y lo llamemos medidor de salud. Lo voy a poner detrás de
todo lo demás en la interfaz de usuario. Esto necesitará un texto
directo para dibujar el borde, un color erecto como relleno, y otro texto directo
si queremos un icono Voy a usar el marco deslizador delgado
como la imagen del borde. Es muy grande, así que la
escalaré a una
cuarta parte de su tamaño. Y voy a usar icono, pequeño corazón lleno para el icono. Redimensiónelo y colóquelo donde se vea bien en
relación con el borde Luego estableceré el color para el color ect para que coincida con
el color del corazón, y estableceré su posición y
dimensiones para llenar el calibre. Voy a restablecer su propiedad de tamaño, anclar esto a la esquina
inferior izquierda. Al hacer clic y arrastrar sobre la propiedad
size x del relleno, podemos ver cómo el calibre se puede ajustar
fácilmente a cualquier porcentaje Al adjuntar un script
al medidor de salud, podemos llamarlo medidor para reutilizarlo para cualquier otro
medidor que podamos desear Tomaremos una referencia
al color de relleno ret
usando add on ready, y también declararemos una
variable para mantener el tamaño punto x del relleno cuando
el calibre
esté completamente lleno, que es lo que se establece la propiedad
size dot x cuando
se carga por primera vez. Luego escribe una
función pública llamada set value, aceptando un parámetro de porcentaje
flotante. Todo lo que tenemos que hacer es establecer
la propiedad size x
del color t para que sea el porcentaje multiplicado
por el tamaño máximo. Al conectar la
señal de cambio de salud del
personaje del jugador a la función de valor
establecido de medidores, ahora
rastreará automáticamente la salud del jugador Para probar el medidor de salud. Solo le diré al
personaje que reciba dos daños cada vez que el
jugador presione el botón de correr. Ahora podemos ver que el indicador de
salud del personaje se agota, y el personaje muere
cuando está vacío Luego restableceré la línea de toma
de daños para que vuelva a correr. Ahora tenemos a nuestro
personaje siendo
golpeado y recibiendo daño de los ataques. Y la siguiente lección, vamos a permitir que los personajes eviten
ser golpeados esquivando Te veré en la siguiente lección.
8. sobreexponer/sobreexposicion: Hola, amigos. En
la lección anterior, permitimos que nuestros personajes
fueran golpeados por ataques, sufrieran daños y murieran. En esta lección,
los ayudaremos a evitar daños esquivando. Comencemos en la configuración del
proyecto, la pestaña Mapa de entrada, agregando un
evento de entrada para esquivar Usaré la barra espaciadora o el botón
de la cara derecha de mi mando. En el script del jugador, podemos usar los mismos métodos que jump y attack para amortiguar
la entrada de esquivar. En el guión del personaje,
necesitaremos una variable para saber si el personaje
quiere esquivar o no. Pero un esquivar no es
sólo una simple entrada. También requiere una dirección
como vector tres. En la región de combate, necesitaremos una función de esquivar
y una función de cancelación de esquivar, estableciendo la
variable booleana Y con cualquier entrada en búfer, todas las demás entradas en búfer se
establecerán en false. Como ya estamos almacenando la dirección de entrada en
el guión de caracteres, podemos verificar si ese es el vector 30 en el momento en que se le dijo al
personaje que esquive. Si no da ninguna entrada, quiero que el personaje
esquive hacia atrás. Voy a usar el vector directo de bases de
plataformas de caracteres, multiplicándolo por
uno negativo para Si estamos dando entrada
direccional, quiero que el personaje
esquive en esa dirección, pero siempre con toda su fuerza. Normalizaré la dirección para eliminar la magnitud
de la ecuación. En la máquina de estado de
árbol de animación de personajes, navegando a través de
la muerte y golpear animaciones en el árbol de mezcla, y finalmente, la máquina de estado de
movimiento. Podemos agregar las animaciones de esquivar en un espacio de
mezcla bidimensional. Transición de locomoción a esquivar si el personaje
quiere esquivar, y de vuelta a locomoción al final de
la animación Ambos con un desvanecimiento cruzado. Dado que esto se está conectando
a la locomoción, el esquivar solo se realizará mientras el personaje
esté en el piso También es posible que desee
tener esquivas aéreas conectadas al estado de
salto inactivo Dentro del espacio de mezcla de esquivar, cambiaré el
ajuste de cuadrícula a factores de uno Después agrega las animaciones Dodge adelante, Dodge hacia atrás, Dodge izquierda y Dodge hacia atrás, Dodge izquierda y
esquivar a la derecha
que se
mezclarán para que el personaje pueda esquivar en cualquier dirección. El script del árbol de animación
tendrá que ser capaz de establecer la cantidad de mezcla de este espacio de
mezcla como un vector dos, la misma manera que establecemos
la cantidad
de mezcla de las animaciones bloqueadas en
estrafing De vuelta en el guión del personaje, al decirle al
personaje que esquive, podemos decirle
a la animación que establezca esta cantidad de mezcla. Pero la dirección de esquivar es un vector tres en el espacio global, mientras que la
cantidad de mezcla para la esquiva es un vector dos en el espacio local de las plataformas de
personajes Podemos calcular la cantidad de
mezcla comparando la dirección de esquivar con los vectores de espacios de plataforma
usando un producto de punto. Voy a necesitar invertir
la cantidad de mezcla x multiplicándola por una negativa Si probamos esto,
la animación de esquivar reproduce tres veces y el personaje en realidad no se mueve. La animación se repite
porque
quiere esquivar es cierto por
un segundo completo, pero la animación tiene
sólo 0.4 segundos de duración. Por lo que se repetirá tantas veces como pueda
hasta que la variable quiere esquivar se ajuste de nuevo a false antes de que el 1 segundo esté arriba. Tendremos que establecer
la variable false una vez que la esquiva se
haya realizado con éxito y también aplicar algo de velocidad para
mover al personaje. Añadiendo otra función, al
igual que aplicar velocidad de salto, aplicaremos dodge velocity y llamaremos a esta función
desde la animación. Si se llama a esta función, el carácter ha esquivado
con éxito, y podemos establecer la
variable en false para
evitar que se produzcan más esquivas desde una sola entrada Después estableceremos la velocidad del
personaje para que sea la dirección de esquivar
multiplicada por la fuerza Dodge. Esto creará un
impulso repentino de velocidad, moviendo al personaje rápidamente
en la dirección en la
que están esquivando Crear otra variable
exportada para la fuerza de esquivar del personaje. Lo pondré en ocho. También puede querer que nuestro esquivar
tenga marcos oculares, abreviatura de marcos de invencibilidad Esta es una duración de tiempo en
la que el personaje no puede
ser perjudicado por ataques Así como tenemos una
función llamada por nuestras animaciones de ataque para
activar o desactivar la caja de cadera, también
tendremos una
función llamada por las animaciones de esquivar para activar y desactivar
la caja Hurt. Deberíamos usar set deferred para establecer la
propiedad monitoreable de la caja Hurt al
valor de active
en caso de que esto ocurra
durante un evento Ya que es posible que
queramos llamar a esta
función como resultado de
una colisión y no podamos encender o apagar los colisionadores mientras se
están procesando En las animaciones de personajes, necesitaremos agregar pistas de llamadas a
funciones a cada una de nuestras animaciones de
esquivar personajes. Primero apagaré la caja Hurt del
personaje. Entonces cuando el
personaje parezca que empieza a moverse
en la animación, voy a aplicar la velocidad de esquivar. Una vez que hayan tenido tiempo para la velocidad de Dodge mueva
al personaje fuera
del camino del ataque, volveré a encender la caja de HRT cambiando el
argumento a true Después repitiendo el
mismo conjunto de
llamadas de función para cada una de las animaciones de
esquivar. Si bien no debería suceder con este código tal como está actualmente, podría ser posible
que el personaje interrumpa mientras esquiva, lo que significa que el het box podría
nunca ser reactivado Dependiendo de cómo funcione
el juego, es posible que desee
incluir
la activación de la caja del personaje en
las acciones de interrupción. Ahora que se está aplicando la
velocidad de esquivar, realmente no
me gusta cómo
la animación de esquivar mueve
realmente la posición raíz de las
plataformas del personaje, lo que resulta en algunos movimientos
abruptos, tanto conduciendo como
saliendo del Entonces abriendo las animaciones, eliminaré los fotogramas clave raíz de las animaciones de esquivar. Mantener la plataforma de personajes
arraigada donde el personaje debe estar según lo determinado por
la física del cuerpo del personaje. Y luego repetiré esto también para las otras
animaciones de esquivar. Ejecutando el juego, podemos
ver el árbol de escenas remotas, encontrar la caja rt del personaje y prestar atención a la propiedad
monitoreable Esquivar establece la
propiedad monitoreable en false, luego la restablece a true, y el personaje anima la esquiva más suavemente con
la velocidad gracias a la
eliminación de
los fotogramas clave raíz Con el esquivar ahora animando
y funcionando correctamente, consideremos ahora
si queremos permitir que el personaje ataque y
esquive al mismo tiempo Además, ¿se debe
permitir que el
personaje ataque o esquive
si está siendo golpeado? Si no queremos
permitir este comportamiento, tendremos que rastrear
cuándo el personaje está atacando, esquivando
o siendo golpeado Vamos a agregar algunas variables
booleanas más a nuestro script de personajes que
está atacando, es esquivando y
es Todos estos deberán exportarse
para que sean accesibles al nodo del reproductor de
animación. Usando pistas de propiedad, las animaciones de
hit pueden establecer la variable is hit en
true al inicio
de la animación. Y volvamos a falso al final. Después en el árbol de animación, al hacer la transición de
la locomoción a la esquiva, podemos verificar para asegurarnos de
que el personaje quiera esquivar y nada es golpeado,
y nada está atacando . Antes de pasar
a cualquier estado de ataque, podemos comprobar no sólo si el
personaje quiere atacar, sino también si no son
golpeados y no esquivando Luego podemos repetir el
proceso de establecer
las variables booleanas en
las animaciones de esquivar Cada uno que establece la variable
está esquivando a true al inicio
y false al final Nuevamente, con cada animación de
ataque, establecer la
variable is attack a true
al inicio de las
animaciones de ataque y cae al final. En caso de que se interrumpan ataques o
esquivas, también
deberíamos volver a establecer estas
variables en false También existe la posibilidad de el personaje muera
interrumpiendo la exitosa animación Así que vamos a establecer la
variable is hit en false aquí. Para que la
variable está atacando sea establecida por la máquina de estado de
acción, también necesitaremos
habilitar el filtro para ella y también la posición del
hit box. Para probar si el
esquivar realmente está funcionando, necesitaremos que los enemigos comiencen
a atacar. Si aún no has configurado las animaciones de ataque
enemigo, una manera fácil de hacerlo es copiar
al jugador de animación de personajes y pegarlo en
la escena enemiga. Entonces podemos decirle
al árbol de animación que use el nuevo reproductor de animación. Y mientras el enemigo tenga la
misma estructura ósea que el personaje, todas
las animaciones funcionarán igual. De lo contrario, deberás
configurar al enemigo para que tenga al menos un ataque capaz
de activar una caja de cadera, enmascarando la caja t del personaje. Para hacer el ataque del enemigo, solo les
voy
a adjuntar un nodo en blanco en la escena de nivel. Con un guión sencillo,
diciéndoles que ataquen. Haré una nueva carpeta para guiones
enemigos y la
llamaré ataque. Después de agarrar una referencia
al personaje como
padre de este nodo, le
diré al personaje que
ataque en la función ready Dado que la variable
nunca volverá a ser falsa,
esto es todo lo que se requiere para que los enemigos
realicen ataques sin cesar Intentemos ejecutar el juego con formas visibles de
colisión encendidas. Y ver el árbol de
escenas remoto donde
podemos ver los valores de
todas nuestras nuevas variables. El personaje esperará a que termine
un ataque antes de realizar una esquiva
y viceversa. Si dejamos que el esqueleto
golpee al personaje, reciben daño y no pueden atacar o esquivar hasta que termine la animación de
golpe. Y podemos esquivar el ataque del
esqueleto con nuestra nueva acción esquivadora Ahora tenemos a nuestro personaje
esquivando para evadir ataques y restringiendo
cuándo el personaje puede realizar En la siguiente lección, permitiremos que los personajes bloqueen
los ataques entrantes con un escudo. Te veré en la siguiente lección.
9. Bloque: Hola, amigos. En
la lección anterior, ayudamos a nuestros personajes a evitar recibir daños
esquivando ataques En esta lección,
les permitiremos bloquear ataques
con un escudo. Comencemos en la configuración del
proyecto, la pestaña Mapa de entrada y agreguemos un
evento de entrada para bloquear. Usaré el botón derecho del ratón y el
botón del hombro izquierdo en mi mando. En el guión del jugador,
el botón de bloqueo no necesita ser búfer, ya que se comporta más
como el botón de ejecución, cambiando el comportamiento del
personaje mientras se mantiene pulsado el botón Enviar una señal al personaje
para bloquear o no, en
función de si
se presiona o suelta el botón. El script de caracteres puede entonces almacenar este valor en una variable. Quiere bloquear. Pero a diferencia
de las otras variables, no
hay necesidad real de almacenar en
búfer la entrada de bloqueo. Después agrega una función en la sección de combate que
establece esta variable. En el
árbol de animación de personajes máquina de estado navegando a la máquina de estado de
acción. Podemos agregar la
animación de bloques y hacer la transición a ella si el personaje quiere bloquear con un corto fundido cruzado. Después la transición de nuevo a si no
quieren bloquear. Al obtener una visión del personaje y fusionarse en
el estado de acción, esta animación hace que
el personaje
levante su escudo. Una vez que se completa esta animación, podemos hacer
la transición a la animación de bloqueo, que debe establecerse en bucle
para mantener el escudo alto siempre el jugador mantenga presionado
el botón de bloqueo. Esto también volverá a inactivo si el personaje ya
no quiere bloquear con un corto fundido cruzado. También podríamos querer
poder hacer la transición a la animación de bloques desde algunos
de nuestros otros estados inactivos,
como los estados inactivos desarmados y de
una mano Para mantener el número de
transiciones más bajo, primero
combinaré los estados inactivo
y inactivo de una mano combinando lógicamente las condiciones de
transición para alcanzar el estado de ataque
con una mano Si la animación de ataque es una, quieren atacar y
no son golpeados y no esquivando Después, regresa al ralentí al
final de la animación de ataque. Eliminando el estado inactivo de una
mano, luego
reorganizaré
los otros estados para que estén un poco más organizados Ahora, ya sea un
ídolo inactivo o desarmado puede pasar a bloquear, si el personaje quiere bloquear, y hacer la transición directamente de
nuevo a desarmado, si la
animación de ataque del personaje es cero, y o bien tienen un
objetivo o quieren atacar, y no quieren Con una prioridad de cero. Ahora bien, ya sea inactivo o inactivo
desarmado puede pasar a bloquear si el
personaje quiere bloquear Los estados de bloqueo y bloqueo
pueden saltar inactivo y regresar directamente a inactivo desarmado
con una prioridad de cero De esta manera, el personaje
no tiene que pasar por dos estados de inactividad diferentes
entre el bloqueo y el ataque. Si lo probamos, nuestro personaje puede hacer la transición a
la animación de bloque al presionar el botón de
bloqueo y volver a estar inactivo cuando se suelta el
botón de bloqueo. Pero tendría más sentido restringir
al personaje para que solo use esta animación si tienen un escudo equipado. Para ello,
necesitaremos otro script de
recursos. Heredando del equipo, dándole un
nombre de clase de escudo Si quieres que tus escudos tengan diferentes variables,
podemos definirlos aquí. Agreguemos una variable por la
cantidad de daño reducido al bloquear con este escudo
con un valor predeterminado de uno. Acceder al recurso personalizado de
escudos redondos bárbaros. Podemos cambiarlo para que sea un escudo y cambiar la
cantidad de reducción de daño si queremos. Recuerde repoblar
las propiedades que se restablecen como resultado
de este cambio de clase, y actualice todos los escudos para
usar el nuevo script de clase En la escena del escudo, tendremos que poder
almacenar las variables
del recurso de objeto en el escudo tal como hicimos
con el arma. Añadiendo un nuevo script,
solo tendrá una variable entera de
reducción de daño y una función ficticio activar
hip box, que ignorará el
argumento booleano y Quedará claro por qué esto
es necesario en un minuto. Entonces podemos reemplazar el guión adjunto a nuestro escudo
por el nuevo. En el guión del personaje, agreguemos otra variable a la categoría de equipo
para saber si el personaje tiene o no
un escudo equipado. Al ponerse una
pieza de equipo, si el objeto es un escudo, entonces lo configuraremos para que sea
el equipo fuera de mano, pasaremos el valor de
reducción
de daño del recurso del objeto
al escudo, y set tiene escudo
equipado a true Dado que la variable off hand ahora sostiene un escudo
en lugar de un arma, interrumpir las acciones del
personaje desactivará todas las cajas de cadera Y como el off
hand no es nulo, le
estamos diciendo que
desactive su caja de cadera Pero le hemos dicho al escudo
que haga caso omiso de esta petición. Entonces al quitarse una
pieza de equipo, si el socket es el offhand, entonces podemos suponer
que el personaje ya no sostiene
un Entonces al decirle al
personaje que bloquee, podemos agregar la condición de que el personaje también debe
tener un escudo equipado. El guión de inventario también
necesitará algunas condiciones más a la hora de
equipar un escudo también para evitar que el personaje
equipe un escudo cuando su mano fuera ya está ocupada con un arma a dos manos
o fuera de la mano Este proceso
variará dependiendo cómo funcionen sus sistemas de inventario y
equipos. Si el
elemento seleccionado es un escudo, y el personaje tiene algo equipado en su mano principal, y el personaje actualmente
está usando las animaciones de dos manos o de
doble rueda, Entonces desequiparé la toma de mano
principal y le diré al personaje que dof el equipo en
su mano principal Si lo probamos. Ahora
se ignora el botón de bloqueo si el personaje no tiene un equipo de escudo. Podemos equipar un arma a dos
manos, luego equipar el escudo. El arma a dos manos se
desequipa automáticamente, y luego se equipa el escudo Y ahora el personaje puede
bloquear con el escudo. A continuación, consideremos cómo funciona
la entrada de bloqueo
con nuestras otras acciones. Si el jugador está bloqueando y decide
atacar o esquivar, entonces me gustaría que
esas acciones tomen prioridad interrumpiendo el bloqueo Pero si solo establecemos la variable wants
to block en false, entonces el jugador
tendrá que soltar el botón de bloqueo y
volver a presionarlo para continuar bloqueando. En su lugar, podemos declarar
otra variable booleana. Vamos a llamarlo bloque de interrupción. Si el personaje
quiere atacar o esquivar, entonces esta variable se
puede establecer como verdadera. Y cuando termine el ataque
o esquivar, podemos volver
a establecerlo en falso para permitir que el personaje continúe
bloqueando automáticamente. Simplificaré la función add
dodge velocity para simplemente llamar cancel dodge. Después en el árbol de animación, podemos agregar las condiciones
para la transición fuera del bloque o el bloqueo para incluir si el
bloque está siendo interrumpido. Y no permitir que las
transiciones vuelvan a
bloquearse hasta que el bloque
ya no esté siendo interrumpido. Ahora el personaje
dejará de bloquear mientras ataca
y automáticamente volverá al bloqueo siempre y cuando el botón de bloqueo
siga presionado. Y lo mismo también
funciona para esquivar. Lo último que tenemos que
hacer es reducir en realidad el daño de
los ataques entrantes mientras se bloquea. Para ello, necesitaremos saber si el personaje está bloqueando. Dado que el bloqueo no se limita a una sola animación y
los bucles de animación, no
hay forma de que
podamos simplemente decirle al animador que establezca una
variable booleana en true o false Vamos a agregar la animación de
golpe de bloque. Habilitando la transición
a esta animación de bloquear y regresar
al final de la animación. Lo que contratamos para saber
si el personaje está bloqueando es en qué estado se encuentra actualmente
esta máquina de estado. Si está en el estado de
bloqueo o golpe de bloque, entonces el
escudo del personaje está arriba. La animación de bloques también
es bastante larga. Incluye no sólo
levantar el escudo, sino también un ciclo de animación de
bloqueo. No creo que
se deba considerar que el personaje bloqueando hasta después de que el
escudo esté completamente levantado, pero tampoco quiero esperar a que termine la animación
de
bloques. Entonces, en el reproductor de
animación del personaje, voy a reducir la longitud de la animación de
bloque para que se detenga después de que el escudo se levante
a un tercio de segundo. En el script de árboles de animación, agreguemos una
función pública para verificar si el carácter está bloqueando,
devolviendo un booleano Primero, almacenar el
nombre de los
estados de acción nodo actual
en una variable de cadena. Podemos regresar si es
bloqueo o golpe de bloqueo. Y también necesitaremos
otra función para reproducir la animación de golpe de bloque, diciéndole al estado de acción que viaje al estado de golpe de bloque. Después en el guión del personaje, en la parte superior de la función
take damage. Podemos comprobar si la animación del
personaje está bloqueando actualmente, y que la dirección de
la que proviene el daño
es el frente del personaje. Usando un producto de punto de la dirección del daño con el vector base de plataformas de caracteres
hacia adelante Si el valor es un número
positivo, entonces el daño viene de algún lugar frente a ellos. Sin embargo, esto cubriría
un
gran ángulo, una media esfera completa
frente al personaje. Usando algo más cercano
a un cuarto o medio, podemos limitarlo a una forma de cono. En estas
condiciones, el ataque debe ser bloqueado con éxito, reduciendo la cantidad de daño por la reducción
de daño del escudo. Usando la función max para
limitarlo a un mínimo de cero. Entonces podemos decirle
al árbol de animación que reproduzca la animación de golpe de bloque, y si la cantidad de daño
se ha reducido completamente a cero, solo
regresaré ya que el personaje no está
recibiendo ningún daño. Vamos a probarlo.
Equipando el escudo y bloqueando el ataque del
esqueleto El daño se reduce a cero y se reproduce la
animación de golpe de bloque. Al recibir daño desde
el costado o la espalda, el personaje aún
recibe daño. Ahora tenemos a nuestro
personaje capaz bloquear ataques con un
escudo desde el frente. En la siguiente lección, les
daremos un arma a distancia que
pueda disparar proyectiles Te veré en la siguiente lección.
10. Rodaje: Hola, amigos. En
la lección anterior, permitimos que nuestro personaje
bloqueara ataques con un escudo. En esta lección, les daremos arma
arreglada capaz
de disparar proyectiles Este paquete de activos no contiene
un perno para la ballesta, así que comenzaré haciendo
uno en la escena de la ballesta Comenzando con un cuerpo
rígido de tres
nodos D , renombrándolo perno Lo colocaré
donde descansará la base
del cerrojo
dentro de la ballesta con su vector base z azul apuntando hacia adelante donde
estará disparando A continuación, voy a añadir una instancia de malla
tres nodo D como hijo, poblándolo con
la malla del cilindro Reduciendo el radio y la altura, girándolo para apuntar hacia adelante y posicionarlo
hacia adelante a lo largo del eje z. Sólo le daré
un material básico
y pondré el albedo
para que sea de color marrón Después agregue un
nodo básico de tres D como otro hijo, por lo que se colocará con
la misma posición y
rotación y renombrarlo amo socket. Entonces reparent amo socket a la ballesta conservando esta
posición y rotación Reparar el perno
al zócalo amo, por lo que su posición y rotación relación con su
padre ahora es cero El cerrojo ahora se puede
convertir en su propia escena, que pondré en una nueva
carpeta para proyectiles, y luego lo eliminaré de la escena de
la ballesta La ballesta ahora
se puede cargar simplemente agregando un cerrojo como
hijo de este nodo El perno necesitará
una forma de colisión. Voy a usar una cápsula con las mismas dimensiones y
posición que el cilindro. Ampliando la sección del solucionador, necesitaré tener habilitado el monitor de
contactos y establecer los contactos máximos en
algo mayor que cero Si queremos que el cerrojo
colisione con el terreno, necesitará enmascarar la capa de
colisión uno Y quiero que mis tornillos se muevan lentamente para poder
ver lo que están haciendo. Pero no quiero que
caigan por gravedad. Entonces pondré su escala de
gravedad a cero. Adjuntando un script al perno, podemos nombrarlo proyectil, por lo que puede ser utilizado para otro
tipo de proyectiles en
nuestro juego y guardarlo en la carpeta de scripts de elementos Tan pronto como
se instancie un cerrojo,
se cargará
en la Y es posible que queramos
pasar información del personaje o arma a las municiones en este momento. Vamos a crear una
función pública para hacer eso. Pero por ahora, solo pondremos verdad
su propiedad
de congelación ya que el cuerpo rígido
no necesita hacer nada hasta después de que se dispare
el arma. Para disparar el proyectil, aplicaremos una fuerza de impulso enviada por el arma
como vector tres En este momento, el cuerpo
rígido puede comenzar aplicar física para mover el
perno a través de la escena del juego, estableciendo su
propiedad de congelación en false. Ya no queremos que el
proyectil siga
las propiedades de transformación de
su padre, la ballesta Debe volver a ser apaciguada a la escena del juego donde
pueda moverse y actuar libremente En caso de que no esté
apuntando directamente hacia la dirección,
se está disparando, podemos decirle al cerrojo que
mire un punto en el espacio que es su propia posición global menos la dirección
de la fuerza de impulso. Después aplique la fuerza de impulso
al perno para que se mueva
en esa dirección. Conectando la
señal ingresada del
cuerpo rígido al guión, se llamará a
esta función
si el cerrojo hace contacto con algo en la
capa de colisión uno, el terreno. Si eso sucede, el cerrojo puede permanecer exactamente donde
hizo contacto, estableciendo su
propiedad de congelación de nuevo en true, pero diferido ya que esto
sucede durante una colisión Es muy importante que
cada vez que implemente una función en un juego que instancie una gran
cantidad de nodos, que también implemente alguna
forma de limpiarlos. De lo contrario, podrías terminar
con cantidades muy grandes que
hacen que las velocidades de fotogramas bajen y
eventualmente bloqueen tu juego. Una práctica común
con los proyectiles es solo darles
una vida útil máxima Vamos a agregar un nodo de tiempo a nuestros proyectiles y configurarlo
para que cuente atrás una Lo pondré a 10 segundos. Luego toma una referencia a la hora o nodo
usando add on ready. Iniciaremos el temporizador
al disparar el proyectil. Si no termina
golpeando nada, todavía
queremos limpiarlo, que no se limite a volar
a la distancia para siempre. Conexión de la señal de tiempo arriba
a la secuencia de comandos del proyectil. Señalará que el proyectil se libere de la escena del juego De vuelta a la escena de la ballesta, necesitaremos un nuevo guión
para esta arma Podemos nombrarlo arma a distancia
y ponerla en la carpeta de scripts de
elementos Sustituir el guión que se
adjunta a esta arma por arma a distancia y darle una referencia al archivo de
recursos personalizado para la ballesta Podemos exportar la munición
como una escena empaquetada, una prefabricada que podemos usar como plano para instanciar tantas
como necesitemos Después asigne el cerrojo como munición para la
ballesta en el inspector Necesitaremos una referencia a
la toma de munición usando at on ready y una referencia a la munición que actualmente está cargada en el arma a distancia También podría ser bueno
tener una bonificación de daño que el arma agregará a los disparos que se
le disparen como un entero. La cantidad de
fuerza de impulso que el arma aplica a su munición cuando
se dispara a flote Usaré un número bajo
como diez para que
podamos ver los pernos moviéndose
por el aire fácilmente, y la máscara de colisión de nuestros
enemigos para que la información pueda pasar del personaje th el arma a la munición. Al equipar el arma, personajes están
configurando la caja de cadera, máscara de
colisión de armas, por lo que podemos reutilizar fácilmente la misma función para
establecer la variable máscara Y al igual que hicimos
con el escudo, podemos agregar una función para
activar la caja de cadera, ignorando este parámetro,
y simplemente regresar Ya que el arma
no tiene caja de cadera propia. El arma
necesitará poder disparar el proyectil
con una función pública, y dejaremos que el
personaje especifique la dirección en
la que
quiere que vaya el proyectil como parámetro Todo lo que el arma
necesita hacer es pasar esta llamada de función
al amo,
multiplicando la dirección
por la fuerza armamentista Después establece la referencia
amo cargada null ya que el arma ya no
está cargada, y una función de recarga, que instanciará
un nuevo perno, asignándolo Después agrégalo como niño
del zócalo amo, dándole la posición
correcta y rotación requerida para que se asiente
bien en la ballesta Entonces podremos pasar cualquier información
que la munición necesite
saber antes de que se dispare, como el daño de las armas
y la máscara de colisión. Entonces, sigamos adelante
y agreguemos estos como parámetros a la función de
onload en el script del proyectil Nuestro guión de personaje
necesitará una variable para saber si el arma que
tienen está cargada actualmente. Y dos nuevas funciones,
recargar y disparar. Recargar, solo establecerá
la variable en true,
y luego le dirá al arma de
mano principal que se recargue Por ahora, disparar solo
establecerá la variable en false,
luego le dirá
al arma principal que dispare en una dirección, pasando las plataformas de personajes
hacia adelante vector base Si el arma no está equipada, ya que se está
retirando completamente del árbol de escenas, también se
retirará
la munición junto con Así que voy a resetear el arma se carga variable de nuevo a
falso en este punto. Nuestra enumeración de tipos de armas, necesitaremos dos entradas más para el rango de ataques con una mano, que será el número cuatro, y los ataques de alcance a
dos manos es el número cinco En el recurso
personalizado ballestas, voy a cambiar el guión
de equipo a arma Cambiaré su
tipo de arma al alcance de una mano, bajaré su daño y
volveré a poblar su icono Y de igual manera cambiar la ballesta pesada
a rango de dos manos En el árbol de
animación de personajes, necesitaremos más acciones
para los ataques de rango. Esta máquina de estado ya se está volviendo bastante grande y desordenada, así que envolveré los ataques de alcance dentro de otra máquina de estado Al hacer la transición a
esta máquina de estado, si la
animación de ataque de los personajes es de
cuatro o cinco, y quieren atacar, y no son golpeados
y no esquivando Después vuelve al ralentí
al final de la animación. Y voy a mezclar ambas transiciones
con un poco de fundido cruzado. Dentro del rango para
atacar la máquina de estado, podemos agregar animaciones para
disparar y recargar. Tanto para ataques a distancia con una mano como a
dos manos. Solo necesitamos jugar el
correcto una vez y luego salir de nuevo a la máquina de estado de
acción. Entonces todos harán la
transición al final. Las transiciones a una mano
requerirán que la
animación de ataque se establezca en cuatro. Y a dos manos establecido a f. si el tiro
o recargar animaciones jugar se basará en el
valor de arma se carga Ahora que las animaciones pueden ser reproducidas por el árbol de animación, necesitamos las animaciones para
llamar a funciones en el guión del
personaje. Durante la animación de disparo, agregaremos un método llamado track and scrub al fotograma antes de que
el personaje retroceda
del proyectil que se está disparando Luego agrega un fotograma clave para
llamar a la función de disparo. Asimismo, durante la animación de
recarga, intentaremos
seleccionar un fotograma cuando el personaje haya terminado de
recargar el arma Y agrega un fotograma clave a la pista del método de llamada para recargar
realmente el arma Si queremos que estas
animaciones bloqueen
al personaje para que
no pueda realizar otras acciones, tendremos que establecer
una variable booleana como hicimos con los ataques Sólo voy a reutilizar la variable está
atacando. Y repita
también para las animaciones
a distancia a dos manos . Vamos a probarlo. Podemos equipar la ballesta
al personaje, y presionando el botón de
ataque una vez, haremos que carguen la
ballesta con un perno Al presionar el
botón de ataque por segunda vez, disparan la ballesta hacia adelante, y el cerrojo dispara hasta
que golpea algo
en el ambiente, donde se detiene y
se destruye después de 10 Ahora necesitamos los tornillos para
infligir daño a los enemigos. De vuelta en la escena del cerrojo,
necesitaremos agregar una
caja de impacto al perno. La caja de impactos necesita
una forma de colisión. Voy a usar la esfera. Lo colocaré en
el otro extremo
del perno y le daré
un radio menor. Al igual que nuestras otras cajas de cadera, no
necesita estar monitoreando ni tener una máscara de colisión todavía. Agarrando una referencia a la caja de
cadera usando en listo, también
exportemos una variable
para el daño de los pernos. Voy a usar un valor predeterminado de uno. Cuando el personaje carga
el cerrojo en la ballesta, esa sería una buena oportunidad para transmitir información, como cualquier bono de daño
y la máscara de colisión La bonificación de daño de armas se
puede agregar al daño de
los pernos, y la capa de
colisión de la caja de cadera
se puede establecer en la capa de colisión
enemiga del personaje. Cuando se dispara el proyectil, podemos decirle a la caja de cadera que comience a monitorear cajas de rebaño enemigas. Conectando el área de la caja de cadera ingresó la señal al guión del
proyectil Podemos decirle a la caja Hurt
que este proyectil impactó para decirle a su
personaje padre que reciba daño. Desde la dirección de las cajas
Hurt posición global menos la
posición global de Bolt normalizada. El perno puede ser entonces para ser
removido de la escena. Y si el cerrojo golpea el terreno, ya no debería estar
monitoreando para infligir daño, así que lo pondremos en
falso diferido En el guión del personaje,
me gustaría asegurarme
absolutamente de que cuando el personaje está
bloqueado en un objetivo, el proyectil se dispara
directamente contra ese objetivo Por lo que la función disparar
se dividirá en dos comportamientos diferentes en función si el personaje
está bloqueado o no en un objetivo, llamando
a una función separada para disparar a un objetivo, pasando el objetivo
como argumento. Pero el arma solo
debería disparar al objetivo
de encierro si el
personaje se enfrenta a ellos. Así podemos verificar si
el producto punto
del carácter rigs
forward basis vector y la diferencia normalizada en sus posiciones globales
es un número positivo Cuanto más cerca de lo
positivo es esto, cuanto más similares son, más se
enfrenta el personaje hacia ellos. Diré que algo más grande que 0.75 está lo suficientemente cerca como para disparar
al objetivo del encierro. En el guión de arma a distancia, dando una definición a disparar al
objetivo, aceptando un objetivo
como parámetro Ahora podemos calcular la
dirección como la diferencia de posiciones de gulple normalizada
y multiplicada por la fuerza Dado que esto utilizará la posición de gubal de
armas,
no la posición de
gubal del personaje, la dirección
será más precisa Y voy a sumar 1 metro hasta la posición del objetivo para
no apuntar a sus pies. Vamos a probarlo.
Equipando un arma a distancia
y bloqueando un objetivo, primero
me
enfrentaré a un lado,
y el proyectil
aún dispara hacia adelante, ya que el personaje
no está mirando hacia el Moviéndose para enfrentar al objetivo
y disparar un segundo perno, esta vez dispara directamente al objetivo e inflige daño. Ahora tenemos proyectiles
disparados desde armas a distancia, golpeando a los enemigos o En la siguiente lección, permitiremos a
los enemigos detectar
jugadores y contraatacar. Te veré en la siguiente lección.
11. Enemigo: Hola, amigos. En
la lección anterior, agregamos ataques de alcance
que disparan proyectiles En esta lección,
permitiremos que los enemigos detecten, persigan y ataquen al personaje
del jugador. En la escena del cementerio, agregamos un simple
nodo que le dice al enemigo que ataque constantemente Eliminemos eso
y comencemos a construir una versión más compleja para
atacar solo cuando el personaje del jugador
esté en rango para ser golpeado. En la escena de esbirros esqueleto, le
agregaremos un nodo hijo de tipo nodo tres D, ya que necesitará acceder a tres posiciones D y rotaciones Voy a llamarlo agresión. Después agrega un nodo D de área tres, que representará el alcance de ataque del
enemigo. Le daré
forma de colisión y usaré una esfera. Ajustando el tamaño de la
esfera para que sea un poco más grande, le
daré un
radio de 1 metro, luego la colocaré para que quede 1 metro arriba del suelo
y 1 metro adelante. El área de alcance de ataque
estará monitoreando las colisiones que enmascaren
la caja del rebaño del jugador. L et's adjuntan un script a este nodo y lo ponen en
la carpeta de scripts enemigos. Dado que el propósito de este
script es controlar
un personaje al igual que el nodo del controlador de entrada
del jugador, necesitaremos una referencia
al personaje que está siendo controlado por este nodo Con la forma en que estoy estructurando
mi árbol de escenas, este nodo siempre será el hijo directo
del nodo de carácter, para que pueda acceder al personaje
llamando a get parent. Conectando las señales de
área ingresada y área de
salida al script, renombraré los parámetros y les daré tipos para mayor claridad Cuando los personajes del jugador Herir caja entra en
el rango de ataque, queremos decirle al
enemigo que ataque. Y cuando la caja Hert
salga del rango de ataque, podemos decirle al
enemigo que no ataque Podemos guardar esta rama como escena
propia y guardarla
en la carpeta de escenas enemigas. Entonces elimínelo de
esta escena enemiga. E De vuelta en la escena del cementerio, podemos unir nuestro
nodo de agresión
enemiga a cualquiera o a todos
nuestros enemigos para que ataquen
automáticamente al personaje
del jugador si
entran en el rango de ataque Vamos a probarlo. Los enemigos aún no
están atacando, pero atacaremos si entramos en su rango de ataque y nos
detenemos cuando lo dejamos. A continuación, permitiremos que
los enemigos vean
al personaje del jugador
desde una distancia adicional. Al abrir la escena del nodo de
agresión, podemos agregar otra área tres nodo D para representar la visión de
un enemigo. Añadiendo una
forma de colisión a esta escena, usaré otra esfera
con un radio mucho mayor. Utilizaré 5 metros y lo colocaré para estar por delante
del enemigo y un
poco arriba del piso. Esta área puede estar monitoreando la capa de
colisión del personaje del jugador. Voy a usar la capa nueve. Después agregue un rayo fundido tres nodos
D para que sea su línea de visión y también mueva esto
hacia arriba del piso. Esto estará buscando la misma capa que
el campo de visión, pero también ser obstruido
por el terreno Ya que usé la capa nueve, que es el
cuerpo del personaje y no la caja t, conectaré las señales de on body ingresadas y salidas
al guión de agresión Cuando un cuerpo entra
al campo de visión, lo
guardaré en una variable, Vamos a llamarlo objetivo de
tipo personaje cuerpo tres D. Pero también
tendremos que confirmar que también
tienen una línea de
visión clara antes de
volverse agresivos. Entonces necesitaremos una
referencia al elenco. Y podemos almacenar si el enemigo
ha visto
o no al jugador en
una variable booleana Tomemos también ahora también una referencia
al campo de
división del enemigo. A. Montando la función de proceso, podemos comenzar comprobando si se
ha establecido
el valor de target. Si es nulo, entonces el enemigo no puede ver
al personaje del jugador. Deberíamos simplemente
regresar. Si el enemigo aún no
ha visto al jugador, entonces podemos verificar su línea
de visión al objetivo. Establecer la posición objetivo
del raycast para que sea la diferencia en sus posiciones
globales, sumando un metro arriba del
suelo Después de forzar al raycast a
actualizarse si está colisionando con algo y
ese algo con lo que está colisionando
es el objetivo,
entonces la línea de visión
no se ve obstruida Podemos establecer la variable has seen
player en true. Si el valor de esta
variable es verdadero, entonces el
comportamiento del enemigo cambiará, y haremos que persigan al personaje
del jugador. Cuando el personaje jugador sale del campo de visión del enemigo, si el cuerpo es el objetivo, y el enemigo
aún no ha visto al jugador, entonces ya no necesitamos
verificar su línea de visión, para
que podamos establecer objetivo en nulo. Este nodo de agresión es
hijo del nodo de carácter, que no está rotando. Por lo que el campo de visión y alcance de
ataque no rotarán
con la plataforma de personajes. Podemos usar la referencia de
caracteres para agarrar la rotación de la plataforma, acceder a la propiedad y, y asignarla a
esta rotación de nodos y Por lo que seguirá
la misma rotación. También podríamos querer una manera de decirle a este enemigo que deje de perseguir
al personaje del jugador. En cuyo caso, podemos
establecer el target en null, ha visto target a false y decirle a este personaje que
se mueva sin dirección. Un buen momento para llamar a esta función sería cuando muere el enemigo. Así que anulando la función
ready. Podemos conectar la señal de
muerte de este personaje a la función de
parada. Cuando el enemigo ve
por primera vez al personaje del jugador, también
podemos conectar la señal de muerte de los
objetivos a la función de
parada para evitar que el enemigo intente matar al personaje del
jugador después de que ya haya muerto. También usaré esta misma función para apagar la visión de este enemigo, estableciendo su
propiedad de monitoreo en falsa. Para que el enemigo
se mueva hacia el jugador, primero
necesitamos hacer algunos
cambios en nuestra escena de niveles. Vamos a agregar una región de navegación
tres nodo D al nivel. Entonces re padre cualquier nodo
que se utilizará para generar nuestro mapa de navegación
como hijos de este nodo, incluyendo el suelo
y los obstáculos. Con eso hecho, selecciona el nodo de la región de
navegación y rellena la
malla de navegación con una nueva malla de navegación Después haz clic en el botón Hornear malla de
navegación. La malla de navegación cubrirá
el terreno con triángulos que forman un área donde los personajes podrán caminar Ampliando el recurso
de malla de navegación, podemos ver sus propiedades. El único apartado
de preocupación en
estos momentos es la sección de agentes. Los agentes son nuestros
personajes que
usarán esta malla de navegación
para pasear por la escena. Echando un vistazo rápido a nuestras cápsulas de colisión de
personajes, les
he dado una
altura de 2.6 metros y un radio de 0.75 metros. Copiaré esos valores en la altura y el radio de los agentes en el recurso de
medición de navegación, luego volveré a hornear la malla de navegación La malla ahora deja más espacio
de paredes y obstáculos. Para poder utilizar la región de
navegación, todos
nuestros caracteres necesitarán otro nodo adjunto a ellos, un agente de navegación tres nodos D. Asegúrate de adjuntar
uno a cada personaje. Agarrando una referencia a este
nodo usando add on ready. Luego podemos escribir una función
en el script de caracteres, que puede usarse para decirle a
cualquier personaje que navegue
a cualquier ubicación en la malla de
navegación por cualquier motivo. Esto también es muy útil para muchas cosas fuera del combate. Aceptando una posición objetivo
como vector tres, estableceremos la posición objetivo del
agente de navegación para que sea la misma ubicación. El agente de navegación utilizará automáticamente
la malla de navegación, asignada la misma capa de
navegación para producir una ruta para
acercarse lo más posible a la
ubicación de destino. llamar a los agentes obtener la
siguiente posición de ruta, devolveremos el primer punto de camino a lo largo de esta ruta como
un vector tres. Luego podemos restar
la posición global
actual del personaje para obtener un vector apuntando
desde donde
estamos a la primera
posición a lo largo del camino Si multiplicamos esto por 101 para eliminar el componente
vertical, entonces normalizamos este vector. Ahora es funcionalmente equivalente a un
vector de entrada producido por nuestro
script de manejo de entrada del jugador cuando el jugador inclina la palanca analógica o
usa las teclas WASD Así podemos asignar esto a la variable
de dirección de entrada. Y el proceso de física
se encargará del resto, diciéndole al personaje que
camine por este camino, que
los llevará hasta su objetivo. Sería una buena idea trasladar todo lo que le sucede
a un personaje
cuando muere a una
función pública en caso cualquier otra cosa que no sea recibir
daños pueda causarle la muerte. Cuando un personaje muere, debemos decirles que
dejen de moverse. Y cuando se les dice
que se muevan o tomen alguna acción, debemos ignorar esas peticiones si el personaje está
muerto al regresar. De vuelta al guión de agresión, solo
necesitamos
decirle al enemigo que navegue hacia su objetivo
una vez que lo haya visto. Antes de probarlo,
escojamos un enemigo. Voy a usar el guerrero esqueleto y seleccionar su navegación
Agente tres nodo D. En la sección D Bug, haz clic en Activar Toggle para
poder ver el camino
renderizado en el juego. Al acercarse al primer esqueleto, cuanto entramos en
su campo de visión, la línea de visión
confirma de inmediato que pueden vernos, y el agente de navegación encuentra un camino para que el enemigo camine
hacia nosotros. Entonces nos atacan.
Derrotar a este enemigo, esta vez, llamemos
la atención del pícaro Ya que están detrás de
la lápida, no
se confirma
la línea de visión y el enemigo permanece escondido Y si nos acercamos al guerrero, podemos correr alrededor de
la tumba abierta, viendo como el agente de
navegación actualizará automáticamente
la ruta en tiempo real, para recorrer el camino más corto posible para
llegar al jugador. También podríamos querer que nuestros enemigos sean
capaces de empuñar armas De vuelta en la escena del cementerio, vamos a unir otro
nodo básico a uno de nuestros enemigos, y nombrarlo equipar Adjuntando un script a este nodo, lo
pondré en la carpeta de guiones del
enemigo. Todo lo que necesitamos hacer es tomar una
referencia al nodo padre, al personaje, y exportar un arma para equipar
a este personaje. Después en la función listo, dígale
al personaje que haga el arma. Le diré a mi guerrero esqueleto
que equipe un gran hacha. Entonces copia y pega
este nodo sobre otro enemigo y cambia el
arma por otra cosa. Le voy a dar unos cuchillos al pícaro. Cada una de nuestras
escenas enemigas necesitará tener
nodos de unión ósea agregados a ellas. Siguiendo su ranura para mano izquierda y
ranura para mano derecha. Luego podemos poblar el conjunto de
sockets de los equipos de
personajes con estos nodos para ser utilizados
al equipar armas Por último, sería
bueno no tener que recargar el juego cuando morimos Así que vamos a conectar la señal de los personajes
del jugador muerto al guión del manager del
juego. Después de desvanecerse a negro, solo le diré
al árbol de escenas que recargue la escena actual, restableciendo todo de nuevo a cómo era cuando se
cargó la escena Vamos a probarlo.
El guerrero esqueleto está equipado con
la gran a y está utilizando las animaciones de
ataque a dos manos. Cuando morimos, se recarga toda la
escena. Y subiendo esta vez contra
el pícaro, están equipados
con los cuchillos y utilizan animaciones de doble rueda. Ahora tenemos un complejo
sistema de combate en nuestro juego con una variedad de
mecánicas que se pueden ajustar para adaptarse a las
necesidades de tu juego.