Godot, 1000 petites choses

Récemment découvert le moteur Godot, un moteur de jeu open source. Je partage quelques astuces et notes, principalement à partir de la zone 3D, du code ou des points généraux.





Godot, en général, a la réputation d'être plutôt un moteur 2D, ce qui a été assez bien élaboré, mais il n'y a pas si longtemps, les fonctionnalités 3D nous permettent de faire des jeux 3D. Surtout si vous êtes en mesure d'optimiser certaines choses par vous-même, ne faites pas un jeu trop lourd et complexe, et vous êtes également satisfait des options de rendu actuelles. Ou vous pouvez attendre les optimisations futures et l'apparition de vulkan.



Hors de la boîte, le moteur a un peu de physique, y compris les articulations et les véhicules à roues. Il n'y a pas d'éditeur de terrain intégré, mais vous pouvez utiliser un plugin, importer à partir de programmes spécialisés ou simplement en tant que maillage à partir d'un package 3D. Dans ce dernier cas, pour des raisons de productivité, vous devrez couper indépendamment le paysage en fragments, et très probablement en faire des maillages séparés pour les collisions. En ce qui concerne les maillages pour la forme de la collision du paysage - pour qu'il n'y ait pas d'incohérences visuelles, vous devez trianguler le modèle lors de l'exportation à partir du package 3D. Par exemple, l'un des moyens les plus simples de faire cela dans Blender est d'exporter le maillage au format collada (.dae), il y a une case à cocher trianguler par défaut.

Parfois, le modèle Blender devra être retourné à 180 degrés à l'intérieur de Godot, alors ne soyez pas surpris si votre terrain n'est pas visible - il est très probable qu'il soit tourné par les normales dans la mauvaise direction.



Godot pratique l'approche «tout est une scène» et est adapté à la structure arborescente des éléments. En pratique, cela signifie que de nouveaux objets à un niveau sont ajoutés en tant que branches aux nœuds qui y existent déjà, ils peuvent être réduits en préfabriqués et ouverts séparément, comme s'il s'agissait de leur petit monde local séparé. Ainsi, il est très pratique d'éditer toutes sortes d'objets composites enregistrés, la seule chose est que si la lumière était exposée à votre niveau, alors, par exemple, en entrant dans le personnage, dans sa scène locale, vous ne verrez pas cet éclairage et en mettant en place ses matériaux, vous ne comprendrez pas à quoi ils ressemblent lumière. Ce problème peut être résolu de différentes manières, par exemple, en passant à la fenêtre de niveau et en évaluant les changements qui ont lieu avec le personnage, après y avoir enregistré sa scène. Ou jetez simplement temporairement la source de lumière à l'intérieur du préfabriqué avec le personnage.





theEnergy, . Area, , , .



En ce qui concerne les langages, mis à part la méthode de bas niveau, les options les plus courantes sont les langages de script GDScript et C #, ainsi que le script visuel pour quelque chose de simple. GDScript est mieux intégré au moteur, a plus d'exemples, ne nécessite pas le lancement d'un environnement externe, et en termes de structure générale, tout se passera ici comme dans la version C # - déclarer des variables, appeler une fonction d'initialisation, une boucle de processus, une boucle de processus physique, etc. Il est donc logique de choisir GDScript comme principal langage de développement de scripts. En passant au C # local, nous ne pouvons qu'obtenir plus de précision et de détail de l'enregistrement, perdant sa concision, mais augmentant l'intelligibilité et le contrôle de la situation - accolades au lieu d'utiliser des tabulations, des sauts de ligne, une frappe plus formelle.





Code attaché à l'objet susmentionné (en GDScript). Une variable identifiant est mise en place, dont la valeur peut être définie dans l'éditeur, puis une fonction d'initialisation ponctuelle dans laquelle rien de spécial ne se produit (et il était possible de l'effacer). Ce qui suit décrit une méthode de gestionnaire de signal qui doit supprimer un objet.



Quant aux variables globales, afin de les utiliser, à la fois en GDScript et en C # il faudra ajouter un script global / scripts à charger automatiquement dans les paramètres du projet, dont les variables sont accessibles globalement.

Il existe également une restriction dans Godot - chaque objet ne peut pas avoir plus d'un script. Mais ce moment peut être contourné, par exemple, en suspendant le deuxième script sur l'objet enfant.



Signaux



Vous pouvez également utiliser une hiérarchie pour échanger des données entre les nœuds de Godot, car les objets sont attachés les uns aux autres, comme des branches à un arbre. Certes, cette approche a ses pièges, car dans notre jeu, la hiérarchie peut être dynamiquement variable. De plus, se référer à la hiérarchie au sein d'une même scène est une chose, mais lorsque vous avez une scène à l'intérieur d'une scène à l'intérieur d'une scène, cela pose quelques difficultés, même si c'est purement pour comprendre ce qui se passe.

Une façon de gérer tout cela et de ne pas trop s'attacher à une hiérarchie actuelle spécifique est par le biais de signaux. Un certain nombre de signaux communs est déjà pré-installé - vous pouvez regarder dans le panneau de signal de l'objet pour attacher une ligne avec le traitement de la réception de l'un d'eux dans un script du même objet ou d'un autre objet avec un script dans la scène. Si vous avez besoin de faire votre propre signal, alors vous le faites comme ceci:





Nous commençons le signal Nous l'émettons



dans le même script quand un bouton est enfoncé ou dans d'autres conditions



Tout va bien avec cela, tant que vous n'avez pas besoin de transférer des signaux d'une scène à une autre. Par exemple, parce que vous codez un niveau à partir de scènes et que vous avez besoin de savoir quand vous devez détruire le niveau actuel et, par exemple, assembler le suivant.

Dans ce cas, juste au moment de construire le niveau avec un code, vous pouvez attacher un gestionnaire de signal à l'objet qui enverra le signal à la scène racine. Ainsi, nous, pour ainsi dire, démarrons un agent espion dans cette branche générée et écouterons ce qu'il nous dit.





Au moment de l'assemblage du niveau, nous trouvons un vaisseau spatial dessus et nous nous cramponnons à l'auditeur du signal, indiquant la méthode dans laquelle nous traiterons les messages de ce signal.



Vous pouvez également associer certaines variables au signal, ce qui peut être très utile. Par exemple, au lieu de démarrer différents signaux sur l'objet, nous pouvons en faire un, mais nous l'enverrons avec différents paramètres et le traiterons en plus à la réception.





Et voici la description de la méthode elle-même, que nous avons commencée plus haut. En recevant un signal, il traite la variable envoyée avec lui.



Une autre chose utile qui réduit le nombre de signaux inutiles est qu'au lieu d'envoyer un signal personnel, un objet peut frapper un autre pour qu'il envoie le signal déjà enroulé en lui. Par exemple, une explosion reçoit un signal indiquant qu'elle a touché un joueur et, dans le gestionnaire de signaux, découvre si le joueur a une méthode d'autodestruction, la lançant si elle est trouvée. Le joueur, dans cette méthode appelée, envoie un signal à la scène racine qu'il est mort. Dans le script de la scène racine, le gestionnaire de signal de mort du joueur efface le monde et assemble le menu du jeu.





Un événement se produit et nous cherchons à voir si l'objet qui est entré dans la zone a la bonne méthode.





, , . , , .



CSG-





L'un des outils 3D utiles de Godot est les primitives de géométrie solide constructive. Autrement dit, ce sont des objets qui prennent en charge les opérations booléennes - intersection, exclusion, union. En plus de l'ensemble des primitives, il existe un maillage CSG universel, pour lequel un maillage arbitraire peut être défini comme forme.







Le mannequin CSG Combiner sera nécessaire pour une utilisation dans une hiérarchie pour contrôler la priorité des opérations lorsqu'il est nécessaire d'assembler une structure complexe.





Une paire de sphères à partir desquelles des sphères d'enfants sont sculptées.



L'application principale de CSG est la commodité et la simplicité du prototypage de la statique de niveau et de certains de ses éléments. En fait, vous pouvez créer un maillage dans un package 3D et y répéter les mêmes formes résultantes, sauf si vous devez le faire en dehors de l'éditeur de jeu.



La prochaine application des CSG statiques est de simuler la destructibilité et les dommages. pour ce faire, vous devez organiser les primitives CSG en mode d'exclusion, comme les trous, les «stubs» et les bosses, puis les masquer temporairement, y compris la visibilité au bon moment. La limite ici est que nous ne pouvons «endommager» que la surface de l'objet CSG, et en outre, le «dommage» doit d'abord y être attaché en tant qu'enfant ou attaché via un code en tant que descendant. Mais cette option en termes de flexibilité de configuration gagne déjà de manière significative par rapport à l'objet destructible préparé dans le package 3D.





Il y a 3 cylindres intégrés dans le pont en mode d'exclusion. Tant qu'ils sont cachés, le pont est intact.



S'il est activé, la zone qu'ils excluent est découpée.



Ensuite, nous avons le CSG en mouvement. Par code ou animation enregistrée. En général, grâce à cette méthode, vous pouvez implémenter certains effets, mais il est très souhaitable que de telles animations ne tournent pas sur la scène en boucle. Plusieurs CSG animés peuvent avoir un impact significatif sur les performances.En outre, Godot n'optimise pas tout, et si vous ne désactivez pas vous-même les CSG animés, ils continueront à consommer des performances hors de la vue de la caméra.

Néanmoins, les effets des CSG animés sont déjà difficiles à remplacer par des solutions de package 3D, vous pouvez donc être intéressé à les utiliser (du moins si vous n'allez pas dessiner de la 3D avancée via du code). L'essentiel est de leur trouver la bonne application, il est préférable de les utiliser ponctuellement, à certains endroits, y compris l'animation de déclenchement. Comme effet d'ouverture d'un passage ou autre effet spécial ponctuel. Naturellement, plus la forme des objets CSG est simple, mieux c'est. Et ils exercent la charge de calcul principale précisément dans le processus de contact en mouvement, de plus, il n'y a pas de différence particulière quel objet est déplacé par rapport à un autre.





Il y a un moment dans la vidéo où la voiture tombe à travers un trou dans le pont, quand une capsule CSG animée passe à travers un CSG Mesh avec un modèle du pont.



Multimesh





Si vous avez besoin de répliquer un maillage en grandes quantités, par exemple en dispersant des pierres ou des arbres à travers le niveau, le nœud MultimeshInstance est utile ici.

Après avoir ajouté le multimesh à la scène, vous devez spécifier sur quel objet disperser les copies et ce qu'il faut prendre comme échantillon pour les clones. En cours de route, vous pouvez choisir la taille des clones et leur nombre. Lorsqu'un multimesh est "cuit", il s'agit d'un ensemble de clones, et les cibles qu'il a utilisées pour le générer peuvent être supprimées si elles ne sont plus nécessaires.





Un bouton de sélection des cibles multimédias apparaît dans la fenêtre de l'éditeur en haut à droite lorsqu'il est sélectionné. Si vous appuyez dessus, cette fenêtre avec les paramètres de génération disparaîtra.





Ici, nous avons deux objets ajoutés à la scène en tant que nœuds MeshInstance. Ensuite, nous clonerons l'objet gauche vers la droite.





Nous obtenons multimesh. Dans cette situation, 10 000 clones ont été définis dans les paramètres. Soit dit en passant, s'il y en avait 3 à 4 000, le résultat ne différerait pas beaucoup.



Le multimesh "cuit" peut être déplacé n'importe où, et en plus, il a un paramètre Instance visible qui affiche initialement le nombre de clones spécifié lors de la génération. En modifiant cette valeur, vous pouvez contrôler le nombre de clones actuellement affichés. Par défaut, c'est -1, mais c'est une valeur spéciale pour afficher le nombre maximum de clones. Si vous mettez 10, il y aura 10 clones. Si 100, puis 100. Si le maximum était 50, alors à 100 et à 1000, et à -1, ils resteront 50.

Cette fonction multi-encoche peut être utilisée pour créer des effets spéciaux en animant le paramètre Instance visible via du code ou une animation enregistrée. Pour un contrôle plus fin de la densité des clones, vous pouvez utiliser le package 3D pour créer un maillage séparé avec un maillage solide exactement aux endroits où la densité maximale de clones est nécessaire, et les endroits où ils ne devraient pas être ne devraient pas être recouverts de polygones, ou y faire des lacunes.





Nous définissons l'instance visible sur 500 et la densité de remplissage diminue considérablement.



Divers





Le contrôle dans Godot peut être configuré en ouvrant l'élément Projet dans le panneau supérieur de l'éditeur. Ensuite, Paramètres du projet , onglet Liste des actions .





Vous pouvez voir comment les boutons par défaut sont appelés pour savoir par quels noms ils sont accessibles via le code. Et ajoutez également le vôtre.



Par exemple, pour le bouton PgUP, le nom par défaut est «ui_page_up», et vous pouvez le gérer en appuyant sur le code dans la ligne suivante dans GDScript - if Input.is_action_pressed («ui_page_up»):

si vous avez besoin d'une action pour un seul clic, alors is_action_pressed doit être remplacé par is_action_Just_pressed. La fin du pressage - pressé passe à relâché.



#



Si vous avez besoin d'animer le scintillement d'un matériau, vous pouvez le faire via un shader auto-écrit. Pour ce faire, sélectionnez New ShaderMaterial comme matériau d'objet.









Ensuite, sélectionnez VisualShader dans le champ vide.





Cliquez dessus, l'éditeur visuel s'ouvre sous l'éditeur.



Ajoutez une paire de nœuds, d'abord Input - All - Time , puis Scalar - Common - ScalarFunc , en le définissant dans sa liste déroulante, par exemple, Péché. En principe, une telle conception donnera déjà quelque chose comme un scintillement entre le noir et le blanc, mais pour mieux, ajoutez un autre nœud Scalar - Common - ScalarFuncet choisissez Abs là-bas. Nous connectons les nœuds les uns aux autres (notez qu'en cliquant sur l'œil fermé de chaque nœud, vous pouvez l'ouvrir et voir comment l'image change à chaque étape) et les connecter au canal Alpha, Emission ou Albedo. Voilà, notre objet scintille maintenant.







Naturellement, c'est loin d'être le seul moyen, mais l'une des options très simples. Et si vous voulez que le scintillement soit coloré, vous devrez créer quelques nœuds avec de la couleur, les mélanger dans un nœud spécial (face à Albedo) et y attacher la sortie de cette chaîne de nœuds que nous avons collectée ci-dessus. Ainsi, cette chaîne agira comme un facteur de mélange pour ces couleurs.



#



Pour transformer le nœud sélectionné en une scène séparée, vous devez cliquer dessus avec le bouton droit de la souris et sélectionner "Enregistrer la branche comme scène". Définissez ensuite un nom pour cette scène. Après cela, l'icône «Ouvrir dans l'éditeur» apparaîtra à côté du nom du nœud, d'où vous pourrez procéder à l'édition de la scène résultante dans une nouvelle fenêtre.

Pour effectuer la manipulation inverse, si, par exemple, nous avons besoin d'obtenir les objets de la branche enregistrée dans la scène actuelle afin de les reconstruire ou de les modifier, faites un clic droit sur un tel nœud qui cache la scène en elle-même et sélectionnez l'élément "Rendre local". La scène sauvegardée, qu'il a représentée, n'est pas détruite.



#



Pour utiliser des variables globales, vous devez créer un script et le déposer dans le chargement automatique: Projet -Paramètres du projet - Démarrage . Un singleton doit être vérifié.





Le contenu du script SaveTheWorld, dont nous voulons utiliser les variables comme globales. Pour le moment, un certain indicateur de santé et un ensemble d'états ennemis sont annoncés ici, qui sont remplis à l'étape d'initialisation.



Pour faire référence à ces variables globales à partir du code, vous devez d'abord obtenir une référence au singleton, puis utiliser ses variables:





Trouvez notre SaveTheWorld, puis vérifiez si l'état de cet ennemi particulier est zéro. Si c'est le cas, l'ennemi est retiré.



UPD. Vous pouvez accéder aux variables d'un singleton directement via son nom, c'est-à-dire que dans l'exemple ci-dessus, nous n'aurions pas à prendre de lien, et au lieu de main.enemy_arr [myID] nous ferions référence à SaveTheWorld.enemy_arr [myID]. Mais vous devez être sûr que ce nœud a une coche dans la colonne "singleton" à son démarrage.



#



Un nœud AnimationPlayer est ajouté à la scène pour enregistrer et lire des animations. Il peut être situé n'importe où dans la hiérarchie. Afin de lui donner la possibilité d'enregistrer une animation, vous devez cliquer sur le bouton "Animation", au-dessus de la chronologie ouverte et créer une nouvelle animation.

Après cela, sur chaque nœud sélectionné dans la scène actuelle, des icônes clés apparaîtront à droite dans l'inspecteur. Si vous cliquez sur la touche, l'animateur vous proposera d'ajouter une nouvelle piste d'animation.







Ensuite, déplacez le curseur de la chronologie vers les points souhaités, et dans chacun d'eux, nous modifions cette valeur animée dans l'inspecteur d'objets, en appuyant à nouveau sur la touche pour que ce point apparaisse sur la chronologie. Vous pouvez étendre le timelan disponible dans le champ avec l'horloge, à droite, par défaut il y a 1 seconde. À droite de l'horloge se trouve le bouton de boucle d'animation. Ci-dessous, la première de la ligne est l'une des options fréquemment utilisées, qui définit l'animation lisse discrète ou continue.

À droite du panneau central avec le nom de l'animation se trouve le bouton d'exécution automatique, si vous appuyez dessus, l'animation sélectionnée sera lue au démarrage de l'application. Si vous avez besoin de plusieurs objets animés qui sont lus en boucle en permanence, vous pouvez créer leurs pistes dans un AnimationPlayer en créant une animation commune pour eux. Si vous devez changer d'animation pour un objet spécifique, vous pouvez créer un AnimationPlayer distinct pour celui-ci et y créer plusieurs animations pour différents états, tandis qu'un seul d'entre eux peut être marqué comme démarrant automatiquement.



#



Pour différents nœuds, par exemple MeshInstance ou CollisionShape, dans le champ Mesh (Shape), vous pouvez choisir parmi une liste préparée de primitives (y compris le chargement de votre modèle personnalisé, dans le cas de MeshInstance).







Pour MeshInstance, l'une des primitives les plus chères sera la sphère et la capsule, car elles contiendront très probablement beaucoup de polygones. Par conséquent, pour les particules 3D, il est préférable de choisir quelque chose comme un polygone, un cube ou un prisme. Pour les collisions, au contraire, la forme de la sphère sera la plus rapide à lire, puisque des paramètres elle n'a qu'un rayon. En fait, ce qui précède s'applique non seulement à Godot, mais également à d'autres moteurs de jeu.

Godot peut également créer automatiquement une forme de collision pour MeshInstance en cliquant sur le bouton Array qui apparaît en haut à droite dans l'éditeur lorsque MeshInstance est sélectionné. Ensuite, choisissez parmi les options proposées, mais en règle générale, pour le même terrain, ce sera le premier élément - «Créer un corps statique concave» (après quoi le nœud StaticBody sera attaché à l'objet avec la collision exacte imbriquée). Dans tous les autres cas, lorsque des collisions particulièrement précises ne sont pas nécessaires, vous pouvez vous en tirer avec des primitives CollisionShape exposées indépendamment, ou collecter des maillages optimaux pour les collisions dans un package 3D, puis les ajouter via MeshInstance et également créer une collision en fonction de leur forme via le bouton "Tableau".



#



Si, dans l'un des champs numériques de l'inspecteur, il est nécessaire, par exemple, d'ajouter un certain nombre au paramètre, de multiplier la valeur, etc., alors vous pouvez assommer de cette façon: "315-180", "20 + 40", "64 * 5" ... l'éditeur calculera et substituera le résultat final de l'opération sur le terrain.



All Articles