Manipulation en temps réel des maillages sur Unity

image

L'un des avantages d'Unity en tant que plateforme de développement de jeux est son puissant moteur 3D. Dans ce didacticiel, vous découvrirez le monde des objets 3D et la manipulation des maillages.

En raison de la croissance des technologies de réalité virtuelle et augmentée (VR / AR), la plupart des développeurs sont confrontés à des concepts complexes de graphiques 3D. Que ce didacticiel soit le point de départ pour eux. Ne vous inquiétez pas, il n'y aura pas de mathématiques 3D compliquées - seulement des coeurs, des dessins, des flèches et plein de choses intéressantes!

Remarque: ce didacticiel est destiné aux utilisateurs qui connaissent l'EDI Unity et ont une certaine expérience de programmation en C #. Si vous ne disposez pas de telles connaissances, étudiez d'abord les didacticiels Introduction à l'interface utilisateur Unity et Introduction aux scripts Unity .

Vous aurez besoin d'une version d'Unity inférieure à 2017.3.1. La dernière version d'Unity peut être téléchargée ici . Ce didacticiel utilise un éditeur personnalisé et vous pouvez en savoir plus à leur sujet dans le didacticiel Extension de l'éditeur Unity .

Se rendre au travail


Pour commencer, familiarisez-vous avec les termes de base des graphiques 3D, qui vous permettront de mieux comprendre le didacticiel.

Termes techniques de base des graphiques 3D:

  • Sommets : chaque sommet est un point dans l'espace 3D.
  • Maillage : contient tous les sommets, arêtes, triangles, normales et données UV du modèle.
  • Filtre de maillage : stocke les données de maillage du modèle.
  • Rendu de maillage : restitue les données de maillage dans la scène.
  • Normales : vecteur d'un sommet ou d'une surface. Il est dirigé vers l'extérieur, perpendiculairement à la surface du maillage.
  • Lignes / arêtes : lignes invisibles reliant les sommets les uns aux autres.
  • Triangles : formés en reliant trois pics.
  • Carte UV : attache le matériau à un objet, créant une texture et une couleur pour celui-ci.

L'anatomie d'un objet 3D commence par son maillage. La création de ce maillage commence à ses sommets. Les lignes invisibles reliant ces sommets forment des triangles qui définissent la forme de base de l'objet.


Ensuite, les données normales et UV définissent l'ombrage, la couleur et la texture. Les données de maillage sont stockées dans un filtre de maillage et le rendu de maillage utilise ces données pour dessiner un objet dans la scène.

Autrement dit, le pseudocode pour créer un modèle 3D ressemble à ceci:

  • Créez un nouveau maillage appelé «myMesh».
  • Ajoutez des données aux propriétés des sommets et triangles myMesh.
  • Créez un nouveau filtre maillé appelé «myMeshFilter».
  • Définissez la propriété de maillage myMeshFilter sur myMesh.

Une fois que vous maîtrisez les bases, téléchargez le projet , décompressez les fichiers et exécutez la pièce du projet dans Unity. Regardez la structure des dossiers dans la fenêtre Projet :


Description des dossiers:

  • Préfabriqués : contient le préfabriqué Sphère qui sera utilisé pour enregistrer le maillage 3D lors de l'exécution de l'application.
  • Scènes : contient les trois scènes que nous utilisons dans ce didacticiel.
  • Editeur : les scripts à l'intérieur de ce dossier nous donnent les super-fonctionnalités de l'éditeur que nous utilisons en développement.
  • Scripts : voici les scripts d'exécution qui s'attachent au GameObject et s'exécutent lorsque vous cliquez sur Play .
  • Matériaux : ce dossier contient le matériau du maillage.

Dans la section suivante, nous allons créer un éditeur personnalisé pour visualiser la création d'un maillage 3D.

Modifier les maillages avec l'éditeur personnalisé


Ouvrez la démo 01 Mesh Study située dans le dossier Scenes . Dans la fenêtre Scène , vous verrez un cube 3D:


Avant d'entrer dans le maillage, jetons un œil au script de l'éditeur personnalisé.

Modification d'un script d'éditeur


Sélectionnez le dossier Editeur dans la fenêtre Projet . Les scripts de ce dossier ajoutent des fonctionnalités à l'éditeur (Editor) pendant le développement et ne sont pas disponibles en mode Build.


Ouvrez MeshInspector.cs et affichez le code source. Tous les scripts Editor doivent implémenter la classe Editor , son attribut CustomEditor indique à la classe Editor quel type d'objet il est destiné. OnSceneGUI() est une méthode d'événement qui permet le rendu dans la fenêtre Scene; OnInspectorGUI() vous permet d'ajouter des éléments GUI supplémentaires à l'inspecteur.

Dans MeshInspector.cs, avant de démarrer la classe MeshInspector ajoutez ce qui suit:

 [CustomEditor(typeof(MeshStudy))] 

Explication du code: l'attribut CustomEditor indique à Unity quel type d'objet la classe de l'éditeur personnalisé peut modifier.

Dans OnSceneGUI() avant EditMesh() ajoutez ce qui suit:

 mesh = target as MeshStudy; Debug.Log("Custom editor is running"); 

Explication du code: la classe Editor a une variable target standard. Ici, la target est une conversion vers MeshStudy . Maintenant, l'éditeur personnalisé dessinera tous les GameObjects dans la fenêtre Scene et les MeshStudy.cs qui leur sont attachés. L'ajout de messages de débogage vous permet de vérifier dans la console que l'éditeur personnalisé est réellement en cours d'exécution.

Enregistrez le fichier et revenez à Unity. Accédez au dossier Scripts et faites glisser MeshStudy.cs sur le cube GameObject dans la hiérarchie pour le joindre.


Maintenant, le message «L'éditeur personnalisé est en cours d'exécution» devrait s'afficher dans la console, ce qui signifie que nous avons tout fait correctement! Vous pouvez supprimer le message de débogage afin qu'il ne nous dérange pas dans la console.

Clonage et vidage du maillage


Lorsque vous travaillez avec un maillage 3D en mode Édition à l'aide de l'éditeur personnalisé, veillez à ne pas écraser le maillage Unity par défaut. Si cela se produit, vous devrez redémarrer Unity.

Pour cloner le maillage en toute sécurité sans écraser le formulaire d'origine, créez une copie du maillage à partir de la propriété MeshFilter.sharedmesh et affectez-le à nouveau au filtre de maillage.

Pour ce faire, double-cliquez sur MeshStudy.cs dans le dossier Scripts pour ouvrir le fichier dans l'éditeur de code. Ce script hérite de la classe MonoBehaviour et sa fonction Start() n'est pas exécutée en mode Edit.

Dans MeshStudy.cs, avant de démarrer la classe MeshStudy ajoutez ce qui suit:

 [ExecuteInEditMode] 

Explication du code: après l'ajout de cet attribut, la fonction Start() sera exécutée à la fois en mode Play et en mode Edit. Maintenant, nous pouvons d'abord instancier l'objet maillé et le cloner.

Dans InitMesh() ajoutez le code suivant:

 oMeshFilter = GetComponent<MeshFilter>(); oMesh = oMeshFilter.sharedMesh; //1 cMesh = new Mesh(); //2 cMesh.name = "clone"; cMesh.vertices = oMesh.vertices; cMesh.triangles = oMesh.triangles; cMesh.normals = oMesh.normals; cMesh.uv = oMesh.uv; oMeshFilter.mesh = cMesh; //3 vertices = cMesh.vertices; //4 triangles = cMesh.triangles; isCloned = true; Debug.Log("Init & Cloned"); 

Explication du code:

  1. Obtient le maillage oMesh origine du composant MeshFilter .
  2. Copie cMesh dans une nouvelle cMesh maillage.
  3. Attribue à nouveau le filtre de maillage de maillage copié.
  4. Met à jour les variables locales.

Enregistrez le fichier et revenez à Unity. Le message «Init & Cloned» doit être affiché dans la console de débogage. Sélectionnez le Cube GameObject dans la hiérarchie et vérifiez ses propriétés dans l' inspecteur . Le filtre de maillage doit afficher un élément de maillage appelé clone . Super! Cela signifie que nous avons réussi à cloner le maillage.


Dans le dossier Editor, accédez à MeshInspector.cs . Dans OnInspectorGUI() , après la deuxième ligne de code, ajoutez ce qui suit:

 if (GUILayout.Button("Reset")) //1 { mesh.Reset(); //2 } 

Explication du code:

  1. Ce code dessine un bouton Réinitialiser dans l' inspecteur .
  2. Lorsqu'il est pressé, il appelle la fonction Reset() dans MeshStudy.cs .

Enregistrez le fichier, ouvrez MeshStudy.cs et ajoutez le code suivant à la fonction Reset() :

 if (cMesh != null && oMesh != null) //1 { cMesh.vertices = oMesh.vertices; //2 cMesh.triangles = oMesh.triangles; cMesh.normals = oMesh.normals; cMesh.uv = oMesh.uv; oMeshFilter.mesh = cMesh; //3 vertices = cMesh.vertices; //4 triangles = cMesh.triangles; } 

Explication du code:

  1. Vérification de l'existence de la source et du maillage cloné.
  2. Réinitialisez cMesh au maillage d'origine.
  3. Affectation à cMesh oMeshFilter .
  4. Mise à jour des variables locales.

Enregistrez le fichier et revenez à Unity. Dans l' inspecteur, cliquez sur le bouton Test Edit pour déformer le maillage du cube. Ensuite, cliquez sur le bouton Réinitialiser ; le cube doit reprendre sa forme d'origine.


Explication des sommets et triangles dans Unity


Un maillage est composé de sommets reliés par des arêtes en triangles. Les triangles définissent la forme de base de l'objet.

Classe de maille:

  • Les sommets sont stockés sous forme de tableau de valeurs Vector3 .
  • Les triangles sont stockés sous la forme d'un tableau d'entiers correspondant aux indices du tableau de sommets.

Autrement dit, dans un simple maillage Quad, composé de quatre sommets et de deux triangles, les données du maillage ressembleront à ceci:


Cartographie des sommets


Ici, nous voulons afficher les sommets du cube sous forme de points bleus.

Dans MeshInspector.cs, nous allons entrer dans la fonction EditMesh() et ajouter ce qui suit:

 handleTransform = mesh.transform; //1 handleRotation = Tools.pivotRotation == PivotRotation.Local ? handleTransform.rotation : Quaternion.identity; //2 for (int i = 0; i < mesh.vertices.Length; i++) //3 { ShowPoint(i); } 

Explication du code:

  1. handleTransform obtient les valeurs de transformation à partir du mesh .
  2. handleRotation obtient le mode Rotation de l'articulation actuelle.
  3. Parcourez les sommets du maillage et tracez les points à l'aide de ShowPoint() .

Dans la fonction ShowPoint() , immédiatement après le commentaire //draw dot , ajoutez ce qui suit:

 Vector3 point = handleTransform.TransformPoint(mesh.vertices[index]); 

Explication du code: cette ligne convertit la position locale du sommet en coordonnées dans l'espace mondial.

Dans la même fonction, dans le bloc if , immédiatement après la ligne de code que vous venez d'ajouter, ajoutez ce qui suit:

 Handles.color = Color.blue; point = Handles.FreeMoveHandle(point, handleRotation, mesh.handleSize, Vector3.zero, Handles.DotHandleCap); 

Explication du code:

  1. Définit la couleur, la taille et la position d'un point à l'aide de la classe d'assistance Handles .
  2. Handles.FreeMoveHandle() crée un manipulateur de mouvement illimité qui simplifie l'opération de glisser-déposer, ce qui nous est utile dans la section suivante.

Enregistrez le fichier et revenez à Unity. Vérifiez la propriété du cube dans l' inspecteur et assurez-vous que l'option Déplacer le point de sommet est activée. Vous devriez maintenant voir que le maillage à l'écran est marqué de plusieurs points bleus. Les voici - les sommets du maillage cube! Essayez de le faire avec d'autres objets 3D et observez les résultats.


Déplacer un seul sommet


Commençons par l'étape la plus simple de manipulation du maillage - déplacer un seul sommet.

Accédez à MeshInspector.cs . Dans la fonction ShowPoint() , immédiatement après le commentaire //drag et juste avant les crochets de fermeture du bloc if , ajoutez ce qui suit:

 if (GUI.changed) //1 { mesh.DoAction(index, handleTransform.InverseTransformPoint(point)); //2 } 

Explication du code:

  1. GUI.changed garde une trace de toutes les modifications qui se produisent avec les points et fonctionne bien avec Handles.FreeMoveHandle() pour reconnaître une opération de glisser-déposer.
  2. Pour le sommet déplaçable, la fonction mesh.DoAction() reçoit ses valeurs d'index et de transformation comme paramètres. Étant donné que les valeurs de sommet de transformation sont dans l'espace mondial, nous les convertissons en espace local à l'aide d' InverseTransformPoint() .

Enregistrez le fichier de script et accédez à MeshStudy.cs . Dans DoAction() , après les crochets d'ouverture, ajoutez ce qui suit:

 PullOneVertex(index, localPos); 

Ajoutez ensuite ce qui suit à la fonction PullOneVertex() :

 vertices[index] = newPos; //1 cMesh.vertices = vertices; //2 cMesh.RecalculateNormals(); //3 

Explication du code:

  1. Nous mettons à jour le sommet cible avec la valeur newPos .
  2. cMesh.vertices valeurs de sommet mises à jour à cMesh.vertices .
  3. Dans RecalculateNormals() recalculons et redessinons le maillage afin qu'il corresponde aux modifications.

Enregistrez le fichier et revenez à Unity. Essayez de faire glisser des points sur le cube; avez-vous vu un maillage cassé?


Il semble que certains des sommets aient la même position, donc lorsque nous ne faisons glisser qu'un seul, les sommets restants restent derrière, et le maillage se brise. Dans la section suivante, nous allons résoudre ce problème.

Trouver tous les sommets similaires


Visuellement, un maillage cubique se compose de huit sommets, six côtés et 12 triangles. Vérifions si c'est le cas.


Ouvrez MeshStudy.cs , jetez un œil devant la fonction Start() et trouvez la variable des vertices . Nous verrons ce qui suit:

 [HideInInspector] public Vector3[] vertices; 

Explication du code: [HideInInspector] masque une variable partagée dans la fenêtre Inspecteur .

Commentez cet attribut:

 //[HideInInspector] public Vector3[] vertices; 

Remarque: masquer les valeurs des sommets aide [HideInInspector] avec des maillages 3D plus complexes. Étant donné que la taille du tableau de sommets peut atteindre des milliers d'éléments, cela peut entraîner une inhibition de Unity lorsque vous essayez d'afficher la valeur du tableau dans l'inspecteur.

Enregistrez le fichier et revenez à Unity. Allez à l' inspecteur . Maintenant, sous le composant de script Mesh Study , la propriété verteices est apparue. Cliquez sur l'icône de flèche à côté; vous Vector3 tableau des éléments Vector3 .


Vous pouvez voir que la taille du tableau est de 24, c'est-à-dire qu'il y a des sommets ayant la même position! Avant de continuer, assurez-vous de décommenter [HideInInspector] .

Pourquoi y a-t-il 24 sommets?
Il existe de nombreuses théories à ce sujet. Mais la réponse la plus simple est: le cube a six côtés, et chaque côté est composé de quatre sommets qui forment un plan.

Par conséquent, le calcul est le suivant: 6 x 4 = 24 sommets.

Vous pouvez rechercher d'autres réponses. Mais pour l'instant, c'est assez simple de savoir que certains maillages auront des sommets qui auront la même position.

Dans MeshStudy.cs, remplacez tout le code à l'intérieur de la fonction DoAction() par ce qui suit:

 PullSimilarVertices(index, localPos); 

Passons à la fonction PullSimilarVertices() et ajoutons ce qui suit:

 Vector3 targetVertexPos = vertices[index]; //1 List<int> relatedVertices = FindRelatedVertices(targetVertexPos, false); //2 foreach (int i in relatedVertices) //3 { vertices[i] = newPos; } cMesh.vertices = vertices; //4 cMesh.RecalculateNormals(); 

Explication du code:

  1. nous obtenons la position du sommet cible, qui sera utilisée comme argument de la méthode FindRelatedVertices() .
  2. Cette méthode renvoie une liste d'index (correspondant aux sommets) qui ont la même position que le sommet cible.
  3. La boucle traverse la liste entière et définit les sommets correspondants sur newPos .
  4. cMesh.vertices vertices mis à jour à cMesh.vertices . Ensuite, nous appelons RecalculateNormals() pour redessiner le maillage avec les nouvelles valeurs.

Enregistrez le fichier et revenez à Unity. Faites glisser l'un des sommets; maintenant le maillage doit conserver sa forme et ne pas s'effondrer.


Maintenant que nous avons terminé la première étape de la manipulation des maillages, enregistrez la scène et passez à la section suivante.

Manipulation de maillage


Dans cette section, vous apprendrez à manipuler les maillages en temps réel. Il existe de nombreuses façons, mais dans ce didacticiel, nous examinerons le type de manipulation de maillage le plus simple, à savoir le déplacement des sommets de maillage créés précédemment.

Collecte des index sélectionnés


Commençons par sélectionner les sommets que nous déplacerons en temps réel.

Ouvrez la scène 02 Create Heart Mesh à partir du dossier Scenes . Dans la fenêtre Scène, vous verrez une sphère rouge. Sélectionnez Sphère dans la hiérarchie et accédez à Inspecteur . Vous verrez que le composant de script Heart Mesh est attaché à l'objet.

Nous avons maintenant besoin du script Editor pour cet objet pour afficher les sommets du maillage dans la fenêtre Scene. Accédez au dossier Editor et double-cliquez sur HeartMeshInspector.cs .

Dans la fonction ShowHandle() , à l'intérieur du bloc if , ajoutez ce qui suit:

 Handles.color = Color.blue; if (Handles.Button(point, handleRotation, mesh.pickSize, mesh.pickSize, Handles.DotHandleCap)) //1 { mesh.selectedIndices.Add(index); //2 } 

Explication du code:

  1. Définit et affiche les sommets du maillage en tant que type Handles.Button .
  2. Lorsque vous cliquez dessus, il ajoute l'index sélectionné à la mesh.selectedIndices pressée, mesh.selectedIndices .

Dans OnInspectorGUI() , avant le crochet de fermeture, ajoutez ce qui suit:

 if (GUILayout.Button("Clear Selected Vertices")) { mesh.ClearAllData(); } 

Explication du code: mesh.ClearAllData() comment ajouter un bouton Reset à l' inspecteur pour appeler mesh.ClearAllData() .

Enregistrez le fichier et ouvrez HeartMesh.cs à partir du dossier Scripts . Dans la fonction ClearAllData() , ajoutez les éléments suivants:

 selectedIndices = new List<int>(); targetIndex = 0; targetVertex = Vector3.zero; 

Explication du code: le code efface les valeurs dans selectedIndices et targetIndex . Il réinitialise également targetVertex .

Enregistrez le fichier et revenez à Unity. Sélectionnez Sphère et accédez à l' inspecteur du composant de script HeartMesh . Développez les indices sélectionnés en cliquant sur l'icône en forme de flèche à côté. Cela nous permettra de suivre chaque sommet ajouté à la liste.

Activez le mode d'édition à l'aide de la case à cocher à côté. Pour cette raison, les sommets du maillage seront dessinés dans la fenêtre Scène. Un clic sur les points bleus dans les indices sélectionnés devrait modifier les valeurs en conséquence. Testez également le bouton Effacer les sommets sélectionnés pour vous assurer qu'il efface toutes les valeurs.


Remarque: dans l' inspecteur personnalisé modifié, nous avons la possibilité d'afficher / masquer le manipulateur de transformation à l'aide de Afficher la poignée de transformation . Alors ne paniquez pas si vous ne trouvez pas le manipulateur Transform dans d'autres scènes! Allumez-le avant de quitter.

Transformer une sphère en cœur


La modification des sommets du maillage en temps réel consiste essentiellement en trois étapes:

  1. Copiez les sommets de maillage actuels (avant l'animation) dans mVertices .
  2. mVertices calculs et modifions les valeurs dans mVertices .
  3. Mettez à jour les sommets de maillage actuels avec mVertices lors de la modification à chaque étape et laissez Unity calculer automatiquement les normales.

Ouvrez HeartMesh.cs et les variables suivantes avant la fonction Start() :

 public float radiusofeffect = 0.3f; //1 public float pullvalue = 0.3f; //2 public float duration = 1.2f; //3 int currentIndex = 0; //4 bool isAnimate = false; float starttime = 0f; float runtime = 0f; 

Explication du code:

  1. Rayon de la zone affectée par le sommet cible.
  2. Faites glisser la force.
  3. La durée de l'animation.
  4. Index actuel de la liste selectedIndices .

Dans la fonction Init() , avant le bloc if , ajoutez ce qui suit:

 currentIndex = 0; 

Explication du code: au début du jeu, currentIndex à 0, le premier index de la liste selectedIndices .

Dans la même fonction Init() , avant le crochet de fermeture du bloc else , ajoutez ce qui suit:

 StartDisplacement(); 

Explication du code: exécutez la fonction StartDisplacement() si isEditMode est false.

Dans la fonction StartDisplacement() , ajoutez ce qui suit:

 targetVertex = oVertices[selectedIndices[currentIndex]]; //1 starttime = Time.time; //2 isAnimate = true; 

Explication du code:

  1. Sélectionnez targetVertex pour démarrer l'animation.
  2. Définissez l'heure de début et modifiez la valeur de isAnimate sur true.

Après la fonction StartDisplacement() , créez la fonction FixedUpdate() avec le code suivant:

 void FixedUpdate() //1 { if (!isAnimate) //2 { return; } runtime = Time.time - starttime; //3 if (runtime < duration) //4 { Vector3 targetVertexPos = oFilter.transform.InverseTransformPoint(targetVertex); DisplaceVertices(targetVertexPos, pullvalue, radiusofeffect); } else //5 { currentIndex++; if (currentIndex < selectedIndices.Count) //6 { StartDisplacement(); } else //7 { oMesh = GetComponent<MeshFilter>().mesh; isAnimate = false; isMeshReady = true; } } } 

Explication du code:

  1. La fonction FixedUpdate() est exécutée dans une boucle FPS fixe.
  2. Si isAnimate est faux, ignorez le code suivant.
  3. Modifiez runtime animations d' runtime .
  4. Si l' runtime est dans la duration , nous obtenons alors les coordonnées mondiales de targetVertex et DisplaceVertices() , couvrant le sommet cible avec les radiusofeffect pullvalue et radiusofeffect .
  5. Sinon, le temps est écoulé. Ajoutez-en un à currentIndex .
  6. Vérifiez si currentIndex partie des selectedIndices . Accédez au sommet suivant de la liste à l'aide de StartDisplacement() .
  7. Sinon, à la fin de la liste, remplacez les données oMesh par le maillage actuel et isAnimate sur false pour arrêter l'animation.

Dans DisplaceVertices() ajoutez les éléments suivants:

 Vector3 currentVertexPos = Vector3.zero; float sqrRadius = radius * radius; //1 for (int i = 0; i < mVertices.Length; i++) //2 { currentVertexPos = mVertices[i]; float sqrMagnitute = (currentVertexPos - targetVertexPos).sqrMagnitude; //3 if (sqrMagnitute > sqrRadius) { continue; //4 } float distance = Mathf.Sqrt(sqrMagnitute); //5 float falloff = GaussFalloff(distance, radius); Vector3 translate = (currentVertexPos * force) * falloff; //6 translate.z = 0f; Quaternion rotation = Quaternion.Euler(translate); Matrix4x4 m = Matrix4x4.TRS(translate, rotation, Vector3.one); mVertices[i] = m.MultiplyPoint3x4(currentVertexPos); } oMesh.vertices = mVertices; //7 oMesh.RecalculateNormals(); 

Explication du code:

  1. Le carré du rayon.
  2. Nous parcourons chaque sommet du maillage.
  3. sqrMagnitude entre currentVertexPos et targetVertexPos .
  4. Si sqrMagnitude dépasse sqrRadius , passez au sommet suivant.
  5. Sinon, continuez en définissant la valeur d' falloff , qui dépend de la distance sommet actuel par rapport au point central de l'oscilloscope.
  6. Vector3 nouvelle position de Vector3 et appliquez sa transformation au sommet actuel.
  7. Lorsque vous quittez la boucle, nous mVertices valeurs mVertices modifiées aux mVertices et mVertices Unity à recalculer les normales.

Source de technologie Falloff
La formule d'origine est extraite du fichier de package d'actifs Exemples de procédures , qui peut être téléchargé gratuitement à partir de l'Unity Asset Store.

Enregistrez le fichier et revenez à Unity. Sélectionnez Sphère , accédez au composant HeartMesh et essayez d'ajouter des sommets à la propriété Indices sélectionnés . Désactivez le mode Édition et cliquez sur Lecture pour voir le résultat de votre travail.


Essayez les valeurs Radiusofeffect , Pullvalue et Duration pour obtenir des résultats différents. Lorsque vous êtes prêt, modifiez les paramètres conformément à la capture d'écran ci-dessous.


Cliquez sur Play . Votre sphère s'est-elle transformée en cœur?


Félicitations! Dans la section suivante, nous enregistrerons le maillage en tant que préfabriqué pour une utilisation future.

Sauvegarde du maillage en temps réel


Pour enregistrer un maillage procédural en forme de cœur en mode Lecture, vous devez préparer un préfabriqué dont l'enfant sera un objet 3D, puis remplacer son actif de maillage par un nouveau à l'aide d'un script.

Dans la fenêtre Projet, recherchez CustomHeart dans le dossier Prefabs . Cliquez sur l'icône de flèche pour développer son contenu et sélectionnez Enfant . Vous voyez maintenant un objet Sphère dans la fenêtre d'aperçu de l' inspecteur . Il s'agit du préfabriqué qui stockera les données du nouveau maillage.


Ouvrez HeartMeshInspector.cs . Dans la fonction OnInspectorGUI() , avant le crochet de fermeture, ajoutez ce qui suit:

 if (!mesh.isEditMode && mesh.isMeshReady) { string path = "Assets/Prefabs/CustomHeart.prefab"; //1 if (GUILayout.Button("Save Mesh")) { mesh.isMeshReady = false; Object pfObj = AssetDatabase.LoadAssetAtPath(path, typeof(GameObject)); //2 Object pfRef = AssetDatabase.LoadAssetAtPath (path, typeof(GameObject)); GameObject gameObj = (GameObject)PrefabUtility.InstantiatePrefab(pfObj); Mesh pfMesh = (Mesh)AssetDatabase.LoadAssetAtPath(path, typeof(Mesh)); //3 if (!pfMesh) { pfMesh = new Mesh(); } else { pfMesh.Clear(); } pfMesh = mesh.SaveMesh(); //4 AssetDatabase.AddObjectToAsset(pfMesh, path); gameObj.GetComponentInChildren<MeshFilter>().mesh = pfMesh; //5 PrefabUtility.ReplacePrefab(gameObj, pfRef, ReplacePrefabOptions.Default); //6 Object.DestroyImmediate(gameObj); //7 } } 

Explication du code:

  1. Définit le path d' path au path d'accès à l'objet préfabriqué CustomHeart.
  2. Crée deux objets à partir du préfabriqué CustomHeart, un pour créer une instance en tant que GameObject ( pfObj ) et le second en tant que liens ( pfRef ).
  3. Crée une instance de l'actif de maillage pfMesh . S'il n'est pas trouvé, crée un nouveau maillage, sinon il nettoie les données existantes.
  4. pfMesh avec de nouvelles données de maillage, puis l'ajoute en tant qu'actif à CustomHeart .
  5. Remplit un actif maillé dans gameObj valeur pfMesh .
  6. Remplace CustomHeart par gameObj faisant correspondre les connexions préexistantes.
  7. gameObj instantanément gameObj .

Enregistrez le fichier et accédez à HeartMesh.cs . Dans la SaveMesh() générale SaveMesh() , après avoir créé l'instance nMesh ajoutez ce qui suit:

 nMesh.name = "HeartMesh"; nMesh.vertices = oMesh.vertices; nMesh.triangles = oMesh.triangles; nMesh.normals = oMesh.normals; 

Explication du code: renvoie un actif de maillage avec des valeurs provenant d'un maillage en forme de cœur.

Enregistrez le fichier et revenez à Unity. Cliquez sur Lecture . Une fois l'animation terminée, le bouton Enregistrer le maillage apparaît dans l' inspecteur . Cliquez sur le bouton pour enregistrer le nouveau maillage, puis arrêtez le lecteur.

Accédez au dossier Prefabs et examinez le préfabriqué CustomHeart. Vous devriez voir que maintenant dans l'objet préfabriqué CustomHeart il y a un tout nouveau maillage en forme de coeur.


Excellent travail!

Tout mettre ensemble


Dans la scène précédente, la fonction DisplaceVertices() utilisé la formule Falloff pour déterminer la force de traînée qui a été appliquée à chaque sommet dans un rayon donné. Le point de «chute», auquel la force de traînée commence à diminuer, dépend du type de chute utilisé: linéaire, gaussien ou aiguille. Chaque type produit des résultats différents dans le maillage.


Dans cette section, nous verrons une autre façon de manipuler les sommets: en utilisant une courbe donnée. En supposant que la vitesse est égale à la distance divisée par le temps (d = (v / t)), nous pouvons déterminer la position du vecteur, en se référant à sa distance divisée par le temps.


Utilisation de la méthode de courbe


Enregistrez la scène actuelle et ouvrez 03 Customize Heart Mesh dans le dossier Scenes . Vous verrez une instance de hiérarchie du préfabriqué CustomHeart. Cliquez sur l'icône en forme de flèche à côté pour développer son contenu et sélectionnez Enfant .

Affichez ses propriétés dans l' inspecteur . Vous verrez le composant Filtre de maillage avec l'actif de maillage Heart .Attachez un script Heart personnalisé à Child en tant que composant . Maintenant, l'actif devrait passer de HeartMesh à cloner .


Ensuite, ouvrez CustomHeart.cs à partir du dossier Scripts . Avant la fonction, Start()ajoutez ce qui suit:

 public enum CurveType { Curve1, Curve2 } public CurveType curveType; Curve curve; 

Explication du code: ici une énumération générale est créée sous le nom CurveType, après quoi elle est mise à disposition par l' Inspecteur .

Accédez à CurveType1()et ajoutez les éléments suivants:

 Vector3[] curvepoints = new Vector3[3]; //1 curvepoints[0] = new Vector3(0, 1, 0); curvepoints[1] = new Vector3(0.5f, 0.5f, 0); curvepoints[2] = new Vector3(1, 0, 0); curve = new Curve(curvepoints[0], curvepoints[1], curvepoints[2], false); //2 

Explication du code:

  1. Une courbe simple se compose de trois points. Définissez les points de la première courbe.
  2. Nous générons la première courbe avec l'aide Curve()et attribuons ses valeurs curve. La courbe dessinée peut être affichée dans l'aperçu si vous spécifiez true comme dernier paramètre.

Accédez à CurveType2()et ajoutez les éléments suivants:

 Vector3[] curvepoints = new Vector3[3]; //1 curvepoints[0] = new Vector3(0, 0, 0); curvepoints[1] = new Vector3(0.5f, 1, 0); curvepoints[2] = new Vector3(1, 0, 0); curve = new Curve(curvepoints[0], curvepoints[1], curvepoints[2], false); //2 

Explication du code:

  1. Définissez les points de la deuxième courbe.
  2. Nous générons la deuxième courbe avec Curve()et attribuons ses valeurs curve. La courbe dessinée peut être affichée dans l'aperçu si vous spécifiez true comme dernier paramètre.

B StartDisplacement(), avant le crochet de fermeture, ajoutez ce qui suit:

 if (curveType == CurveType.Curve1) { CurveType1(); } else if (curveType == CurveType.Curve2) { CurveType2(); } 

Explication du code: ici nous vérifions l'option sélectionnée par l'utilisateur curveTypeet la générons en conséquence curve.

B DisplaceVertices(), à l'intérieur de l'instruction de boucle foravant les crochets de fermeture, ajoutez ce qui suit:

 float increment = curve.GetPoint(distance).y * force; //1 Vector3 translate = (vert * increment) * Time.deltaTime; //2 Quaternion rotation = Quaternion.Euler(translate); Matrix4x4 m = Matrix4x4.TRS(translate, rotation, Vector3.one); mVertices[i] = m.MultiplyPoint3x4(mVertices[i]); 

Explication du code:

  1. Nous obtenons la position de la courbe à celle donnée distanceet multiplions sa valeur ypar forcepour obtenir increment.
  2. Créez un nouveau type de données Vector3pour stocker la nouvelle position du sommet actuel et appliquez sa transformation en conséquence.

Enregistrez le fichier et revenez à Unity. Vérifiez les propriétés du composant CustomHeart objet jeu d' enfants . Vous verrez une liste déroulante où vous pouvez sélectionner le type de courbe . Dans la liste déroulante Modifier le type , sélectionnez Ajouter des indices ou Supprimer des indices pour mettre à jour la liste des sommets et expérimenter différents paramètres.


Pour voir des résultats détaillés pour différents types de courbes, entrez les valeurs selon la capture d'écran:


Pour la liste Curve Type , sélectionnez Curve1 , assurez-vous que None est sélectionné pour Edit Type, puis cliquez sur Play . Vous devriez voir le maillage diverger dans le motif. Faites rouler le modèle pour le voir en vue latérale et comparez les résultats pour les deux types de courbes. Vous voyez ici comment le type de courbe sélectionné affecte le décalage du maillage.



C'est tout!Vous pouvez cliquer sur Effacer les sommets sélectionnés pour réinitialiser les indices sélectionnés et expérimenter avec vos propres motifs. Mais n'oubliez pas qu'il existe d'autres facteurs qui affecteront le résultat final du maillage, à savoir:

  • La valeur du rayon.
  • La distribution des sommets dans la zone.
  • Position du motif des sommets sélectionnés.
  • La méthode sélectionnée pour le décalage.

Où aller ensuite?


Les fichiers du projet terminé sont dans les archives du projet de tutoriel.

Ne vous arrêtez pas là! Essayez les techniques plus sophistiquées utilisées dans le didacticiel Unity Procedural Maze Generation .

J'espère que vous avez apprécié ce didacticiel et que les informations vous ont été utiles. Un grand merci que j'exprime Jasper Flick de Catlike de codage pour ses excellents tutoriels qui m'a aidé à assembler une démo pour mon projet.

Source: https://habr.com/ru/post/fr428796/


All Articles