Transcription
1. Introduction: combat et les jeux vidéo peuvent sembler intimidants et difficiles à mettre en
œuvre Ce cours vous
fournira tous les outils et
connaissances dont vous aurez besoin pour créer un système de combat évolutif et dynamique dans Gado Nous décomposerons le système de
combat en mécanismes
individuels
et les combinerons pour créer un système de combat
d'action robuste qui pourra être personnalisé
en fonction de vos besoins. Vous apprendrez à combiner des animations de
combat et de mouvement. Synchronisez les zones de frappe
avec les animations d'attaque, intégrez des images oculaires
dans les animations d'esquive, bloquez les ennemis. Lancez des projectiles avec une arme
arrangée
et contrôlez les ennemis à l'aide de scripts
d'IA Si vous avez besoin d'aide, notre serveur
Discord regorge d' autres étudiants et développeurs de
jeux qui peuvent répondre à toutes
vos questions Cliquez sur le lien du site Web
dans mon profil pour m'inscrire. J'utiliserai un projet de démarrage
créé dans la version 4.3 de God qui est disponible sur mon GitHub en utilisant des ressources gratuites
provenant de ce point IO Mais vous pouvez suivre votre propre projet en utilisant
différents actifs. Pour tirer le meilleur parti
de ce cours, vous aurez besoin d'une scène
dans votre projet avec un personnage que le joueur peut contrôler et au moins un ennemi. Vous pouvez également avoir besoin d'un système d' inventaire et d'équipement capable d'équiper les personnages d'une arme et d'un bouclier Pour plus d'informations
sur ces sujets, consultez mon cours précédent. Le combat ne doit pas nécessairement
être une bataille ardue. Dégainons nos armes et
battons-nous ensemble.
2. Configuration: Bonjour, mes amis.
Avant de commencer, vous devriez avoir un projet avec un personnage capable se déplacer dans un environnement et
des ennemis à combattre. Vous pouvez également
avoir besoin d'un menu d'inventaire capable d'équiper des objets, y compris au moins
une arme mala, une arme arrangée et un bouclier Tout au long de ce cours, nous
ajouterons des commandes, des mécanismes et des animations à notre projet
pour fixer une cible,
attaquer, esquiver, bloquer
et tirer des projectiles
3. Verrouillage: Pour notre première leçon, nous allons permettre au joueur
de s'accrocher à un ennemi. Commençons par ajouter un mappage d'entrée pour
activer le verrou Ouvrez les paramètres du projet, passez à l'onglet de la carte d'entrée. Nous pouvons ajouter un
événement d'entrée nommé Toggle Lock. faisant défiler l'écran vers
le bas pour trouver le nouvel événement d'entrée, je vais associer la touche Q clavier et le joystick
droit ma manette à cet Dans le script de
gestion des entrées du joueur, nous aurons besoin de références
au personnage, au bras à ressort et à la caméra, tout configuré avec Add-on Ready. Pendant la fonction de saisie, après avoir vérifié l'absence de pause, ouvert ou fermé
le menu d'inventaire et si le
contrôle du joueur a été désactivé. J'ai divisé le reste
des entrées entre les caméra et les commandes de
personnage pour une meilleure organisation. Actuellement, la seule commande de
caméra consiste faire pivoter le bras à ressort qui maintient la caméra
à l'aide de la souris. Vérifions également si le bouton de
verrouillage a été enfoncé. Il s'agira d'une entrée
contextuelle avec plusieurs fonctions
possibles. Nous devons savoir si le joueur est actuellement bloqué
sur une cible. Déclarons donc une
variable contenant cible actuellement verrouillée sous
la forme d'un nœud en trois D, sorte que n'importe quel objet en trois D notre monde de jeu pourrait
potentiellement être verrouillé. Nous pouvons d'abord diviser
les fonctions
du bouton de verrouillage en
deux catégories possibles, si la valeur de la cible
est nulle ou non, que nous pouvons
raccourcir en deux catégories simples Commençons par le bloc s où le joueur n'est actuellement
bloqué sur rien. Ici, nous devrons
attribuer à la
cible la valeur la
plus proche de la cible visible, et nous pouvons déléguer la
responsabilité de
déterminer quelle est la cible
visible la plus proche de la caméra Dans le cas où
aucune cible visible n'est la plus proche, la cible sera toujours nulle. Dans de nombreux jeux d'action-aventure, lorsque vous appuyez sur le
bouton de verrouillage, il
n'y a rien
à verrouiller. La caméra se réinitialise ensuite pour se
placer derrière le personnage du joueur, ce qui sera fonction
du bras à ressort Si le joueur est
déjà bloqué sur une cible et qu'
il appuie sur
le bouton de verrouillage, plusieurs cas doivent également
être pris en compte. S'il y a plusieurs cibles
visibles, le joueur se fixe sur cible
visible
la plus proche, plus de celle sur laquelle il
est actuellement bloqué Nous pouvons réutiliser
la même fonction de la caméra pour trouver la cible
la plus proche Mais cette fois, fournissez également la cible actuelle
comme argument, et nous allons écrire l'algorithme
pour ignorer cette cible. Dans le cas ci-dessous,
nous pouvons toujours dépasser la cible actuelle puisque
sa valeur est nulle, nous
n'aurons
donc rien à ignorer. S'il n'y a pas plusieurs cibles
visibles, cette fonction renverra également null et le verrouillage
sera désactivé. Qu'
il y ait ou non plusieurs cibles, si le joueur appuie
également sur le bouton enfoncé, la plupart des jeux désactiveront le
verrouillage dans ce cas Nous pouvons déterminer si la
direction d'entrée donnée est similaire à celle du bas en utilisant un
produit scalaire des deux vecteurs et en vérifiant si elle
est supérieure à 0,75 Cela couvrira toutes les
directions proches du bas, mais n'atteindra
pas les diagonales. Nous voulons avoir la
possibilité de désactiver le verrou depuis l'extérieur
du script, il serait
donc judicieux d'en
faire une fonction publique Appelons-le toggle
lock et donnons-lui un paramètre optionnel pour forcer verrouillage avec une valeur
par défaut false La valeur de la cible
sera définie sur null si elle est forcée. Sinon, il peut être réglé sur cible visible
la plus proche,
telle que déterminée par la caméra, ignorant la
cible actuelle s'il y en a une. les trois
cas ci-dessus, il est désormais possible d' appeler Toggle lock
, il suffit spécifier que le verrouillage
est activé dans le cas où
la
direction de saisie vers le bas est également indiquée, et d'autres scripts peuvent également obliger le joueur à le verrouiller pour une raison
ou une autre Passage au script
Spring Arm. Supposons que le joueur appuie sur le bouton de verrouillage, mais qu'aucune cible ne soit visible Nous voulons que le
bras à ressort
positionne la caméra derrière le personnage. Nous aurons donc besoin d'une référence
au personnage auquel le
bras à ressort est attaché, qui dans mon cas
sera toujours le nœud parent
du bras à ressort. Si vous utilisez une structure de nœud
différente, vous pouvez
plutôt
exporter cette variable et définir sa valeur
dans le panneau de l'inspecteur. Pour faire pivoter
progressivement la caméra derrière le personnage au fil du temps, nous utiliserons une
variable d'interpolation de type tween Il serait
judicieux d'exporter
une variable correspondant à la
durée de l'interpolation J'utiliserai un quart
de seconde. Nous pouvons également avoir besoin d'une valeur pour la rotation x préférée afin de réinitialiser la rotation des
bras du ressort à deux. J'utiliserai 0,5 radian négatif, en positionnant la caméra
légèrement au-dessus du personnage, en
regardant vers l' avant et
légèrement vers le bas selon un angle Déclarons également
une variable pour conserver la rotation cible de l'interpolation
sous forme de vecteur trois et initialisons-la en tant
que vecteur trois avec la
rotation x réinitialisée comme valeur x, mais zéro pour les rotations y
et z. donnant
une définition à la fonction, nous pouvons également accepter un
paramètre facultatif pour la durée de l'interpolation en l'utilisant comme valeur par défaut afin
qu'il puisse être remplacé Pour faire pivoter la caméra
derrière le personnage, nous pouvons faire appel à une nouvelle fonction
privée pour ajuster la rotation des
bras du ressort Spécifier que nous voulons que
la rotation y soit la rotation des personnages plus
une demi-rotation représentée par Pi radians Écrivons ensuite
la fonction privée qui interrompt la rotation des bras du
ressort, en
acceptant une rotation cible en tant que valeur flottante,
ainsi qu'une durée
pour l'
interpolation acceptant une rotation cible en tant que valeur flottante,
ainsi qu'une durée
pour l'
interpolation avec une valeur par défaut de la durée
exportée Nous allons commencer par définir
la propriété y de la rotation
cible comme étant la rotation
y cible acceptée
en tant que paramètre. Mais pour que
la rotation
emprunte toujours le chemin le plus court
autour du personnage, nous devons placer sa
valeur de manière à ce qu'elle
soit toujours comprise entre le point de
rotation actuel y moins une demi-rotation et le point de rotation actuel
y plus une demi-rotation. Si un préadolescent
existe déjà et est en cours d'exécution, nous devons le tuer
avant d'en créer un nouveau Nous pouvons ensuite adapter la rotation des bras du
ressort à la rotation cible
sur la durée Laissons ensuite la caméra
détecter les cibles visibles. Ma caméra n'a pas encore de comportement
scripté, alors ajoutons un nouveau script et placons-le dans le dossier des
scripts des joueurs Nous aurons besoin d'une fonction
publique pour obtenir la cible visible la plus proche, acceptant un
paramètre facultatif de la cible actuelle avec
une valeur par défaut nulle, afin que nous puissions éventuellement l'ignorer. Cela renverra un nœud en trois D, et le cas par défaut
sera de renvoyer null si nous ne
trouvons pas de cible visible. Afin de déterminer laquelle des
cibles visibles est la plus proche, nous devons conserver une liste de toutes les cibles visibles. Déclarons une autre
variable contenant
toutes les cibles visibles sous la forme
d'un tableau de nœuds à trois D. Initialisé pour être vide. Un moyen simple de savoir
quelles cibles sont visibles est d'attacher un nœud de zone
3D à la caméra. Appelons cela la plage cible. Cette zone
surveillera tout ce
qui se trouve dans la couche de
collision 11, que j'ai choisie pour
représenter les ennemis. Assurez-vous que la couche de collision
de vos ennemis est définie sur
la même couche que celle
masquée par le verrou lors du ciblage Je devrai également
réinitialiser les zones transformées pour la positionner
à l'origine de la caméra. Le nœud de la zone trois D
a besoin d'une forme de collision, et nous pouvons remplir la ressource de forme
avec un polygone convexe À l'aide d'un polygone convexe, nous pouvons définir la
forme sous la forme d'une pyramide, qui copie exactement le champ de vision de la
caméra, mais avec une portée limitée Comme le
champ de vision de la caméra prendra la forme d'
une pyramide à quatre côtés, nous pouvons le définir avec
cinq points le premier point étant
identique à la position de la caméra. Les quatre autres seront
positionnés le long de l'axe Z, la distance maximale
de notre portée de verrouillage. J'utiliserai une
distance maximale de 15 mètres. Passant à la vue orthogonale supérieure et masquant l'
environnement pendant un moment, je vais simplement
ajuster rapidement la position de
chaque point de la pyramide pour qu'elle corresponde
approximativement au champ de vision de la
caméra, 11,4 mètres à
gauche et à De même, en vue
orthogonale à gauche, ajustant les valeurs y des points de
la pyramide,
6,4 mètres vers le haut et vers Jusqu'à ce que nous ayons une forme de pyramide, correspondant au
champ de vision de la caméra, qui atteint 15 mètres. Je reviendrai ensuite
à la vue en perspective et reparlerai
de la visibilité de l'environnement. Chaque fois qu'un corps entre dans cette zone, reliant le
signal saisi par le corps au script de la caméra, nous pouvons ajouter le corps à notre
gamme de cibles visibles De même, chaque fois qu'un
corps sort de cette zone, il peut être effacé
de la matrice Tout
corps de collision en trois D sur la couche 11, qui existe à l'intérieur de cette zone sera désormais considéré comme
une cible visible. Dans mon script Spring Arm, j'aurai besoin de n'importe quelle balise pour utiliser
la fonction get parent. lançant le jeu et en passant
à l'arborescence des scènes distantes, nous pouvons sélectionner la caméra et afficher ses propriétés
dans l'inspecteur, y compris le tableau
des cibles visibles. Au fur et à mesure que la caméra se
déplace sur
la scène, le tableau des cibles visibles se
met à jour automatiquement pour ajouter et supprimer chaque ennemi lorsqu'il entre dans
le champ de vision ou en sort. Appuyez sur le bouton de verrouillage ne rien
cibler pour l'instant, mais nous pouvons voir comment
cela repositionne la caméra derrière le personnage Avant d'autoriser le
verrouillage d'une cible, nous pouvons également vérifier
si la ligne de
visée du joueur par rapport à la cible est
obstruée par le terrain Ajoutons également un nœud Ray Cast Three D à
la caméra et nommons-le ligne de visée. Ensuite, saisissez-en une référence dans le script de la caméra. Pour trouver la
cible visible la plus proche avec notre caméra, si le réseau est vide, sa taille est nulle, alors il n'y a aucune cible
visible à prendre en compte, et nous
devons simplement revenir. S'il y a
des cibles visibles à prendre en compte, nous devrons comparer
les distances de chacune par rapport à la caméra pour trouver celle
qui est la plus proche. Pour ce faire, nous avons besoin
d'une variable pour maintenir à la distance entre la cible
actuelle flot
la distance entre la cible
actuelle et la caméra La distance la plus proche à flot et l'indice de la cible
visible la plus proche sous forme Nous allons définir la distance la
plus proche sur infinie en utilisant le mot clé I NF, et l'indice le plus proche sur moins un pour indiquer qu'il ne s'agit pas d'
un
index pas d'
un Si, après avoir itéré l'ensemble du tableau de cibles
visibles, l'indice le plus proche est
toujours négatif, alors aucune cible visible n'
a été considérée comme valide et nous devons renvoyer la valeur null Sinon, nous pouvons renvoyer la cible visible à
l'index le plus proche. Si la cible visible à l'indice
I est la cible actuelle, nous pouvons l'ignorer avec
la déclaration continue. Pour toute autre cible visible, nous devrons calculer sa
distance par rapport à la caméra. Nous pouvons utiliser la distance au carré car c'est mathématiquement
plus efficace Si la distance actuelle est inférieure à la distance
la plus proche, nous devrons
vérifier si la ligne de visée de cette
cible est obstruée abord, nous devons réinitialiser Tout d'abord, nous devons réinitialiser la rotation actuelle
de la ligne de visée. Réglez ensuite la position cible
du rayon diffusé sur la position
globale de la cible moins
la position globale de la caméra et
forcez la mise à jour. Mais la position des personnages
est généralement au sol, ce qui est facilement obstrué
par de petits bouts de terrain et n'est pas toujours un bon
indicateur de la ligne de visée Ajoutons également 1 mètre. Si la ligne de visée
entre en collision avec quelque chose et que cet objet
est la cible visible, alors la ligne de visée
n'est obstruée par rien, ce qui fait de cette cible
la cible visible la plus proche que
nous ayons trouvée jusqu' Nous pouvons définir la distance la plus proche par rapport
à la distance actuelle et l'indice le plus proche I avant de passer
au reste du tableau Cela renverra désormais la valeur nulle
ou la
cible visible la plus proche de la caméra La ligne de visée entrera également
en collision avec la couche 11, à la
recherche d'ennemis, mais aussi couche 1 qui sera
obstruée par Il serait également intéressant de faire
savoir au joueur sur quoi il est bloqué grâce à
l'indicateur de cible. Ajoutons un nœud Sprite Three
D en tant qu'enfant du gestionnaire de saisie
du joueur et
renommons-le Pour la texture, je vais utiliser le pointeur vide de la barre de
défilement. Mais modifiez ses
paramètres de saisie pour activer Alpha
prémultiplié afin de le
rendre un peu plus fluide Et réduisez-le
au quart de sa taille. Ensuite, en élargissant la section drapeau, je vais activer son
drapeau d'affichage, afin qu'il soit toujours face
à la caméra Et le drapeau de test sans profondeur attirera toujours le sprite au-dessus tout le reste, quelle que soit sa position dans l'espace tridimensionnel
par rapport à la caméra L'indicateur de cible
peut être invisible par défaut puisque le joueur démarre sans
cible à indiquer. Saisir une référence à l'indicateur cible
en utilisant Add on ready Nous devrons ensuite le
positionner au-dessus de la cible verrouillée. Donc, après avoir déterminé sur
quoi le joueur est bloqué, s'
il y a une cible. Un moyen simple de faire en sorte que l'indicateur
cible suive la cible est de le réparer
en fonction de cette cible. Nous pouvons ensuite le déplacer de quelques
mètres vers le haut pour le positionner au-dessus la tête de la cible et définir sa propriété
visible sur true. S'il n'y a aucune
cible à indiquer, nous pouvons réparer l'indicateur
sur ce nœud et
redéfinir sa propriété de visibilité sur falls pour le
masquer. Essayons-le. Lorsque nous appuyons sur
le bouton de verrouillage, l'ennemi le plus proche est ciblé et l'indicateur est positionné
au-dessus de la tête de la cible En appuyant à nouveau sur le bouton de
verrouillage, passez à l'ennemi le plus
proche Maintenez le bouton de verrouillage enfoncé et appuyez dessus pour désactiver le verrouillage. S'il n'y a qu'
une seule cible visible sur
laquelle nous sommes déjà verrouillés, verrouillage est également désactivé. Dans notre jeu, le joueur
se concentre désormais sur ses ennemis. Dans la leçon suivante, nous allons modifier le comportement de l'appareil photo et du personnage
lorsqu'il est verrouillé. Je te verrai dans la prochaine leçon.
4. Strafe: Bonjour, mes amis. Dans
la leçon précédente, nous avons ajouté un
bouton de verrouillage
contextuel à notre jeu Dans cette leçon, nous allons
modifier le comportement des
nœuds du joueur lorsqu'ils se
bloquent sur une cible. À partir du script du lecteur, une
fois qu'une cible a
été verrouillée, émettons un signal afin
que tout autre script puisse écouter et réagir à la modification de la
valeur de la cible, en spécifiant ce qui était
ciblé en tant que paramètre. À l'aide d'un setter, nous
pouvons émettre le signal chaque fois que la valeur de la cible
est modifiée pour une raison quelconque Désormais, le
personnage, le bras à ressort et la caméra peuvent se
connecter au signal l'utiliser pour définir leurs
propres variables privées pour ce qui est ciblé. Quelle que soit la
valeur de target dans le script de
gestion des entrées du joueur, tous les autres nœuds auront également les mêmes informations, y compris s'ils sont définis sur null. Écrire une fonction simple
pour chacun qui définit une variable cible locale afin qu'ils puissent tous y
accéder facilement. Une fois que notre personnage s'
est fixé sur une cible, nous nous attendons
à ce qu'il fasse face à la cible au lieu de faire face dans la direction dans laquelle il
se déplace. Dans mon script,
la rotation du personnage s'effectue selon un processus physique,
qui indique au
personnage de faire face
dans la
direction dans
laquelle le mouvement est entré. Déclarons une nouvelle variable en
haut du script, qui
veut faire face à la direction sous la forme d'un trois. Et remplacez la direction
d'entrée par want to face direction
dans l'appel de fonction. Ensuite, avant cet appel de fonction, nous pouvons vérifier si le personnage
est verrouillé sur une cible. S'ils sont attachés
à une cible, la direction à
laquelle
ils voudront faire face sera vers la cible, faire face sera vers la cible, ce que nous pouvons facilement déterminer en soustrayant leurs positions
globales S'ils ne sont pas verrouillés,
ils voudront faire face à la direction de
saisie du mouvement, comme c'était le cas auparavant. Maintenant, le personnage fait face à
la cible bloquée, mais ses
animations locales ne sont pas très belles, car elles
se mélangent uniquement en fonction de la
vitesse à laquelle le personnage se déplace
et non en fonction de la direction Dans la machine à états de l'
arbre d'animation du personnage, ils sont en état d'inactivité car il n'y a pas de
plancher dans la scène. L'état de mouvement de la locomotive est
un espace de mélange unidimensionnel, mêlant les
animations de marche au ralenti et de course en fonction de la vitesse de déplacement du
personnage Supprimons cet état et
remplaçons-le par
une autre machine à états. Reconnecter les transitions
aux autres états, commençant par une
transition entre le début locomotion
pour en
faire l'état par défaut La transition
vers le démarrage par saut a été activée avec un
poids transversal de 0,3 seconde. Et sautez de la terre ferme à
la locomotion
en changeant à la fin avec un
destin croisé de 0,67 seconde Je vais omettre la transition
entre la locomotion et l'
inactivité temporaire lorsque je travaille dans la machine de locomotion, afin que le personnage reste dans l'état de locomotion et que je puisse voir les résultats Appuyez sur le bouton de jeu pour
forcer le personnage se déplacer
et il se lancera car
il est
actuellement vide Dans l'état de locomotion, nous aurons besoin de
deux séries différentes d'animations de
locomotion, à savoir
lorsque le personnage est bloqué sur une cible
et lorsqu'il
ne l'est pas, et pour pouvoir
passer de l'une à l' La valeur par défaut sera la
même qu'avant, un espace blond unidimensionnel. Disons qu'il n'est pas verrouillé. Ensuite, nous pouvons également ajouter un espace blond
bidimensionnel. Appelons celui-ci verrouillé. L'ajout d'une transition
entre le mode de démarrage le mode
non verrouillé fait de
celle-ci la transition par défaut. Nous pouvons ensuite
passer de « non verrouillé » à verrouillé » si la valeur
de la cible n'est pas nulle, nous pouvons la raccourcir pour n'en faire que cible et lui donner
un court fondu croisé. Et revenez
à la cible non verrouillée, sinon à la cible avec
le même fondu croisé. À l'intérieur de l'espace
de mélange non verrouillé. Nous pouvons le recréer
exactement comme avant, avec une valeur minimale
de zéro en mélangeant des animations de ralenti, de
marche et de course en fonction de la vitesse de
déplacement du personnage fois cela fait, utilisez les miettes de pain pour
monter d'un niveau jusqu'à la machine de locomotion
et appuyez sur le bouton de jeu la machine verrouillée
pour forcer le personnage à
entrer dans cet état pour forcer le personnage à
entrer dans cet Dans l'espace de mixage verrouillé
, nous allons fusionner
les animations en fonction la direction dans
laquelle le personnage se déplace par rapport à sa direction
avant, c'est-à-dire vers sa cible. Je vais régler le quadrillage par incréments d'un pour
faciliter les choses Si nous positionnons notre champ de
vision derrière le personnage et imaginons qu'il est bloqué sur une cible devant lui, axe y
représente la vitesse à laquelle le personnage se rapproche
ou s'éloigne de la cible. L'axe X représente la
vitesse à laquelle le personnage se déplace
vers la gauche ou vers la droite contourner la cible Commençons par placer l'animation
inactive au milieu. Pour l'axe X,
nous allons placer
une animation de mitraillage gauche sur
le côté gauche et une animation le côté gauche et une mitraillage droit
sur le côté droit Pour l'axe y, nous pouvons placer une animation en cours en position avant, ce qui générera des
triangles dans l'espace de fusion indiquant comment les
différentes animations seront fusionnées Et en ajoutant une animation de marche en
arrière en position Y négative, nous ajouterons également d'autres triangles Si nous changeons la position de fusion, nous pouvons voir à quoi ressemblera le
personnage tout en donnant une entrée de mouvement
dans n'importe quelle direction. En fonction des
ressources que vous utilisez, vous pouvez également avoir des animations de
mouvements en diagonale à ajouter à cet espace de fusion. Parfois, cet aperçu
ne
simule pas exactement le
comportement du personnage pendant le
jeu. Et vous devriez toujours le
tester en jouant
au jeu pour vous assurer qu'il s'
intègre bien dans le jeu. Mais avant
cela, revenons à la base de la machine
étatique et ajoutons la transition entre
la
locomotion et le saut au
ralenti, à condition que le personnage ne
soit pas au sol J'avais l'habitude de franchir le temps de fondu de 0,3 seconde pour cette transition. Nous devons également mettre à jour
la partie de notre script qui définit la
position de fusion de l'espace de fusion,
ce qui, dans le script de mon personnage se produit dans le cadre de la physique du sol. En sélectionnant l'arbre d'animation, nous pouvons copier le
chemin de propriété de la position non verrouillée lors du
mélange et le mettre à jour
dans la fonction set. Mais cela ne doit être défini que si le personnage n'est
pas attaché à une cible. S'ils sont verrouillés
sur une cible, nous devrons plutôt définir
la position
de fusion de l'espace de
fusion verrouillé. La position de fusion bloquée est un vecteur
deux avec un x et un y
, que nous devrons calculer. Déclarons donc une variable pour la conserver nommée locked on blend. Pour éviter de répéter les mêmes
calculs plusieurs fois, je vais également déclarer
une autre variable pour stocker la vélocité
relative du personnage, qui sera sa vélocité x z divisée par sa vitesse de course. Après avoir calculé cette valeur, la position
de fusion de l'espace de
fusion non verrouillé peut être réglée
sur la longueur de ce vecteur. Si le personnage est
bloqué sur une cible, nous pouvons trouver la valeur x de
la position de mélange en utilisant le produit scalaire
du vecteur de base global
x des plates-formes avec leur vitesse relative Le produit scalaire de deux
vecteurs donne un nombre représentant leur
similitude ou leur différence. Nous vérifions donc dans quelle mesure
la vitesse
relative du personnage est similaire la vitesse
relative du personnage est à celle d'un vecteur pointant
directement vers sa droite. En fonction de la configuration de votre
personnage la direction
considérée comme allant vers l'avant, vous devrez peut-être
multiplier cette valeur par moins un pour l'inverser. La position du mélange y peut également être déterminée en utilisant
la même méthode, mais en utilisant le vecteur z
avant du personnage. Ensuite, lorsqu'elle est verrouillée
sur une cible, la caméra doit regarder la cible, et non le personnage du
joueur. Dans la fonction de
traitement de la caméra, ignorant Delta, s'
il y a une cible, nous pouvons dire
à la caméra de regarder la cible et ajouter 1 mètre pour
ne pas regarder ses pieds. Lorsque vous définissez la
valeur de la cible, si la cible est définie sur zéro, nous pouvons réinitialiser la rotation de la
caméra pour revenir à la
même valeur que son nœud parent,
le bras à ressort, en réglant
sa rotation sur le vecteur 30 Nous pouvons également vouloir
déclencher la fonction de verrouillage si la cible actuelle sort de
notre limite de portée visible Ether se verrouille ou passe
automatiquement
à une cible plus proche. Ajoutons donc un signal indiquant quand
la cible actuelle
sort de portée et émettons-le si le corps qui a quitté la zone est
la cible actuelle Nous pouvons ensuite connecter ce signal au script de
gestion des entrées du lecteur. Appel de la fonction Toggle
Lock. Selon
que vous souhaitez que le comportement
passe à la
cible la plus proche ou qu'il soit simplement bloqué, vous souhaiterez peut-être lier
un argument vrai pour la force du paramètre. Dans le script Spring Arm, lorsque vous êtes bloqué sur une cible, nous voulons que le bras à ressort pointe
toujours dans le sens opposé à la cible afin
de garder la cible et le personnage du joueur dans le champ de
vision de la caméra. Ajoutons une nouvelle variable pour conserver cette direction
sous forme de vecteur trois. Ensuite, lorsque la valeur
de la cible est
définie, si elle n'est pas nulle,
nous pouvons définir la valeur de la direction de la
cible
comme étant définie, si elle n'est pas nulle, nous pouvons définir la valeur de la direction de la différence entre notre position globale moins la position globale de la
cible. Cela se traduira par
un vecteur pointant de la cible vers
le personnage du joueur. Nous pouvons ensuite réutiliser la fonction de rotation
entre deux, mais elle attend un paramètre float
représentant une rotation y. Nous pouvons obtenir la rotation y, qui pointera
dans cette direction utilisant la fonction trigonométrique
A t deux, en lui donnant les valeurs x et z de
notre Une fois la cible définie,
le bras à ressort fait tourner
la caméra dans
la direction opposée à celle de
la cible située derrière le joueur. Mais nous voulons qu'il y reste. Dans la fonction de traitement, si la valeur de la cible a
été définie et entre parenthèses, si l'interpolation n'
existe pas ou n'est pas en cours,
ce qui signifie que l'interpolation est terminée
et que le bras du ressort
est en position,
nous pouvons effectuer les mêmes calculs,
mais simplement régler
la
valeur de rotation
y directement au lieu de
faire un autre ce qui signifie que l'interpolation est terminée et que le bras du ressort
est en position, nous pouvons effectuer les mêmes calculs,
mais simplement régler
la valeur de rotation
y directement au lieu de faire Cela permet de maintenir le bras à ressort dirigé à l'opposé de la cible, tout en
maintenant la cible et le
personnage du joueur dans le champ de vision de la caméra. Enfin, dans le script de gestion des
entrées du joueur, nous voulons empêcher
le joueur de pivoter le bras à ressort
lorsqu'il est bloqué sur une cible. Cela se produit à deux endroits
différents dans mon script, l'un pour les commandes sur PC à
l'aide de la souris, et l'autre pour le
support de la manette avec le joystick droit. Je vais donc simplement intégrer les deux dans une
instruction if pour ne pas autoriser
ces entrées lorsque je suis verrouillé sur une cible. Essayons-le. Lorsque nous nous accrochons à un ennemi, la caméra se concentre
sur la cible, tandis que le bras à ressort tourne pour positionner la caméra dans
la direction opposée En déplaçant le personnage,
ils pivotent pour faire face à l'ennemi et animent
des mouvements fluides dans toutes les directions Le bras à ressort maintient la position de la caméra, qui
se trouve derrière le personnage
, en direction opposée à la cible, tandis que la caméra
continue de regarder la cible. Les commandes normales de l'
appareil photo du joueur ont été désactivées
lorsqu'il est verrouillé. Si la cible verrouillée
est hors de portée, elle passe
automatiquement à cible
la plus proche ou
se verrouille s'il n'y en a pas
une sur laquelle se verrouiller. Si nous forçons le verrouillage, la caméra se recentre
sur le personnage du joueur, contrôle
normal du bras à
ressort reprend et les
animations de locomotion du personnage redeviennent Nos nœuds de
joueurs adaptent désormais leurs comportements au
verrouillage d'une cible. Dans la leçon suivante, le personnage
du joueur va exécuter des attaques. Je te verrai dans la prochaine leçon.
5. Attaque: Bonjour, mes amis. Dans
la leçon précédente, nous avons modifié le comportement des nœuds
du joueur lorsqu'ils
sont verrouillés sur une cible. Dans cette leçon, nous allons ajouter des animations
d'attaque afin que les personnages puissent s'
attaquer les uns les autres. Commençons par ouvrir
les paramètres du projet, l'onglet de saisie de la carte, et ajouter un nouvel
événement d'entrée pour attaquer. Je vais utiliser le bouton gauche de la souris
et le bouton droit de l'épaule
de ma manette. Ensuite, dans le script du gestionnaire de
saisie du joueur, nous pouvons vérifier si le bouton d'
attaque a été enfoncé lors de la vérification des entrées de contrôle des
personnages Si le bouton d'attaque
a été enfoncé dans cette image, alors nous devrions dire au
personnage d'attaquer. Mais que faire si le
personnage est occupé ? Ils peuvent sauter ou
effectuer une autre action et nous ne voulons peut-être pas qu'ils
soient capables d'attaquer en ce
moment. Exiger du joueur qu'il
attende qu'il soit
possible d'attaquer avant d'
appuyer sur le bouton serait très frustrant. La plupart des jeux modernes
considèrent que le fait d'appuyer
sur le bouton est valide pendant une courte période
après l'avoir enfoncé, ce que l'on appelle la mise en mémoire tampon des
entrées Ajoutons une heure ou un nœud au gestionnaire
des entrées du joueur. Nommez-le tampon d'entrée et définissez sa
propriété one shot sur true, afin qu'il ne compte à
rebours qu'une seule fois à la fois. saisissant une référence à ce temporisateur de la mémoire tampon d'entrée
en utilisant Add on Ready, nous pouvons démarrer le chronomètre après avoir demandé au
personnage d'attaquer, puis attendre son signal d'expiration Une fois que le compte à rebours aura été
compté jusqu'à zéro, nous demanderons
au personnage d' annuler l'ordre d'attaque
qui lui a été donné. Ainsi, à tout moment pendant le
compte à rebours, le personnage essaiera d'
attaquer lorsqu'il sera prêt. Le temps d'attente par défaut pour
le temporisateur est de 1 seconde, ce qui est une
durée raisonnable pour la mémoire tampon
d'entrée de l'attaque. Une autre entrée que nous pourrions vouloir
mettre en mémoire tampon est l'entrée de saut. suivant le même schéma
que l'entrée d'attaque, nous pouvons démarrer le chronomètre, attendre son signal d'expiration, puis annuler l'entrée de saut. Dans le script du personnage, commençons par créer une
nouvelle région de code pour le combat. Déplacez ensuite la
fonction ciblée par le joueur dans cette région. Nous aurons besoin d'une fonction publique
pour demander au personnage d' attaquer et d'une autre pour lui demander d'annuler
l'instruction. La fonction de saut aura également besoin d' une correspondance et d'une fonction de
saut d'annulation deux. L'objectif principal
de ces fonctions est de définir des variables qui seront vérifiées par
l'arbre d'animation afin qu'il sache vers quels
états se déplacer. En haut du script, nous ajouterons d'autres
variables pour indiquer les intentions
du personnage quant à ce qu'il veut faire ensuite entrées en
mémoire tampon sous forme de booléens, s'il veut
sauter ou attaquer Ensuite, la fonction d'attaque
définira la
variable want to attack sur true et annulera
l'attaque la remettra sur false. Comme les entrées
sont mises en mémoire tampon, nous n'avons plus besoin
d'exiger que le personnage soit capable de
se déplacer ou d'être au sol, et nous pouvons déléguer
cette responsabilité à la machine d'état
des arbres d'animation De plus, nous n'avons pas besoin de demander à la machine d'
état de l'arbre
d'animation de
passer à l'état de démarrage rapide. Nous rendrons cette transition automatique si les
conditions sont remplies. Mais nous ne voulons pas que ces deux variables soient vraies
en même temps. Le personnage voudra
soit sauter, soit attaquer, pas les deux. Ainsi, chaque fois qu'une
entrée mise en mémoire tampon est définie sur true, toutes les autres sont définies sur false, annulant ainsi
l'instruction Dans la
scène du personnage, en sélectionnant l'arbre d'animation et passant au panneau de l'arbre
d'animation, nous pouvons voir la machine à états. Faisons en sorte que la
transition entre la locomotion et le démarrage soit
automatique à condition que le personnage soit au sol, qu'il puisse
se déplacer et qu'il veuille sauter Désormais, le personnage sautera
automatiquement dès qu'
il en capable dans la seconde qui suit l'
appui sur le bouton de saut. Ceci est particulièrement utile pour enchaîner les sauts les
uns après les autres, puisque le joueur
pourra appuyer sur le bouton de saut avant de
toucher le sol Mais en ce qui concerne la machine à états de
saut, voyons comment intégrer
les animations d'attaque. Nous pourrions passer
de la locomotion
à l' attaque et vice versa. Mais les animations
seraient mauvaises si nous
voulions que le personnage puisse se
déplacer tout en attaquant. Je n'autoriserais pas le personnage
à attaquer en sautant. Il serait préférable de séparer
les animations impliquant le déplacement du personnage de celles impliquant l'
exécution d'actions. Si votre
machine à états n'a pas encore été enregistrée en tant que
ressource de projet, cliquez sur le menu déroulant à côté Tree Root et sélectionnez Enregistrer sous. J'ai déjà enregistré le mien
dans le
dossier des scènes de personnages et je l'ai nommé animations de
personnages. Mais je vais le renommer en mouvements
de personnage. fois la machine à états enregistrée, retirons-la de l'arbre d'animation du
personnage et remplacons-la par
un arbre de fusion de nœuds d'animation. Le panneau de l'arbre d'animation affiche
désormais un graphique qui contient notre arbre de fusion, ce qui nous permet de fusionner autant d'
animations que vous le souhaitez. Cliquez avec le bouton droit de la souris dans
un espace vide, puis sélectionnez Charger. Parcourez ensuite les ressources de votre
projet pour trouver la machine à états de
mouvement de votre personnage. La machine à états que nous utilisions précédemment est désormais un nœud
dans le graphe de l'arbre de fusion, et le résultat de la machine à
états
sera affiché par la broche
située sur le côté droit. Si nous connectons la sortie de la machine à états à la
sortie de l'arbre de fusion, l'animation
fonctionnera comme avant. Mais le but de
l'arbre de fusion est de fusionner plusieurs
animations. Débranchons la broche. Cliquez ensuite avec le bouton droit de la souris et
ajoutez un nœud de fusion à deux. Le nœud
de fusion commence par l'animation
connectée à sa broche
d'entrée et intègre un pourcentage de l'animation connectée à sa broche d'entrée de
fusion. Le résultat de ce mélange sera
affiché par la broche située
sur le côté droit, que nous pouvons connecter à
la sortie des arbres de mélange. L'animation que nous voulons
intégrer aux mouvements du personnage
sera celle des actions du personnage,
à savoir ses attaques. Nous pouvons ajouter une autre machine à
états à l'arbre de mélange et la
nommer action. Connectez ensuite sa sortie à la broche d'entrée du
mélange à deux nœuds. Ensuite, nous allons ouvrir la machine à états
d'action et lancer le personnage
dans l'animation inactive. Passer de l'état de démarrage à l' inactif pour en faire l'état d'action
par défaut Ensuite, nous aurons besoin d'une vue de notre personnage et de démarrer
les machines à états de mouvement et d'action en
cliquant sur
le bouton de jeu situé dans leur état de départ
respectif. Retournez ensuite à la racine
de l'arbre de mélange. Notre personnage
semble toujours dans l'
animation « jump idle » car le pourcentage de
l'animation d'action qui y est intégrée
est actuellement nul Si nous faisons glisser la
poignée sur un, nous pouvons voir l'animation passer
progressivement du mode «
jump idle » au « idle ». Cliquez ensuite sur le bouton
Modifier les filtres, puis activez l'activation du filtrage. Déplaçons la
fenêtre pour que nous puissions
voir notre personnage tandis que nous filtrons les os individuels, décidant à quels os
nos animations d'action doivent être appliquées
et à quels os elles ne doivent pas être appliquées. Activez tous les os qui constituent le haut du corps du
personnage. Désormais, le bas du corps du personnage, y compris sa position, est affecté
par
l'état de mouvement. Sautez au ralenti, tandis que le haut de
leur corps est contrôlé par
leur état d'action inactif. Cela nous permet de combiner ces animations
de trois manières différentes. Si le personnage se déplace mais
n'effectue aucune action, montant du mélange sera nul, en utilisant uniquement la sortie de
la machine à états de mouvement. Si le personnage exécute
une action mais ne bouge pas, montant du mélange sera égal à un et les filtres désactivés, en utilisant uniquement le résultat de
la machine à états d'action. Si le personnage se déplace
et exécute une action, les filtres
seront activés. Utilisation de la sortie de la machine à états de
mouvement pour le bas du corps du personnage et la sortie de la machine à
états d'action pour
le haut du corps. Nommons ce mélange de deux
nœuds inférieur et supérieur, car il mélange les animations du
haut du corps avec les animations du bas du corps Mais si le
montant du mélange est égal à zéro ou à un, les animations de
l'une des machines à états ne seront pas exécutées pour économiser du temps de traitement, ce qui peut entraîner
des problèmes si nous nous
appuyons sur elles pour définir les
propriétés ou appeler des méthodes. Il peut être utile de toujours faire fonctionner
les deux machines à états en permanence, même si le personnage n'
effectue aucune action
ou ne bouge pas. Pour garantir que les deux
machines à états sont toujours actives, nous pouvons définir le montant du
mélange à 1 %
et, lorsque vous effectuez une action, l'
augmenter à 99 %. Nous pouvons supposer qu'il devrait commencer par un mélange de 1 % car le personnage n'
effectuera aucune action
lors du premier chargement. en revenir au script du personnage, étant donné que l'arbre d'animation va devenir
beaucoup plus complexe, il serait judicieux d' abstraire ses comportements
dans son propre script. Nous pouvons supprimer la variable de lecture State
Machine
du script de personnage et ajouter un nouveau script à
l'arbre d'animation. Je vais l'enregistrer dans le dossier des scripts de
personnages. Dans le nouveau script de l'
arbre d'animation, notre objectif principal est de créer les trois
mélanges d'animation que nous venons de mentionner. Dans la fonction de traitement, nous devrons définir le paramètre de quantité de
mélange comme nous l'avons fait avec
les espaces de mélange. Copier le chemin de propriété et
spécifier une quantité de mélange. Faisons du blend
amount une variable
flottante privée avec une valeur
par défaut de 1 %, et transmettons cette variable comme argument. Nous devrons ensuite modifier
la valeur du montant du mélange fonction du fait que le
personnage
exécute ou non une action. Stockons l'état
d'action lu par
les machines dans une variable. Cette fois, en utilisant
le mot clé self, puisque ce script est
attaché à l'arborescence et en utilisant le chemin de propriété pour lire
la machine à états
d'action. Ensuite, dans la fonction de traitement, nous pouvons vérifier dans quel nœud se trouve actuellement
la lecture de l'état d'action. Et s'il est à l'état inactif, cela signifie que le personnage
n'effectue aucune action, et nous pouvons définir le montant du
mélange à 1 %. Sinon, ils exécutent une action et nous
pouvons la définir à 99 %. Mais il s'agira d'un changement
instantané qui peut sembler un peu agité. Ainsi, au lieu de définir la
variable directement sur 1 % ou 99 %, déplacons-la
légèrement vers ce chiffre au fil du temps. En utilisant la fonction move towards, nous pouvons partir de ce qu'est actuellement la
variable, en la déplaçant vers ce que nous
voulons qu'elle soit par Delta. Cela fera prendre
une seconde à la
transition , ce qui est un peu long. Multiplions donc Delta par une nouvelle variable pour
maintenir la vitesse de fusion, laquelle je donnerai une valeur
par défaut de quatre. La transition prendra
un quart de seconde. Pour activer ou désactiver les filtres, nous devons accéder directement au nœud
Blend Two. Déclarer donc une
variable pour la contenir, qui est de type
animation node blend two. Nous pouvons y accéder à partir de la racine de l'arbre d'animation, en utilisant la fonction get node. Cette fonction accepte
un nom de chaîne, que nous pouvons spécifier comme étant
le même nom que celui que nous avons donné au nœud dans le
graphe de l'arbre de fusion, inférieur plus haut. Veillez à ce que l'
orthographe soit exactement la même. Nous ne sommes pas autorisés à
activer ou
désactiver les filtres pendant le traitement de l'
arbre d'animation. Créons donc une fonction publique pour laisser le
script du personnage le faire à notre place, indiquant à l'arbre d'animation si le
personnage bouge ou non. Si le personnage bouge, les filtres doivent
être activés pour intégrer les actions du haut du corps aux mouvements
du bas du corps. Si le personnage est immobile, les filtres peuvent être désactivés pour n'utiliser que les animations
d'action. Pendant que nous sommes ici, ajoutons également deux autres fonctions pour
définir les quantités
de mélange des espaces de
mélange de locomotion afin qu'ils
restent absents du script
du personnage Définissez le paramètre verrouillé sur le mélange, acceptant un
paramètre vectoriel à deux pour la quantité de mélange, en définissant le paramètre
de
quantité de mélange de l'espace de mélange verrouillé. Et définissez non verrouillé sur le mélange, acceptant un paramètre flottant
pour la quantité de mélange, en définissant le paramètre
de
quantité de mélange de l'espace de mélange non verrouillé
. De retour dans le script des personnages, nous pouvons constater que
les chemins de propriété menant aux quantités de mélange ne
sont plus valides, puisqu'ils ne font pas référence à
la machine à états de mouvement. faisant abstraction de ces
fonctions, nous conserverons les
modifications apportées à l'arbre
d'
animation dans son propre script Dans le processus physique normal, nous devrons également indiquer à l'arbre d'animation
si
le personnage
est en train de se déplacer ou non. Cependant, nous supposons maintenant
que chaque personnage doit avoir ce script attaché
à son arbre d'animation et qu'il utilise
le même arbre d'animation. Nous allons donc enregistrer notre
nouvel arbre d'animation en tant que ressource de projet. Je vais le mettre dans le dossier des scènes des
personnages, avec la machine à états de
mouvement des personnages. Mettez ensuite à jour chacun des
autres personnages pour qu'ils utilisent le nouvel arbre d'animation et
associez-y le script, afin qu'ils fonctionnent
tous de la même manière. Je n'utilise que le barbare et les squelettes dans ce projet, mais le mage nocturne et le voleur devraient également être mis à jour
si vous les utilisez Cela pose toutefois
un nouveau problème. Si tous les personnages partagent la
même ressource d'arbre de mélange, la modification de la propriété d'activation des
filtres pour un personnage changera
la même chose pour tous les personnages. Nous pouvons contourner ce problème en donnant à chaque personnage sa propre copie
unique de l'arbre de mélange. Pour éviter d'avoir à reproduire chaque modification de l'arbre de
mélange de chaque personnage à chaque fois, je vais utiliser un simple raccourci Dans le script de l'arbre d'animation, pendant la fonction Ready, je définirai la propriété
racine de l'arbre de façon à ce qu'elle soit une copie de
l'arbre de fusion. transmettez true comme argument, les sous-ressources
utilisées par cette
ressource
seront également dupliquées . Depuis l'arbre de fusion, cet arbre
d'animation utilise car sa racine n'est plus la même que celle qui lui avait été
initialement attribuée. Nous devrons
attribuer les valeurs de la lecture de l'état d'action et du nœud de fusion à deux
après cette duplication. Désormais, chaque fois
qu'un
personnage est chargé, il crée sa
propre copie unique de l'arbre de mélange et
peut modifier son comportement de
filtrage sans affecter les
autres personnages. Revenons à la machine à états
d'action des personnages. Notre personnage n'a pas
encore d'objets équipés, alors transformons-le en
idole désarmée Pour l'instant, conditionnons
cette transition à
la condition qu'ils
ciblent un ennemi
ou s'ils
veulent attaquer en utilisant un
court fondu croisé, et qu'ils puissent revenir en
arrière s'ils ne
visent pas un ennemi et
ne veulent pas attaquer. Ensuite, pour garder les choses organisées. Ajoutez également une autre machine d'État
nommée attaques non armées, et passez à
la machine d'État si le personnage
veut attaquer Ils peuvent ensuite redevenir une idole
désarmée à la fin
de l'animation d'attaque Modification de la machine à
états désarmée. Commençons par le coup de poing
masculin non armé A. Il passera
à la fin ou au coup d'attaque masculin B
non armé à la fin de l'animation, selon que le personnage
souhaite ou non attaquer à nouveau Nous pouvons répéter ce schéma
en passant à la fin animation
ou à un
coup de pied d'attaque masculin désarmé, selon que le personnage
veut ou
non attaquer à nouveau. Et nous pouvons créer une combinaison cycliste
infinie en revenant
au premier coup
tant que le joueur continue d'
appuyer sur le bouton d'attaque Lorsqu'ils arrêtent d'appuyer sur
le bouton d'attaque, la machine à
états passe à la fin, qui
revient au mode inactif sans arme Il se peut également que nous souhaitions restreindre la
façon dont le joueur se déplace
lorsqu'il attaque. Par exemple, cela n'aurait aucun
sens que le personnage bouge
pendant l'animation du coup de pied, car ses pieds devraient être occupés. Je vais zoomer sur l'affichage de la piste d'
animation pour mieux adapter la durée
de ces animations. Ajoutons une fonction publique au script
du personnage
pour limiter les mouvements, acceptant un paramètre
booléen si le
personnage peut se déplacer ou non Nous allons ensuite définir
la valeur opposée
de la variable move. Dans l'animation
Kick du personnage. Nous pouvons ajouter une piste de méthode d'
appel appelant une méthode sur le nœud racine du
personnage. Appelez la fonction de restriction des
mouvements au début de l'animation, en utilisant true comme argument, en
limitant les mouvements du personnage lorsqu'il donne des coups Et une autre touche à la fin
de l'animation peut restaurer la capacité du personnage à se déplacer en remplaçant l'
argument par faux. Mais pour que cela fonctionne,
nous devons revenir à l'arbre de fusion et
ajouter des fonctions
aux filtres de fusion de deux nœuds afin que si le personnage se déplace
et exécute une action, les fonctions d'action
soient appelées. Essayons-le.
Nos animations semblent fonctionner
comme avant. Dès que nous demandons au
personnage d'attaquer,
il passe à
l'état inactif sans arme avant de lancer une attaque Si nous continuons à donner des coups, ils
continueront à attaquer à plusieurs reprises parcourant les différentes animations d'attaque
à mains nues Il est même possible de se déplacer
ou de sauter en attaquant, et le personnage utilisera animations appropriées pour
le haut et le bas de
son corps, mais il n'est pas autorisé à
bouger ou à sauter lorsqu'il donne des coups Si nous nous accrochons à une cible, le personnage passe
en état d'inactivité désarmé et bloque les transitions
vers l'idole normale Notre personnage
exécute maintenant des attaques à mains nues. Dans la leçon suivante, nous ajouterons des animations
d'attaque par arme. Je te verrai dans la prochaine leçon.
6. Arme: Bonjour, mes amis. Dans
la leçon précédente, nous avons combiné des actions du haut du corps
avec des mouvements du bas du corps, permettant à notre personnage de lancer
des attaques à mains nues Dans cette leçon, nous allons également ajouter diverses
animations d'attaque par arme. Commençons par l'arbre
d'animation des personnages où nous avons déjà des attaques désarmées, inactives
et désarmées En suivant ce
modèle, nous allons ajouter l'animation inactive à deux mains. Dans ce pack d'actifs, il
n'y a pas d'animations inactives
à une main ou à deux roues Mais nous pouvons simplement
ajouter deux nouvelles copies de l'animation inactive
et les renommer. À partir de chacune de ces animations
inactives, nous pouvons ensuite nous connecter pour attaquer des machines à
états qui fonctionnent exactement
comme les attaques non armées Connexion de chacune
des animations inactives aux attaques si le
personnage veut attaquer,
puis revenir à la
fin de l'animation. Nous avons juste besoin d'un moyen de dire
au personnage quel ensemble d' animations utiliser en
fonction de son arme équipée. Dans ce projet, nous avons
un script nommé enums, contenant toutes nos énumérations, auquel nous ajouterons
un autre commençant par Unarmed par défaut,
puis en
listant chacun des types
d'armes
nécessitant des animations différentes, à savoir types
d'armes
nécessitant des animations différentes le mala à
une main, le mala à deux mains et le
mala à deux roues Il est important de savoir que l'énumération
n'est qu'une liste numérotée, sorte que chacune de ces valeurs
est en fait un nombre, commençant par zéro pour
désarmé, en
commençant par zéro pour
désarmé,
un pour une main pour un,
deux mains pour deux mains pour deux et trois pour deux roues Dans le
script du personnage, nous allons ajouter une autre variable nommée
attack animation avec un type de notre
nouvelle énumération Nous pouvons exporter cette variable à
des fins de test. Changeons l'animation d'attaque du
personnage pour qu'elle ne soit pas armée J'utiliserai la mêlée à deux mains. De retour dans la machine à
états d'action, nous pouvons définir la
condition de transition pour passer de l'état inactif au mode inactif
sans arme, comme si l'
animation d'attaque du personnage est nulle, ce qui est « non armé » dans
notre énumération, et également au moins une des autres conditions
en les mettant entre La condition de retour sera
alors également l'inverse. Soit l'
animation de l'attaque n'est pas nulle, soit les deux autres
conditions sont remplies. En ajoutant des transitions à chacun
des différents états d'inactivité, nous pouvons définir leurs conditions à ce qu'elles soient les mêmes que celles du mode inactif non armé, en utilisant
uniquement une valeur différente
pour l'animation d'attaque Je vais également donner à chacun d'eux le
même temps de fondu croisé. Puis retour au mode veille dans des conditions logiquement
opposées À l'intérieur de chacune des machines d'état d'
attaque, nous pouvons utiliser les
animations d'attaque de la même manière que nous l'avons fait pour
les attaques non armées Il existe quatre attaques à
une main différentes, crée un cycle d'animations
différentes tant que le personnage
veut continuer à attaquer. Répéter le même processus
pour les attaques à deux mains, qui ne comportent que trois attaques
différentes. Et la machine d'
État à deux roues ne dispose
également que de trois attaques Nous pouvons le
tester dans le jeu, puisque l'
animation d'attaque des personnages est réglée sur deux mains, ils utilisent les animations d'
attaque à deux mains. Nous pouvons leur dire d'utiliser également des animations d'attaque à une
main ou
des animations à deux roues Il ne nous reste plus qu'à modifier la variable lorsque nous équipons le personnage d'
objets Dans les ressources personnalisées, nous aurons besoin d'une classe plus
spécifique pour décrire une arme
héritée de l'équipement lui donnant le nom de classe weapon, nous pouvons ajouter une variable
exportée supplémentaire pour stocker le type
d'arme dont il s'agit, et nous pouvons utiliser la même
énumération que le Ensuite, toutes les
ressources du projet
qui sont des armes peuvent être
reclassées en armes, leur
attribuant une valeur correspondant
à leur type d'arme, afin que le personnage sache quelles animations utiliser pour l'
équiper À des fins de démonstration, je vais mettre à jour le x pour en faire
une arme à une main. N'oubliez pas de remplir à nouveau
les champs qui ne
sont pas reportés lorsque vous
modifiez le script de ressource Le grade en tant qu'arme à
deux mains
et le poignard en tant qu'arme à
deux roues Dans l'int ou dans le script que vous
utilisez pour équiper des objets, nous aurons besoin d'une exception si l'objet à
équiper est une arme. Et s'il s'agit
d'une arme à deux mains ou d'une arme à deux mains, nous
devrons retirer tout ce que le personnage possède
dans son emplacement hors main Vérifiez d'abord si le fichier, la matrice d'équipements de
progression contient quelque chose d'équipé dans
l'emplacement secondaire. Je vais ensuite m'en servir pour
indexer les boutons des objets dans l'inventaire du joueur et retirer le E correspondant à l'équipement
du bouton. Ensuite, réglez également la valeur des ensembles d'
équipements sur moins un ou sur vide. Je demanderai ensuite au
personnage de mettre n'importe quel équipement dans sa prise
de courant Dans le script du personnage, le personnage doit savoir ce qu'il tient
entre ses mains. Ajoutons des variables de type nœud 3 D pour tenir leur équipement
principal et secondaire. Notre personnage qui porte une
arme peut alors également se voir ajouter une logique supplémentaire pour déterminer
si l'objet est une arme L'objet principal du personnage peut ensuite être attribué
à cette arme, et les animations d'attaque des personnages peuvent
être définies
pour correspondre à celles de
l'arme équipée. Si l'objet est une arme à deux
roues, j'ajouterai également une autre
copie de l'arme dans la prise du
personnage. Et assignez-le à la variable «
off hand ». Lorsque vous retirez une
pièce d'équipement,
si cet équipement est
retiré de la main principale du
personnage,
nous pouvons définir la variable de la main
principale sur
zéro et vérifier également s'ils
sont actuellement en double maniement si cet équipement est retiré de la main principale du
personnage, nous pouvons définir la variable de la main
principale zéro et vérifier également s'ils
sont actuellement en double En cas de double maniement, je demanderai au personnage de saisir également
l'objet de sa main Ensuite, je mettrai l'
animation de l'attaque à désarmé. De même, si le socket à désactiver est le socket
décalé, nous
devons définir la variable
offhand Nous n'avons plus besoin d'exporter
l'animation de l'attaque, puisqu'elle sera désormais définie
par l'arme équipée. Maintenant, le personnage commence à
utiliser des attaques à mains nues. Mais lorsqu'on est équipé d'
une arme à une main passe aux attaques à
une main. Nous pouvons les équiper d'un bouclier, puis passer à une arme à
deux mains, et le bouclier sera
automatiquement retiré. Le personnage utilise désormais des animations d'attaque
à deux mains. Passant aux dagues à deux
roues, le personnage a un
poignard dans les deux mains
et utilise les animations d'attaque à deux roues. Après avoir équipé les dagues, le personnage recommence à
utiliser
des attaques à mains nues La dernière chose dont nos attaques
ont besoin, ce sont des boîtes à hanches. Zones de collision pour détecter si l'attaque touche réellement un
ennemi et lui inflige des dégâts. En ouvrant les scènes d'armes, nous pouvons ajouter des boîtes de frappe
à chacune d'elles. Utiliser un nœud de zone 3D, qui ne sera pas surveillé
ou surveillable par défaut, couche de collision
ni aucun masque de collision tant
qu'on ne leur aura pas demandé de le faire Comme ces
modèles de personnages ont des membres
courts et des armes légères, leurs attaques ne
vont pas très loin. Je vais donc être très
généreux avec leurs boîtes à hanches, en les rendant plus grandes que
les armes réelles. Création d'un nouveau script pour
les armes, en
héritant de l'objet Je vais remplacer le
script attaché
au nœud racine des armes
et l'ouvrir pour le modifier. Nous pouvons indiquer à l'
arme de saisir ou référence à sa
zone de frappe en utilisant Add on Ready. Ajoutez ensuite des fonctions pour définir un nouvel entier pour
le
masque de collision des cases à cocher. Et une autre qui
activera ou désactivera la hitbox en définissant
sa propriété de surveillance Le personnage qui détient
cette arme peut désormais spécifier dans quelle couche de
collision trouvent
ses ennemis et
activer la case de frappe lorsqu'il
fait pivoter l'arme Le modèle de personnage
aura également besoin d' une boîte à hanches pour les attaques à mains nues Tout comme les
armes, elles n'
ont pas besoin d'être surveillées,
surveillables, ni de couche de collision ni de masque de collision et
elles
auront une forme de collision surdimensionnée Mais nous n'avons pas besoin de
le positionner pour le moment et nous pouvons déléguer cette responsabilité
aux animations. Dans le
script du personnage, nous pouvons saisir une référence à la boîte à
hanches désarmée en utilisant Add-on Ready N'oubliez pas d'ajouter une
case à chaque caractère ou d'utiliser la
fonction get node ou null pour éviter les erreurs. Exportons également une couche physique en
trois D pour contenir la couche de collision des ennemis de
ce personnage. Cela ajoutera une grille de chiffres dans l'
inspecteur, tout comme les couches de collision dans la zone des trois propriétés des notes en D. De cette façon, nous pouvons spécifier
que ce personnage
essaiera de toucher des objets sur la couche de collision Blessure
ennemie, que j'ai
qualifiée de couche 18. Pendant ce temps, les ennemis utilisant
le même script peuvent définir leur couche de collision ennemie comme couche de
collision HRT du joueur Pendant la fonction de préparation, nous pouvons configurer le masque de collision de la boîte à hanches désarmée pour qu'il devienne
la couche de collision de l'ennemi De même, chaque fois qu'une
arme est équipée, nous pouvons configurer son masque de collision pour qu'il soit la couche de
collision de l'ennemi, afin qu'il sache quelles couches masquer, peu importe
qui la détient. Nous aurons ensuite besoin de
certaines fonctions script
du personnage
pour activer et
désactiver les boîtes à hanches des armes pendant
les animations d'
attaque, acceptant un paramètre
booléen spécifiant si la boîte
à hanches est spécifiant si la boîte
à hanches est activée ou désactivée et un entier Et je vais lui donner une valeur par défaut de un pour désigner la main principale. À l'aide d'une déclaration de match, nous pouvons créer trois cas
distincts, activant la boîte à hanches
pour les attaques à mains nues, les attaques à main
principale
ou les attaques hors main Si vous n'êtes pas armé, nous pouvons activer la propriété de surveillance de la hanche
non armée Qu'il s'agisse d'une main principale ou d'une main désactivée, nous pouvons demander à l'arme d' activer ou de désactiver
sa zone de frappe Les animations de nos personnages
peuvent ensuite être
ajoutées à des pistes pour activer et
désactiver les boîtes à succès Je vais juste vous montrer avec
une attaque de chaque type, commençant par un coup d'attaque
masculin à une main. En ajoutant une
piste de méthode d'appel à cette animation, nous nous
attendons généralement à ce que la zone de frappe soit activée juste après qu'
elle commence à osciller. En ajoutant une touche à ce moment, nous pouvons changer l'
argument booléen en vrai pour activer la case de frappe de l'arme principale du
personnage. Puis désactivé à la fin
du swing en remplaçant
l'argument par false Cela empêchera les ennemis
d'entrer dans l'arme lorsqu'elle ne bouge pas et
d'être blessés par celle-ci, et n'infligera des dégâts que lorsque le personnage manipule
réellement l'arme avec force Le processus est le même lorsque vous maniez une arme entre les mains. L'ajout d'une piste, puis fonction de cadrage des
touches
appelle à activer la case de frappe au début
du swing de l'arme et désactiver à
la fin du En cas de double maniement,
nous devrons
spécifier quelle boîte à hanches
est activée, qu'il
s'agisse de la
main principale ou de la main libre, en modifiant également le paramètre
entier à deux, si la boîte
à hanches activée ou
désactivée appartient à
l'arme à main levée Et une fois désarmés, nous devrons non seulement
activer la boîte à hanches, mais également la positionner
au bon endroit Utiliser une piste de propriétés pour encadrer la propriété de
position des hip boxes. Nous allons ensuite changer l'
argument entier dans les appels de fonction à zéro pour indiquer que nous voulons utiliser la boîte à hanches non armée Il est conseillé de
s'assurer que la boîte à hanches est en place au moins un cadre
avant de l'activer. Il est utile d'utiliser des
vues orthogonales pour positionner la hanche exactement sur le poing du personnage sous
au moins deux angles différents Cliquez ensuite sur l'icône en forme de
clé pour cadrer cette position
dans l'animation. Nous ne serons pas en mesure de tester
ces boîtes à hanches avant la prochaine leçon, lorsque nous
ajouterons des boîtes de blessure à toucher. La boîte à hanches s'
activera non seulement avec l'animation, mais suivra également
le poing du personnage. N'oubliez pas que vous
devez effectuer ce processus pour chaque animation d'
attaque. Notre
personnage attaque désormais avec des animations
différentes
pour chaque type d'arme. Dans la leçon suivante, nous autoriserons personnages à se
blesser et à subir des dégâts. Je te verrai dans la prochaine leçon.
7. Hit: Bonjour, mes amis. Dans
la leçon précédente, nous avons ajouté des boîtes de frappe à nos
armes et à nos animations d'attaque. Dans cette leçon, nous allons
ajouter des boîtes de blessures à nos personnages afin qu'ils
puissent être touchés par des attaques. La boîte Hurt d'un personnage n'est qu'
un autre nœud de la zone 3 D. Nous allons ajouter des modèles
de personnages. Ils ne seront pas surveillés, mais pourront être surveillés
par les boîtes à succès Ils existeront
soit sur la couche
Hurt Box du joueur , soit sur
la couche Heart Box
de l'ennemi de manière appropriée. Mais il n'est pas nécessaire de masquer quoi que ce soit puisqu'ils ne
surveillent pas de toute façon. Pour la forme de
collision des boîtes Hert, une autre capsule est très courante, mais elle est généralement plus petite que la forme de
collision du corps du personnage et entièrement contenue dans
le modèle du personnage Ce ne serait pas juste
pour le joueur de se faire toucher par quelque chose qui ne
semble pas entrer en contact. N'oubliez pas que
les armes
utilisent des boîtes à hanches surdimensionnées Il serait
donc raisonnable de
sous-dimensionner les boîtes à cœur , mais je vais adapter la mienne à la tête et au
corps du personnage Je vais ensuite copier-coller la même boîte en cœur dans les scènes de mes personnages
ennemis, remplaçant leur couche de collision par la
couche HRT ennemie Ensuite, dans nos scènes d'armes, je vais utiliser la hache comme exemple. Nous devrons connecter
le signal
saisi par la zone de frappe au script
de l'arme. Si cette arme entre dans la boîte à blessures
d'un personnage, nous
aurons besoin de cette arme pour infliger des dégâts à
ce personnage Pour l'instant, ajoutons une variable publique pour
ces dégâts infligés par les armes. Lorsque la collision se produit, nous aurons besoin d'une référence
au personnage auquel appartient la case
Hurt. Dans mon projet, ce sera toujours le
nœud parent de la boîte Hurt. Nous pouvons ensuite demander au
personnage de subir des dégâts, en utilisant les
dégâts de l'arme comme argument. Il peut également être intéressant de connaître la direction d'où proviennent les
dégâts. Nous pouvons donc utiliser la
différence entre leurs
positions globales normalisée. Pour conserver toutes nos
informations sur les armes au même endroit, leurs dégâts doivent être ajoutés
au fichier de ressources en
tant que variable exportée, et je vais leur donner une
valeur par défaut de deux dégâts. Chaque fichier de
ressources d'arme peut ensuite spécifier l'ampleur des dégâts infligés par
cette arme N'oubliez pas de connecter également le signal de zone saisie pour chaque scène d'
arme. De même, la boîte à hanches
désarmée de notre personnage a également besoin d'une connexion de signal pour indiquer au personnage d'
infliger des dégâts à un
joueur non armé Prendre le parent
de la Hurt Box, lui dire de subir un dommage et lui donner
la direction normalisée Ensuite, dans le script du personnage, lorsque nous créons l'instance
d'arme, nous pouvons définir le même nombre
de dégâts que celui de la ressource. I. Pendant que nous sommes ici, écrivons également la fonction de prise de
dégâts dans
la zone de combat. Accepter le
montant des dégâts à
encaisser, ainsi que
la direction d'où ils proviennent, lui attribuant
la valeur par défaut du vecteur 30. Pour subir des dégâts, nos personnages auront besoin de santé. Je vais ajouter une catégorie d'exportation
pour les variables de combat. Déclarez ensuite un
pour la santé
maximale des caractères sous la forme d'un entier
, que je mettrai à cinq. Et leur état de santé actuel est
également un entier,
que nous pouvons définir à leur santé
maximale
en utilisant Add-on Ready. Déclarons également quelques paramètres
booléens indiquant si le personnage est mort
ou non
et si les dégâts subis ont
été infligés par derrière, et saisissons également une référence à
la boîte à rats du personnage
en utilisant Add on En cas de dégâts, la santé actuelle du
personnage sera réduite en fonction du
montant des dégâts subis, mais nous ne voulons pas
qu'elle passe en dessous de zéro. Nous pouvons donc utiliser la
fonction max pour le régler sur ce calcul ou sur
zéro, selon la valeur la plus élevée. Le
booléen vu de derrière peut alors être défini sur true si le produit
scalaire de la direction des dégâts par le vecteur de
base avant du personnage est un Si la santé
actuelle du personnage après
avoir subi des dégâts est nulle,
il mourra. Dans le cas contraire, ils seront touchés. Bien que l'animation de la mort
soit automatique, l'animation des victimes peut être gérée par le script
Animation Trees, et nous lui indiquerons
si les dégâts
subis étaient inférieurs ou
supérieurs à un certain seuil. De cette façon, nous pouvons modifier l'animation du coup en fonction de l'
ampleur des dégâts subis. Nous pouvons également vouloir suivre l' état de santé
d'un personnage
ou le moment de sa mort. Ce serait une bonne idée de diffuser ces deux
événements sous forme de signaux. déclarant un signal chaque fois que la
santé du personnage change, nous pouvons utiliser un pourcentage
de santé restante comme argument et
un autre signal
pour indiquer le moment où le personnage meurt. Émettez ensuite le signal de
changement de santé s'ils subissent des dégâts et le signal de mise à mort
si le personnage meurt. Pour calculer leur pourcentage
de santé restante, il suffit de diviser leur
santé actuelle par leur santé MX. Mais comme ces deux
valeurs sont des entiers, le résultat sera
également un entier, sorte qu'il n'en
résultera que zéro ou un Nous devrons d'abord lancer
au moins l'un d'entre eux à flot avant de
procéder à la division, afin que le résultat soit
également Si nous ne voulons plus que les personnages
morts soient affectés par les collisions, nous pouvons également définir leur couche de
collision à zéro, leur masque de collision à un, afin qu'ils ne soient
affectés que par le terrain et définir leur propriété
surveillable H rtbach Il est également possible
qu'un personnage
soit touché ou tué pendant qu'il
exécute une action. Nous devons donc également garder une trace
des actions interrompues susceptibles de provoquer des problèmes et les corriger dans le cadre
d'une fonction privée. Par exemple, nous devrions
probablement désactiver toutes boîtes à hanches si
leurs
attaques étaient interrompues, ce que nous pouvons également faire dans
une fonction séparée, vérifiant si des références à
chacune d' entre elles existent avant de les
désactiver. Dans l'arbre
d'animation des personnages, nous voulons que le personnage soit
tué ou touché interrompe et annule
toutes les autres animations Comme cet arbre de fusion est
déjà enregistré en tant que ressource, nous pouvons le supprimer de
l'arbre d'animation et le remplacer par
une machine à états. À la base
de la machine à états, nous allons commencer par les animations de mort de nos
personnages, car celles-ci auront la priorité
absolue par rapport à toutes les autres animations. Ajoutez ensuite une autre machine à états
pour les animations à succès. Nous passerons de l'attaque A à la mort si le
personnage est mort. Avec un court fondu croisé. Ou bien
la mort B s'ils ont également été touchés par derrière en lui donnant cette priorité
en la mettant à zéro. n'a peut-être pas besoin Notre personnage n'a peut-être pas besoin de
revenir de sa mort, mais cela ne fait pas de mal
d'ajouter cette transition
à condition
qu'il ne soit pas mort. Dans la machine à états des hits, nous allons faire la même chose avec les animations des hits et ajouter notre arbre de fusion comme animation
par défaut ici. Activer les transitions vers les animations sélectionnées et revenir à l'arbre de fusion à la fin de leurs animations. Avec un fondu croisé à la fois dans et hors des animations
visitées, la machine
d'
état de l'arbre d'animation mise à jour, nous l'enregistrerons en
tant que ressource du projet. Je vais appeler ça des animations de
personnages. Et pour la dernière
fois, chaque personnage peut être mis à jour pour utiliser
la nouvelle machine à états. Dans le script Animation trees, nous aurons besoin d'une référence
à la lecture de l'état du hit. De plus, comme nous avons mis à jour
le format de l'arbre, nous devrons mettre à jour tous ces chemins
de propriétés. Nous allons maintenant accéder
au nœud de fusion en obtenant le nœud sélectionné, puis le nœud d'arbre de fusion, et enfin, le nœud de mélange inférieur
et supérieur. donnant une définition à la
fonction get hit, nous pouvons recevoir le paramètre
booléen comme si le caractère
est légèrement touché ou non Dites ensuite
à l'état touché de passer à A s'il a été touché légèrement ou B s'il
a été touché plus fort. Essayons-le. Si
nous frappons le squelette, il réagit
lorsqu'il est légèrement touché, en utilisant une hache et en l'
attaquant à nouveau. Ils sont plus durement touchés. Un
troisième coup et ils meurent en tombant en arrière puisqu'ils
ont été touchés par l'avant Nous pouvons équiper la grande hache, que j'ai définie pour
infliger
cinq dégâts, tuer un autre
squelette par derrière, et ils tombent en
avant en mourant. Ce serait également
bien de pouvoir
suivre l'état de santé du personnage du joueur sur l'interface utilisateur. Ajoutons un nœud de contrôle
et appelons-le jauge de santé. Je vais le mettre derrière
tout le reste de l'interface utilisateur. Cela nécessitera un texte
direct pour dessiner la bordure, un montage de couleur en guise de remplissage et un autre texte direct
si nous voulons une icône Je vais utiliser un cadre coulissant fin
comme image de bordure. Il est très grand, je vais
donc le réduire au
quart de sa taille. Et je vais utiliser une icône, un petit cœur plein pour l'icône. Redimensionnez-le et positionnez-le là où il est beau
par rapport à la bordure Je vais ensuite définir la couleur de
la couleur, etc., pour qu'elle corresponde à
la couleur du cœur, et définir sa position et ses
dimensions pour remplir la jauge. Je vais réinitialiser sa propriété de taille, ancrer dans le coin
inférieur gauche. En cliquant et en faisant glisser le
pointeur sur la propriété size x du remplissage, nous pouvons voir comment la jauge peut facilement être réglée sur n'importe quel pourcentage En joignant un script
à la jauge de santé, nous pouvons simplement l'appeler jauge pour réutiliser pour toute autre
jauge que nous souhaiterions Nous allons récupérer une référence à la couleur de remplissage ret
en utilisant add on ready, et également déclarer une
variable contenant le point de taille x
du remplissage lorsque la jauge
est complètement remplie, quoi la propriété
size point x à quoi la propriété
size point x
est définie lors du premier chargement. Écrivez ensuite une
fonction publique nommée set value, acceptant un paramètre de pourcentage à
virgule flottante. Il suffit de définir
la propriété size x de la couleur t comme étant le pourcentage multiplié
par la taille maximale. En connectant le
signal de changement de santé du
personnage du joueur à la fonction de
réglage de la valeur des jauges, il suivra désormais automatiquement
l'état de santé du joueur Pour tester la jauge de santé. Je vais juste dire au
personnage de subir
deux dégâts à chaque fois que le
joueur appuie sur le bouton Exécuter. Nous pouvons maintenant voir que la jauge de
santé du personnage s'épuise et que le personnage meurt
lorsqu'elle est vide. Je vais ensuite remettre à zéro la ligne de prise de
dégâts pour qu'elle fonctionne. Notre
personnage est maintenant
touché et subit des
dégâts à cause des attaques. Et dans la prochaine leçon, nous allons permettre aux personnages d'éviter de
se faire toucher en esquivant Je te verrai dans la prochaine leçon.
8. Dodge: Bonjour, mes amis. Dans
la leçon précédente, nous avons autorisé nos personnages
à être attaqués, subir des dégâts et à mourir. Dans cette leçon, nous allons
les aider à éviter les dégâts en esquivant. Commençons par les paramètres du
projet, dans l'onglet Carte d'entrée, en ajoutant un
événement d'entrée pour l'esquive J'utiliserai la barre d'espace ou le bouton droit
de ma manette. Dans le script du joueur, nous pouvons utiliser les mêmes méthodes que le saut et l'attaque pour amortir
l'esquive. Dans le script du personnage, nous aurons besoin d'une variable indiquant si le personnage
veut esquiver ou non. Mais une esquive n'est pas une
simple saisie. Il nécessite également une direction
sous forme de vecteur trois. Dans la zone de combat, nous aurons besoin d'une fonction d'esquive
et d'une fonction d'annulation de l'esquive, en définissant la
variable booléenne Et avec toute entrée mise en mémoire tampon, toutes les autres entrées mises en mémoire tampon
seront définies sur false Comme nous enregistrons déjà la direction d'entrée dans
le script du personnage, nous pouvons vérifier s'il s'agit du vecteur 30 au moment où le
personnage a reçu l'ordre d'esquiver. Si je ne donne aucune information, je veux que le personnage
esquive en arrière. Je vais utiliser le vecteur avant de Character
Rigs Bases, multipliant par moins
un pour l'inverser Si nous donnons une
orientation, je veux que le personnage
esquive dans cette direction, mais toujours avec force. Je vais normaliser la direction pour supprimer la magnitude
de l'équation. Dans la machine à états de l'
arbre d'animation des personnages, naviguez entre
les
animations de la mort et des touches dans l'arbre de mélange, et enfin, dans la machine à états de
mouvement Nous pouvons ajouter les animations d'esquive dans un espace de
fusion bidimensionnel. Passage de la locomotion à l' esquive si le personnage
veut esquiver,
puis retour à la locomotion à
la fin de l'animation Les deux avec un fondu croisé. Comme cela est lié
à la locomotion, l'esquive ne sera exécutée que lorsque le personnage
est au sol Vous pouvez également associer des esquives aériennes à état d'inactivité du
saut Dans l'espace du Dodge Blend, je vais remplacer le clivage de
la grille par un facteur d'un Ajoutez ensuite les animations
Dodge forward, Dodge back,
Dodge left et esquive right
qui seront
mélangées pour que le personnage
puisse esquiver dans n'importe quelle direction Le script de l'arbre d'animation
devra être capable de définir la quantité de fusion de cet espace de
fusion sous forme de vecteur deux, la même manière que nous avons défini
la quantité
de fusion des animations bloquées lors du
mitraillage Dans le script du personnage, lorsque vous demandez au
personnage d'esquiver, nous pouvons demander
à l'animation de définir cette quantité de mélange. Mais la direction de l'esquive est un vecteur trois dans l'espace global, tandis que le
montant du mélange pour l'esquive est un vecteur deux dans l'espace local des plates-formes de
personnages Nous pouvons calculer la quantité de
mélange en comparant la direction d'esquive aux vecteurs
des espaces de montage à
l'aide d'un produit ponctuel. Je vais devoir inverser
le montant du mélange x multipliant par moins un Si nous essayons cela,
l'animation d'esquive se joue trois fois et le personnage ne bouge pas vraiment. L'animation se répète
car Wants to esquive est vrai pendant
une seconde complète, mais l'animation
ne dure que 0,4 seconde. Il se répétera donc autant de fois que possible
jusqu'à ce que la variable wants to esquive soit redéfinie false avant la fin de la seconde. Nous devrons définir
la variable false une fois que l'esquive aura
été exécutée avec succès et appliquer
de la vélocité pour
déplacer le personnage. En ajoutant une autre fonction, un peu comme l'application de la vélocité de saut, nous appliquerons la vélocité d'esquive et appellerons cette fonction
depuis l'animation. Si cette fonction est appelée, le personnage a
réussi à esquiver et nous pouvons définir la
variable sur false pour
éviter que d'autres esquives ne
se produisent à partir d'une seule entrée Ensuite, nous définirons la vélocité du
personnage comme étant
la direction d' esquive
multipliée par la force d'esquive. Cela créera une
impulsion soudaine de vélocité, déplaçant rapidement le personnage dans la direction dans laquelle
il esquive Création d'une autre variable
exportée pour la force d'esquive du personnage. Je vais le mettre à huit. Vous voudrez peut-être aussi que notre esquive
ait des montures pour les yeux, abréviation de lunettes d'invincibilité Il s'agit d'une durée pendant laquelle le personnage ne peut pas
être blessé par des attaques Tout comme nous avons une
fonction appelée par nos animations d'attaque pour
activer ou désactiver la case Hip, nous aurons également une
fonction appelée par les animations d'esquive pour activer et désactiver
la case Hurt. Nous devons utiliser set deferred pour définir la
propriété monitorable de la case Hurt sur la
valeur active
au cas où cela se produirait
lors d'une collision Comme il est possible que nous souhaitions appeler cette
fonction à la suite d' une collision, nous ne pouvons pas activer ou désactiver
les collideurs pendant
leur traitement Dans les animations des personnages, nous devrons ajouter des pistes d'appels de
fonctions à chacune des animations d'
esquive de nos personnages. Je vais d'abord désactiver la case Hurt du
personnage. Ensuite, lorsque le
personnage aura l'air commencer à se déplacer
dans l'animation, j'appliquerai la vélocité d'esquive. Une fois qu'ils auront eu le temps d'utiliser
la vélocité d'esquive
pour utiliser
la vélocité d'esquive
pour empêcher
le personnage de passer à l'attaque, empêcher
le personnage de passer à l'attaque,
je réactiverai la case HRT en remplaçant l'
argument par vrai Répétez ensuite le
même ensemble d'
appels de fonction pour chacune des animations d'
esquive. Bien que cela ne devrait pas se produire avec ce code tel qu'il est actuellement, il est possible
que le personnage soit interrompu pendant qu'il esquive,
ce qui signifie que la case
à cocher
ne sera peut-être jamais réactivée Selon le fonctionnement
du jeu, vous pouvez
inclure
l'activation de la case du personnage dans
les actions d'interruption. Maintenant que la
vélocité d'esquive est appliquée, je n'aime pas vraiment
la façon dont l'animation d'esquive déplace
réellement la
position racine du personnage, ce qui entraîne des mouvements
brusques, fois avant et en
sortant de l' En ouvrant les animations,
je vais donc supprimer les images clés racines animations
d'esquive. Garder le personnage
ancré là où le personnage doit être, conformément à
la physique du corps du personnage. Ensuite, je vais également répéter cela pour les autres
animations d'esquive. cours de jeu, nous pouvons
voir l'arbre des scènes distantes, trouver la boîte à rats du personnage et faire attention à la propriété
surveillable esquive définit la
propriété surveillable sur false, puis la redéfinit sur true,
et le personnage anime l'esquive de manière plus fluide avec
la vélocité grâce à
la
suppression des images-clés et le personnage anime l'esquive de manière plus fluide avec
la vélocité grâce à
la
suppression Maintenant que l'esquive s'anime
et fonctionne correctement, voyons maintenant
si nous voulons permettre
au personnage d'attaquer et d'
esquiver en même temps De plus, le
personnage devrait-il être autorisé à attaquer ou à esquiver
s'il est touché ? Si nous ne voulons pas
autoriser ce comportement, nous devrons savoir
quand le personnage attaque, esquive
ou
est touché Ajoutons quelques variables
booléennes supplémentaires à notre script
de personnage : attaque, esquive et
est Tous ces éléments devront
être exportés pour être accessibles au nœud du lecteur
d'animation. À l'aide des pistes de propriétés, les animations
touchées peuvent définir la variable is hit sur
true au début
de l'animation. Et revenons au faux à la fin. Ensuite, dans l'arbre d'animation, lors de la transition de
la locomotion à l'esquive, nous pouvons vérifier
que le personnage
veut esquiver et que rien n'est touché
et que rien n'attaque et que rien Avant de
passer à un état d'attaque, nous pouvons vérifier non seulement si le
personnage veut attaquer, mais aussi s'il n'est pas
touché et s'il n'esquive pas Nous pouvons ensuite répéter le
processus de définition
des variables booléennes dans
les animations d'esquive Chacun définit la variable
is dodging sur true au début
et false à la fin Encore une fois, pour chaque animation d'
attaque, définissez la
variable « attaque » sur true
au début des
animations d'attaque et sur « baisse » à la fin. Si les attaques ou les
esquives sont interrompues, nous devons également remettre ces
variables sur false Il est également possible que
le personnage meure en
interrompant l'animation à succès Nous allons donc définir la
variable is hit sur false ici. Pour que la
variable d'attaque soit définie par la machine à états
d'action, nous devons également
activer le filtre correspondant ainsi
que la position de la case de
frappe. Afin de vérifier si l'
esquive fonctionne réellement, nous aurons besoin que les ennemis commencent
à attaquer. Si vous n'avez pas encore configuré les animations d'attaque
ennemie, un moyen simple de le faire est de copier le lecteur d'animation des personnages et de le coller dans
la scène ennemie. Nous pouvons ensuite indiquer à
l'arbre d'animation d'utiliser le nouveau lecteur d'animation. Et tant que l'ennemi a la même structure osseuse
que le personnage, les animations fonctionneront
toutes de la même manière. Sinon, vous devrez
configurer l'ennemi pour qu'il dispose d' au
moins une attaque capable
d'activer une boîte à hanches, masquant ainsi la boîte en T du personnage Pour lancer l'attaque de l'ennemi, je vais simplement lui attacher un nœud
vide dans la scène de niveau. Avec un simple script, leur
disant d'attaquer. Je vais créer un nouveau dossier pour les scripts
ennemis et
l'appeler attaque. Après avoir saisi une référence
au personnage en tant que
parent de ce nœud, je vais lui demander d'
attaquer dans la fonction Ready Comme la variable
ne sera jamais remise à false, c'est tout
ce qu'il
faut pour que les ennemis
exécutent des attaques à
l'infini Essayons de lancer le jeu avec des formes de
collision visibles. Et visualisez l'arbre des
scènes distantes où nous pouvons voir les valeurs de
toutes nos nouvelles variables. Le personnage attendra la fin
d'une attaque avant d'
effectuer une esquive
et vice versa. Si nous laissons le squelette
toucher le personnage,
celui-ci subit des dégâts et ne pourra ni
attaquer ni esquiver tant que l'animation du
personnage ne sera pas terminée. Et nous pouvons esquiver l'attaque du
squelette grâce à notre nouvelle action d'esquive Notre personnage
esquive désormais pour échapper aux attaques et limite les moments
où le personnage peut effectuer certaines actions Dans la leçon suivante, nous autoriserons personnages à bloquer les
attaques entrantes à l'aide d'un bouclier. Je te verrai dans la prochaine leçon.
9. Bloc: Bonjour, mes amis. Dans
la leçon précédente, nous avons aidé nos personnages à éviter subir
des dégâts en
évitant les attaques Dans cette leçon, nous allons
leur permettre de bloquer les attaques à l'
aide d'un bouclier. Commençons par les paramètres du
projet, dans l'onglet Carte d'entrée, et ajoutons un
événement d'entrée à bloquer. J'utiliserai le bouton droit de la souris
et le bouton gauche de l'épaule
de ma manette. Dans le script du joueur,
le bouton de blocage n'a pas besoin d'être mis en mémoire tampon, car il se comporte davantage
comme le bouton d'exécution, modifiant ainsi le comportement du
personnage lorsque le bouton est maintenu Envoi d'un signal au personnage
pour qu'il bloque ou non, selon que le bouton
est enfoncé ou relâché. Le script de caractères peut ensuite stocker cette valeur dans une variable. Il veut bloquer. Mais contrairement
aux autres variables, il n'est pas vraiment nécessaire de mettre en
mémoire tampon l'entrée bloquante. Ajoutez ensuite une fonction dans la section de combat qui
définit cette variable. Dans l'
arbre d'animation des personnages, la machine à états navigue vers la machine à états
d'action Nous pouvons ajouter l'
animation du bloc et
y faire la transition si le personnage souhaite bloquer avec un court fondu croisé. Revenez ensuite à s'
ils ne veulent pas bloquer. obtenant une vue du personnage et en se mélangeant dans
l'état d'action, cette animation amène le personnage à
lever son bouclier Une fois cette animation terminée, nous pouvons passer à
l'animation de blocage, qui doit être réglée en boucle
pour maintenir le bouclier en place tant que le joueur maintient
le bouton de blocage enfoncé. Cela redeviendra également inactif si le personnage
ne veut plus
bloquer avec un court fondu croisé. Nous souhaiterons peut-être également
pouvoir passer à
l'animation par blocs à partir de certains
de nos autres états inactifs, tels que les états non armé et inactif d'
une seule main Pour réduire le nombre de
transitions, je vais d'abord combiner les états d'inactivité
et d'inactivité unilatérale en combinant
logiquement les conditions de
transition pour atteindre l'état d'attaque
unilatérale Si l'animation d'attaque en est une, ils veulent attaquer, ils
ne sont pas touchés et ils n'esquivent pas Revenez ensuite au mode inactif à la
fin de l'animation d'attaque. supprimant l'état d'inactivité d'une
main, je vais ensuite réorganiser
les autres états pour qu'ils soient un peu plus organisés Désormais, une
idole inactive ou désarmée peut passer au bloc, si le personnage veut bloquer, et
revenir directement à une idole désarmée, si l'
animation d'attaque du personnage est nulle et qu'il a une
cible ou veut attaquer,
mais qu'il ne veut pas bloquer Avec une priorité de zéro. Désormais, un joueur inactif ou
non armé peut
passer au mode bloc si le
personnage le souhaite. Les états de blocage et de blocage
peuvent ignorer l'état d'inactivité et revenir directement au mode inactif non armé
avec une priorité de zéro De cette façon, le personnage
n'a pas à passer par deux états d'inactivité différents
entre le blocage et l'attaque. Si nous l'essayons, notre personnage peut passer à
l'animation
du bloc appuyant sur le bouton de
blocage et revenir au mode veille lorsque le
bouton de blocage est relâché. Mais il serait plus logique
de restreindre le personnage à n'utiliser cette animation s'il est équipé d'un bouclier. Pour ce faire, nous aurons besoin d'un autre script de
ressources. Hériter de l'équipement, en lui donnant le
nom de classe shield Si vous souhaitez que vos boucliers aient des variables différentes, nous
pouvons les définir ici. Ajoutons une variable pour le
montant des dégâts réduits en bloquant avec ce bouclier
avec une valeur par défaut de un. Accès à la ressource personnalisée Barbarian Round
Shields. Nous pouvons le transformer en bouclier et modifier le
montant de la réduction des dégâts si nous le voulons. N'oubliez pas de renseigner à nouveau
toutes les propriétés réinitialisées à la suite
de ce changement de classe et de mettre à jour tous les boucliers pour
utiliser le nouveau script de classe Dans la scène du bouclier, nous devrons être en mesure de
stocker les variables issues de la ressource objet dans le bouclier comme nous l'avons fait
avec l'arme. En ajoutant un nouveau script, il contiendra simplement une variable entière de
réduction des dégâts et une fonction fictive d'activation de
la boîte à hanche, qui ignorera l'
argument booléen et La raison pour laquelle cela
est nécessaire deviendra claire dans une minute. Nous pouvons ensuite remplacer le script attaché à notre bouclier
par le nouveau. Dans le script du personnage, ajoutons une autre variable à la catégorie d'équipement
pour savoir si le personnage possède ou non
un bouclier. Lorsque vous enfilez une
pièce d'équipement, s'il s'agit d'un bouclier,
nous le configurons comme un équipement original, nous
transmettons
la valeur de
réduction des dégâts de la ressource
de l'objet
au bouclier,
et le bouclier de l'ensemble est
équipé pour fonctionner. Comme la variable « off hand » consiste désormais à tenir un bouclier
au lieu d'une arme, si vous
interrompez les actions du
personnage toutes les boîtes à hanches
seront désactivées Et comme le off
hand n'est pas nul, nous lui demandons de
désactiver sa boîte à hanches. Mais nous avons demandé au bouclier
d'ignorer cette demande. Ensuite, lorsque vous retirez une
pièce d'équipement, si la prise est désactivée, nous pouvons supposer
que le personnage ne
tient plus Ensuite, lorsque vous demandez au
personnage de bloquer, nous pouvons ajouter la condition selon laquelle le personnage doit également être équipé
d'un bouclier. Le script d'inventaire
nécessitera également quelques conditions supplémentaires lors de l'
équipement d'un bouclier
afin d'empêcher le personnage
de s'équiper d'un bouclier alors
qu' afin d'empêcher le personnage
de s'équiper d'un bouclier alors est déjà occupé par une arme à deux mains
ou à deux mains Ce processus
varie en fonction du fonctionnement de votre inventaire et de vos systèmes d'
équipement. Si l'
objet sélectionné est un bouclier, le personnage a quelque chose d'équipé dans sa main principale, et que le personnage utilise
actuellement les animations à deux mains ou
à deux roues, alors je déséquiperai la prise
principale et je
demanderai au personnage de porter
l'équipement dans
sa main demanderai au personnage de porter principale Si on l'essaie.
Le bouton de blocage est désormais ignoré si le personnage ne possède pas d'équipement de bouclier. Nous pouvons équiper une arme
à deux mains, puis équiper le bouclier. L'arme à deux mains est automatiquement
déséquipée, puis le bouclier est équipé Et maintenant, le personnage peut
bloquer avec le bouclier. Voyons ensuite comment entrée
de blocage fonctionne
avec nos autres actions. Si le joueur bloque et décide d'
attaquer ou d'esquiver, je voudrais que
ces actions soient
prioritaires pour interrompre le blocage. Mais si nous définissons simplement la variable wants
to block sur false, le joueur
devra relâcher le bouton de blocage et appuyer à
nouveau dessus pour continuer à bloquer. Au lieu de cela, nous pouvons déclarer
une autre variable booléenne. Appelons cela un bloc d'interruption. Si le personnage
veut attaquer ou esquiver, cette variable
peut être définie sur true. Et lorsque l'attaque
ou l'esquive est terminée, nous pouvons la remettre
sur false pour permettre
au personnage de continuer à
bloquer automatiquement. Je vais simplifier la fonction d'ajout de vélocité d'
esquive pour simplement appeler Annuler l'esquive. Ensuite, dans l'arbre d'animation, nous pouvons ajouter les conditions
de transition hors bloc ou de blocage à inclure si le
bloc est interrompu. Et ne laissez pas les
transitions revenir au bloc tant que le blocage n'est
plus interrompu. Désormais, le personnage
arrête de bloquer pendant l'attaque
et
revient automatiquement au blocage tant que le bouton de blocage est
toujours enfoncé. Et il en va de même
pour l'esquive. La dernière chose
à faire est de réduire les dégâts causés par
les
attaques entrantes lors du blocage. Pour cela, nous devons savoir si le personnage bloque. Comme le blocage n'est pas limité à une seule animation et
aux boucles d'animation, nous ne pouvons pas simplement
demander à
l' animateur de définir une
variable booléenne sur true ou false Ajoutons l'animation Block
Hit. Activation de la transition
entre le
blocage et le retour à cette animation à
la fin de l'animation. Ce que nous contractons pour savoir
si le personnage bloque, c'est dans quel état se trouve actuellement
cette machine à états. S'il est
bloqué ou bloqué,
le bouclier du personnage est levé. L'animation du bloc
est également assez longue. Cela inclut non seulement le
soulèvement du bouclier, mais également un cycle de
blocage de l'animation. Je ne pense pas que le personnage doive
être considéré comme bloquant tant que le
bouclier n'est pas complètement levé, mais je ne veux pas non plus attendre la fin
de l'animation du bloc. Dans le lecteur
d'animation du personnage,
je vais donc réduire la durée de l'animation du
bloc pour qu'elle s'arrête une fois que le bouclier est levé
au tiers de seconde. Dans le script des arbres d'animation, ajoutons une
fonction publique pour vérifier si le personnage bloque et
renvoie une valeur booléenne Tout d'abord, le
nom de l'action indique le nœud actuel
dans une variable de chaîne. Nous pouvons revenir s'il s'agit d'un
blocage ou d'un blocage. Et nous aurons également besoin d'
une autre fonction pour exécuter l'animation de blocage, indiquant à l'état d'action de passer à l'état de blocage. Ensuite, dans le script du personnage, en haut de la fonction
Take Damage. Nous pouvons vérifier si l'animation du
personnage est actuellement bloquée et si
les dégâts proviennent de
l'avant du personnage. En utilisant un produit ponctuel de la direction des dégâts avec le vecteur de base
avancé du personnage Si la valeur est
positive, les dégâts
proviennent de quelque part devant eux. Cela couvrirait cependant un
grand angle, une demi-sphère complète
devant le personnage. En utilisant quelque chose
de plus proche du quart ou de la moitié, nous pouvons le limiter à une forme de cône. Dans ces
conditions, l'attaque doit être bloquée avec succès, réduisant le montant des dégâts par la réduction
des dégâts du bouclier. Utiliser la fonction max pour le
plafonner à un minimum de zéro. Nous pouvons ensuite demander
à
l'arbre d'animation de jouer l'animation bloquée, et si le montant des dégâts a été complètement réduit à zéro, je reviendrai simplement puisque le personnage ne
subit aucun dommage. Essayons-le.
Équiper le bouclier et bloquer l'attaque du
squelette Les dégâts sont réduits à zéro et l'
animation du bloc touché s'exécute. En subissant des dégâts par
le côté ou par le dos, le personnage
subit toujours des dégâts. Notre
personnage est désormais capable de bloquer les attaques avec un
bouclier placé de face. Dans la prochaine leçon,
nous leur donnerons une arme à distance
capable de tirer des projectiles Je te verrai dans la prochaine leçon.
10. Séance photo: Bonjour, mes amis. Dans
la leçon précédente, nous avons autorisé notre personnage à
bloquer les attaques avec un bouclier. Dans cette leçon, nous allons leur donner une arme
arrangée capable
de tirer des projectiles Ce pack d'actifs ne contient
pas de verrou pour arbalète Je vais
donc commencer par en créer
un dans la scène des arbalètes En commençant par un
nœud en trois D à corps
rigide , renommez-le boulon Je vais le positionner là
où la base du verrou reposera
à l'intérieur de l'arbalète avec son vecteur de base en Z bleu pointant vers l'avant, là où
il va tirer Ensuite, je vais ajouter une instance de maillage à
trois nœuds D en tant qu'enfant, en la remplissant avec
le maillage cylindrique Réduire le rayon et la hauteur, faire pivoter pour qu'il pointe vers l'avant et le positionner vers l'
avant le long de l'axe z. Je vais juste lui donner
un matériau de base et régler l'albédo
pour qu'il soit de couleur marron Ajoutez ensuite un
nœud de base en trois D comme autre enfant, afin qu'il soit placé avec
la même position et rotation et
renommez-le amo socket Reconnectez ensuite la douille Amo à l'arbalète en conservant cette
position et cette rotation Replacer le boulon par rapport
à la douille AMO, sorte que sa position et sa rotation par rapport à son
parent soient désormais nulles Le verrou peut maintenant être
transformé en sa propre scène, que je vais placer dans un nouveau
dossier pour les projectiles, puis le supprimer de la scène de
l'arbalète L'arbalète peut désormais
être chargée simplement en ajoutant un boulon en tant qu'
enfant de ce nœud Le verrou devra avoir
une forme de collision. J'utiliserai une capsule aux mêmes dimensions et à
la même
position que le cylindre. En élargissant la section du solveur, je devrai activer le moniteur de
contacts et régler le nombre maximum de contacts sur une
valeur supérieure à zéro Si nous voulons que le verrou
entre en collision avec le terrain, il devra masquer la première couche de
collision Et je veux que mes boulons
bougent lentement pour que je puisse
voir ce qu'ils font. Mais je ne veux pas qu'ils
tombent à cause de la gravité. Je vais donc régler leur échelle de
gravité à zéro. En attachant un script au verrou, nous pouvons le nommer projectile, afin qu'il puisse être utilisé pour d'autres
types de projectiles dans notre jeu et l'enregistrer dans
le dossier des scripts des objets Dès qu'un verrou
est instancié, il est chargé
dans l'arbalète Et nous souhaiterons peut-être
transmettre
des informations concernant le personnage ou l'arme aux munitions pour le moment. Créons une
fonction publique à cette fin. Mais pour l'instant, nous allons simplement régler sa propriété
de gel sur true, car le corps rigide
n'a
rien à faire avant
le tir de l'arme. Pour tirer le projectile, nous appliquerons une force d'impulsion envoyée par l'arme
sous forme de vecteur trois À ce moment, le corps
rigide peut commencer appliquer de la physique pour déplacer le
verrou dans la scène de jeu, en définissant sa
propriété de gel sur False. Nous ne voulons plus que le
projectile suive
les propriétés de transformation de
son parent, l'arbalète Il doit être replacé dans la scène
du jeu où il
peut se déplacer et agir librement S'il ne
pointe pas directement dans la
direction,
s'il est tiré, nous pouvons dire au verrou de
regarder un point dans l'espace correspondant sa propre position globale moins la direction
de la force d'impulsion. Appliquez ensuite la force d'impulsion
au boulon pour le faire bouger
dans cette direction. En reliant le
signal saisi par le
corps rigide au script, cette fonction sera appelée
si le boulon entre en contact
avec un objet situé sur la première
couche de collision, le terrain. ce cas, le verrou peut rester exactement là où
il est entré en contact,
rétablissant ainsi sa
propriété de blocage sur true, mais en différé puisque cela
se produit lors d'une collision. Il est très important que
chaque fois que vous implémentez une fonctionnalité dans un jeu qui instancie un grand
nombre de nœuds, vous implémentiez également un
moyen de les nettoyer. Sinon, vous pourriez vous retrouver
avec de très grandes quantités, ce qui entraînerait une baisse de la fréquence d'images et
éventuellement un crash de votre jeu. Une pratique courante
avec les projectiles consiste simplement à leur donner
une durée de vie maximale Ajoutons un nœud temporel à nos projectiles et réglons le compte
à rebours une Je vais le régler sur 10 secondes. Ensuite, saisissez une référence à l'heure ou au nœud
en utilisant add on ready. Nous démarrerons le chronomètre
lors du tir du projectile. S'il ne finit pas par
heurter quoi que ce soit, nous voulons tout de même le nettoyer, afin qu'il ne s'envole pas
au loin pour toujours. Connecter le signal d'augmentation du temps
au script du projectile. Cela indiquera que le projectile sera libéré de la scène de jeu en revenir à la scène de l'arbalète, nous aurons besoin d'un nouveau script
pour cette arme Nous pouvons l'appeler arme à distance et la placer dans le dossier des scripts des
objets Remplacez le script
attaché à cette arme par une arme à distance et donnez-lui une référence au fichier de
ressources personnalisé pour l'arbalète Nous pouvons exporter les munitions
sous la forme d'une scène pleine à craquer, d'un préfabriqué que nous pouvons utiliser comme plan pour en instancier
autant que nécessaire Ensuite, assignez le verrou comme munition pour l'
arbalète de l'inspecteur Nous aurons besoin d'une référence à
la prise de munitions utilisant at on ready et d'une référence aux munitions actuellement chargées dans l'arme à distance Il peut également être intéressant d'
avoir un bonus de dégâts que l'arme ajoutera
aux coups de feu tirés
sous forme de nombre entier. La
force d'impulsion que l'arme applique à ses munitions lorsqu'elle
est tirée à flot Je vais utiliser un chiffre faible,
comme dix, pour que nous
puissions voir facilement les
éclairs se déplacer dans les airs, et le masque de collision de nos
ennemis pour que les informations
puissent être transmises
du personnage à l'arme aux munitions. Lors de l'équipement de l'arme, les
personnages
configurent la boîte à hanches, masque de
collision des armes, afin que nous puissions facilement réutiliser la même fonction pour
définir la variable du masque Et comme nous l'avons fait
avec le shield, nous pouvons ajouter une fonction pour
activer le hip box, en ignorant ce paramètre,
et simplement revenir. Puisque l'arme
n'a pas de boîte à hanches qui lui est propre. L'arme
devra être capable de
tirer le projectile
avec une fonction publique, et nous laisserons le
personnage spécifier
la direction dans laquelle il
souhaite que le projectile aille
en tant que paramètre Il
suffit à l'arme de transmettre cet appel de fonction à l'
ampli, en multipliant la direction
par la force de l'arme Définissez ensuite la référence
amo chargée null puisque l'arme n'
est plus chargée, et une fonction de rechargement, qui instanciera
un nouveau verrou, attribuant Ajoutez-le ensuite en tant qu'enfant
de la douille Amo, en lui donnant la
bonne position et rotation nécessaires pour qu'il tienne
bien dans l'arbalète Nous pouvons ensuite
transmettre toutes
les informations dont les munitions auront besoin avant d'
être tirées, comme les dommages causés par les armes
et le masque de collision. Allons-y
et ajoutons-les en tant que paramètres à la fonction
onload dans le script du projectile Le script de notre personnage
aura besoin d'une variable pour savoir si l'arme qu'il
détient est actuellement chargée. Et deux nouvelles fonctions :
recharger et filmer. Rechargez, il suffit de définir
la variable sur true, puis de demander à l'arme de
main principale de la recharger Pour l'instant, Shoot
définira simplement la variable sur False, puis indiquera
à l'arme principale de tirer dans une direction, passant le vecteur de base
vers l'avant du personnage Si l'arme n'est pas équipée, puisqu'elle est complètement
supprimée de l'arbre des scènes, les munitions seront également
retirées en même Je vais donc simplement remettre la variable Arme is Loaded à
False à ce stade. énumérer les types d'armes, nous aurons besoin de deux entrées supplémentaires pour la gamme d'attaques à une main, qui sera numéro quatre, et attaques à distance à
deux mains, numéro cinq Dans la ressource
personnalisée sur les arbalètes, je vais changer le script
de l'équipement à l'arme Je vais changer son
type d'arme à portée d'une main, réduire ses dégâts et
repeupler son icône. De même, passez l'arbalète lourde
à deux mains. Dans l'arbre
d'animation des personnages, nous aurons besoin de plus d'actions
pour les attaques à distance. Cette machine à états est déjà assez
volumineuse et désordonnée. Je vais
donc intégrer les attaques
à distance dans une autre machine à états En passant à
cette machine à états, si les personnages attaquent animation est de
quatre ou cinq, qu'ils veulent attaquer, ne sont pas touchés
et qu'ils n'esquivent pas Revenez ensuite au mode veille à
la fin de l'animation. Et je vais mélanger les deux transitions
avec un peu de fondu croisé. À l'intérieur de la zone de tir pour
attaquer State Machine, nous pouvons ajouter des animations pour le
tournage et le rechargement Aussi bien pour les attaques à distance à une main que pour les attaques à
deux mains. Il suffit de jouer le
bon jeu une seule fois
, puis de revenir à la machine à états
d'action. Ils feront donc tous
la transition à la fin. Pour passer à une main l'
animation de l'attaque doit être réglée sur quatre. Et le jeu à deux mains est réglé f. La
valeur de l'arme chargée
déterminera si les animations de tir
ou de rechargement sur
f. La
valeur de l'arme chargée
déterminera si les animations de tir
ou de rechargement seront jouées Maintenant que les animations peuvent être jouées par l'arbre d'animation, nous avons besoin des animations pour appeler des fonctions dans le script du
personnage. Pendant le tournage de l'animation, nous ajouterons une méthode, une piste d'appel et un gommage à l'image avant que le personnage ne recule devant
le projectile tiré Ajoutez ensuite une image clé pour
appeler la fonction de prise de vue. De même, lors de l'animation de
rechargement, nous essaierons de
sélectionner une image lorsque le personnage aura fini de
recharger l'arme Et ajoutez une image clé à la piste de la méthode d'appel pour recharger
réellement l'arme Si nous voulons que ces
animations empêchent le personnage d'effectuer d'
autres actions, nous devons définir
une variable booléenne,
comme nous l'avons fait pour les attaques Je vais simplement réutiliser la variable
d'attaque. Et répétez
également l'opération pour les animations à distance à deux
mains . Essayons-le. Nous pouvons équiper le personnage d'une arbalète
, et en appuyant une fois sur le bouton d'
attaque, nous lui demanderons de charger l'
arbalète avec un En appuyant une seconde fois sur
le bouton d'attaque, ils tirent l'arbalète vers l'avant, et le verrou jaillit jusqu'à ce qu' il touche un
objet dans l'environnement, où il s'arrête et
se détruit au bout de 10 secondes. Nous avons maintenant besoin des boulons pour
infliger des dégâts aux ennemis. revenir à la scène du verrou, nous
devrons ajouter une
case de frappe au verrou. La zone de frappe doit avoir la forme
d'une collision. Je vais utiliser la sphère. Je vais le positionner à
l'autre bout
du boulon et lui donner
un rayon plus petit. Tout comme nos autres boîtiers branchés, il n'est pas nécessaire qu'il soit surveillé ou qu'il soit encore équipé d'un masque anticollision. En saisissant une référence à la boîte à
hanches en utilisant at on ready, exportons également une variable indiquant l'endommagement
des boulons Je vais utiliser une valeur par défaut de un. Lorsque le personnage place le verrou dans
l'arbalète,
c'est personnage place le verrou dans
l'arbalète, une bonne occasion transmettre des informations, telles que les bonus de dégâts
et le masque de collision Le bonus de dégâts infligés par les armes peut être ajouté
aux dégâts infligés par les boulons, et la couche de
collision de la boîte à hanches peut être réglée sur la couche de collision
ennemie du personnage. Lorsque le projectile est tiré, nous pouvons demander à la boîte à hanches de commencer à surveiller les nichoirs ennemis En connectant la zone de la hanche signal
est entré dans le script du
projectile Nous pouvons indiquer à la boîte à blessures
que ce projectile a touché pour indiquer à son
personnage parent de subir des dégâts À partir de la direction de la position globale des cases
Hurt
moins la
position globale du Bolt normalisée. Le verrou peut ensuite être
retiré de la scène. Et si le verrou touche le terrain, il ne devrait plus être
surveillé pour infliger des dégâts Nous le réglerons
donc sur un
faux différé. Dans le script du personnage,
je voudrais m'
assurer que lorsque le personnage est
bloqué sur une cible, le projectile est tiré
directement sur cette cible Ainsi, la fonction de tir
se divise en deux comportements différents selon que le personnage
est bloqué ou
non sur une cible, appelant une fonction distincte
pour tirer sur une cible, en passant la cible
comme argument. Mais l'arme ne
doit tirer sur la cible verrouillée que si le
personnage lui fait face. Nous pouvons donc vérifier si
le produit scalaire
du vecteur de base
avancé des personnages et de la différence normalisée leurs positions globales
est un nombre positif Plus c'est
positif, plus ils se ressemblent,
plus le personnage est
tourné vers eux. Je dirais qu'un objet supérieur à 0,75 est suffisamment proche pour atteindre
la cible verrouillée Dans le script d'arme à distance, donner une définition du tir sur
cible, accepter une cible
comme paramètre Nous pouvons maintenant calculer la
direction sous la forme de la différence entre les positions d' affaissement normalisée
et multipliée par Comme cela utilisera la position gubale de l'
arme, non la position
gubale du personnage, la direction
sera plus précise Et je vais ajouter 1 mètre à la position de la cible pour
ne pas viser ses pieds. Essayons-le.
En m'équipant d'une arme et en m'accrochant à une cible, je vais d'abord faire face
sur le côté, et le projectile
continue de tirer vers l'avant, puisque le personnage
n'est pas face à En se déplaçant pour faire face à la cible
et en tirant un deuxième éclair, il tire
cette fois directement sur la cible et inflige des dégâts. Nous avons maintenant des projectiles
tirés à distance qui
touchent des ennemis ou Dans la prochaine leçon, nous allons autoriser les ennemis à détecter les
joueurs et à riposter. Je te verrai dans la prochaine leçon.
11. Ennemi: Bonjour, mes amis. Dans
la leçon précédente, nous avons ajouté des attaques à distance
qui tirent des projectiles Dans cette leçon, nous allons
autoriser les ennemis à détecter, poursuivre et attaquer le personnage du
joueur. Dans la scène du cimetière, nous avons ajouté un simple
nœud qui indique l'ennemi d'attaquer constamment Supprimons cela
et commençons à créer une version plus complexe pour n'
attaquer que lorsque le personnage du joueur
est à portée d'être touché. Dans la scène des sbires squelettes, nous y ajouterons un nœud enfant de type nœud trois D, car il devra accéder à trois positions et rotations en D. Je vais appeler ça de l'agressivité. Ajoutez ensuite un nœud de zone 3 D, qui représentera la portée d'attaque de l'
ennemi. Je vais lui donner une
forme de collision et utiliser une sphère. En ajustant la taille de la
sphère pour qu'elle soit un peu plus grande, je lui donnerai un
rayon de 1 mètre, puis je la positionnerai à 1 mètre du sol
et à 1 mètre vers l'avant. La zone de portée d'attaque
surveillera les collisions masquant
le coffre du joueur. Attachons un script à ce nœud et
placons-le dans le dossier des scripts ennemis. Le but de ce
script étant de contrôler un personnage de la même manière que le nœud du gestionnaire d'entrées du
joueur, nous aurons besoin d'une référence
au personnage contrôlé par ce nœud Compte tenu de la façon dont je structure
mon arbre de scène, ce nœud sera toujours l'enfant direct
du nœud du personnage Je peux
donc accéder au personnage
en appelant get parent En connectant les signaux de
zone entrée et de zone sortie
au script, je vais renommer les paramètres et leur donner des types pour Lorsque la boîte à
blessures du personnage du joueur entre dans
la zone d'attaque, nous voulons dire à l'
ennemi d'attaquer. Et lorsque la boîte Hert
sort de la zone d'attaque,
nous pouvons dire à l'
ennemi de ne pas attaquer Nous pouvons enregistrer cette branche en tant que scène à part
entière et l'enregistrer
dans le dossier des scènes ennemies. Supprimez-le ensuite de
cette scène ennemie. E De retour dans la scène du cimetière, nous pouvons associer notre
nœud d'agression
ennemi à l'un ou à l'ensemble
de nos ennemis pour qu'ils attaquent
automatiquement le personnage
du joueur s'il entre dans la zone d'attaque Essayons-le.
Les ennemis n'attaquent pas encore, mais nous attaquerons si nous entrons dans
leur zone d'attaque et nous nous
arrêterons lorsque nous la quitterons. Ensuite, nous allons permettre
aux ennemis de voir le personnage
du joueur de plus loin. En ouvrant la scène du nœud d'
agression, nous pouvons ajouter un autre nœud de zone en
trois D pour représenter la vision
d'un ennemi. En ajoutant une
forme de collision à cette scène, j'utiliserai une autre sphère
avec un rayon beaucoup plus grand. Je vais utiliser 5 mètres et le positionner de manière à ce qu'il devance l'ennemi et un
peu au-dessus du sol. Cette zone peut surveiller couche
de
collision du personnage du joueur. J'utiliserai la couche 9. Ajoutez ensuite un nœud à trois
points en D pour leur ligne de visée et déplacez-le vers le
haut hors du sol. Cela recherchera la même couche que
le champ de vision, mais sera également obstrué
par le terrain Comme j'ai utilisé la couche 9, qui correspond au
corps du personnage et non à la boîte en T, je vais relier les signaux entrés
et sortis sur
le corps au script d'agression Lorsqu'un corps entre dans
le champ de vision, je le stocke dans une variable, nommons-le cible de
type personnage corps trois D. Mais nous
devons également confirmer qu'
il a également une ligne de
visée claire avant de
devenir agressif. Nous aurons donc besoin d'une
référence au casting. Et nous pouvons enregistrer si l'ennemi
a vu le joueur
ou non dans
une variable booléenne Faisons également référence
au champ de
division de l'ennemi. R. En utilisant la fonction de processus, nous pouvons commencer par vérifier si la valeur de la cible
a été définie. S'il est nul, l'ennemi ne peut pas voir
le personnage du joueur. Nous devrions simplement
rentrer. Si l'ennemi n'
a pas encore vu le joueur, nous pouvons vérifier sa ligne
de visée par rapport à la cible. Définissez la position cible
du raycast comme étant la différence entre leurs positions
globales, en ajoutant un mètre
au-dessus du sol Après avoir forcé le raycast à se
mettre à jour s'il entre en collision avec un objet et si l'objet
avec
lequel il entre en collision est la cible,
la ligne de visée
n'est pas obstruée Nous pouvons définir la variable has seen
player sur true. Si la valeur de cette
variable est vraie, le
comportement de l'ennemi changera et nous lui demanderons de poursuivre
le personnage du joueur. Lorsque le personnage du joueur quitte le champ de vision de l'ennemi, si le corps est la cible et que l'ennemi n'a pas
encore vu le joueur, nous n'avons plus besoin de
vérifier sa ligne de visée, nous pouvons
donc définir la cible sur zéro Ce nœud d'agression est un
enfant du nœud personnage, qui ne tourne pas. Le champ de vision et la portée d'
attaque ne changeront donc pas en
fonction de la configuration du personnage. Nous pouvons utiliser la référence du
caractère pour saisir la rotation de l'anneau, accéder à la propriété y et l'affecter à la rotation y de
ce nœud. Il suivra donc
la même rotation. Nous voudrions peut-être aussi trouver un moyen de dire à cet ennemi d'arrêter de poursuivre
le personnage du joueur. Dans ce cas, nous pouvons
définir la cible sur null, avoir vu la cible sur false et dire à ce personnage de
se déplacer sans direction. Le bon moment pour appeler cette fonction serait lorsque l'ennemi meurt. Donc, remplacez la fonction
Ready. Nous pouvons connecter le signal
mort de ce personnage à la fonction
d'arrêt. Lorsque l'ennemi voit le personnage
du joueur pour la première fois, nous pouvons également associer le signal de mort de
la
cible à la fonction d'
arrêt pour empêcher l'ennemi
d'essayer de tuer le personnage
du
joueur qu'il est déjà mort. J'utiliserai également cette même fonction pour désactiver la vision de cet ennemi, en définissant sa
propriété de surveillance sur False. Pour que l'ennemi puisse
se déplacer vers le joueur, nous devons d'abord apporter quelques
modifications à notre scène de niveau. Ajoutons un nœud en
trois D de la région de navigation au niveau. Reparentez ensuite tous les nœuds
qui seront utilisés pour générer notre carte de navigation
en tant qu'enfants de ce nœud, y compris le sol
et les obstacles. fois cela fait, sélectionnez le nœud de la région de
navigation et remplissez le
maillage de navigation avec un nouveau maillage de navigation Cliquez ensuite sur le bouton du maillage
de navigation Bake. Le maillage de navigation couvrira
le terrain avec des triangles qui formeront une zone où les personnages pourront marcher. En élargissant la ressource de
maillage de navigation, nous pouvons voir ses propriétés. La seule section
préoccupante à l'
heure actuelle est la section des agents. Les agents sont nos
personnages qui
utiliseront ce maillage de navigation
pour se déplacer dans la scène. En jetant un coup d'œil aux capsules de collision de nos
personnages, je leur ai donné une
hauteur de 2,6 mètres et un rayon de 0,75 mètre Je vais copier ces valeurs dans la hauteur et le rayon de l'agent dans la ressource de
mesure de navigation, puis redéfinir le maillage de navigation Le maillage laisse désormais plus d'espace
entre les murs et les obstacles. Pour utiliser la région de
navigation, nos personnages auront tous besoin d' un autre nœud attaché à eux, un nœud tridimensionnel de l'agent de navigation. Assurez-vous d'en attacher
un à chaque personnage. Saisir une référence à ce
nœud à l'aide de la commande add on ready. Nous pouvons ensuite écrire une fonction
dans le script de caractères, qui peut être utilisée pour indiquer à
n'importe quel personnage de naviguer
vers n'importe quel endroit du maillage de
navigation pour une raison quelconque. C'est également très utile pour de nombreuses choses en dehors du combat. En acceptant une position cible
comme vecteur trois, nous allons définir la position
cible de l'
agent de navigation comme étant la même position. L'agent de navigation utilisera automatiquement
le maillage de navigation, auquel est affectée la même couche de
navigation, pour créer un chemin permettant de se rapprocher le plus possible de l'
emplacement cible. appelant les agents à obtenir la position du chemin
suivant, nous allons renvoyer le premier point de chemin le long de ce chemin sous la forme
d'un vecteur trois. Nous pouvons ensuite soustraire
la position globale
actuelle du personnage pour obtenir un vecteur pointant
de l'endroit où nous nous trouvons vers la première
position le long du chemin Si nous le multiplions par 101 pour supprimer la composante
verticale, normalisons ce vecteur. Il est désormais fonctionnellement équivalent à un
vecteur d'entrée produit par notre
script de gestion des entrées du lecteur lorsque le joueur incline le stick analogique ou
utilise les touches WASD Nous pouvons donc l'attribuer à la variable de direction
d'entrée. Et le processus physique
s'occupera du reste, demandant au
personnage de suivre ce chemin, qui le guidera vers
sa cible. Ce serait une bonne idée de transférer tout ce qui arrive
à un personnage
lorsqu'il meurt dans une
fonction publique au cas où autre
chose que le fait de subir des
dégâts pourrait entraîner sa mort. Quand un personnage meurt, il
faut lui dire
d'arrêter de bouger. Et lorsqu'on leur demande
de bouger ou d'agir, nous devons ignorer ces demandes si le personnage est
mort en revenant. en revenir au scénario d'agression, il suffit de
dire à l'ennemi de se
diriger vers sa cible
une fois qu'il l'a vue. Avant de l'essayer,
choisissons un ennemi. Je vais utiliser le guerrier squelette et sélectionner son nœud 3D
Agent de navigation. Dans la section D Bug, cliquez sur le bouton d'activation pour voir le chemin
affiché dans le jeu l'approche du premier squelette, dès que nous entrons dans
son champ de vision, la ligne de visée
confirme immédiatement qu'il peut nous voir, et l'agent de navigation trouve un chemin pour que l'ennemi puisse marcher
vers nous. Alors, attaque-nous.
En battant cet ennemi, cette fois, attirons
l'attention du voleur Comme ils se trouvent derrière
la pierre tombale, ligne de visée n'
est pas confirmée et l'ennemi reste caché Et si nous nous approchons du guerrier, nous pouvons courir autour de
la tombe ouverte voir comment l'agent de
navigation mettra automatiquement à jour
le chemin en temps réel, afin de contourner le chemin le plus court possible pour
atteindre le joueur. Nous voudrions peut-être aussi que nos ennemis soient capables de manier des armes Revenons à la scène du cimetière, attachons un autre
nœud de base à l'un de nos ennemis
et nommons-le et nommons-le En joignant un script à ce nœud, je le mettrai dans le dossier des scripts de l'
ennemi. Il suffit de saisir une
référence au nœud parent,
le personnage, et d'exporter une arme à équiper
pour ce personnage. Ensuite, dans la fonction Prêt, dites au personnage
de manier l'arme. Je vais demander à mon guerrier squelette
de s'équiper d'une belle hache. Copiez et collez ensuite
ce nœud sur un autre ennemi et remplacez l'
arme par autre chose. Je vais donner des couteaux au voleur. d'attache osseuse devront être ajoutés
à chacune de nos
scènes ennemies nœuds d'attache osseuse devront être ajoutés
à chacune de nos
scènes ennemies. En suivant leur
fente gauche et leur fente droite. Nous pouvons ensuite remplir le tableau de
prises d'équipement des
personnages avec ces nœuds à utiliser
lors de l'équipement Enfin, ce serait
bien de ne pas avoir à recharger le jeu à notre mort. Connectons donc le signal
mort du personnage du
joueur au script du
game manager. Une fois passé au noir,
je vais simplement demander
à l'arbre des scènes de recharger la scène en cours, en
rétablissant le tout comme
il était lors du premier je vais simplement demander
à l'arbre des scènes de recharger la scène en cours, en
rétablissant le tout comme chargement de la scène Essayons-le.
Le guerrier squelette est équipé
du grand A et utilise les animations d'
attaque à deux mains. Quand on meurt, toute la
scène est rechargée. Et pour affronter
le voleur cette fois, ils sont
équipés de couteaux et utilisent des animations à deux roues Nous avons maintenant un
système de combat complexe dans notre jeu avec une variété de
mécanismes qui peuvent être ajustés en fonction des
besoins de votre jeu.