Einer der Vorteile von Unity als Plattform für die Spieleentwicklung ist die leistungsstarke 3D-Engine. In diesem Tutorial lernen Sie die Welt der 3D-Objekte und der Netzmanipulation kennen.
Aufgrund des Wachstums der VR- und AR-Technologien (Virtual and Augmented Reality) sind die meisten Entwickler mit komplexen Konzepten von 3D-Grafiken konfrontiert. Lassen Sie dieses Tutorial der Ausgangspunkt für sie sein. Keine Sorge, es wird keine komplizierte 3D-Mathematik geben - nur Herzen, Zeichnungen, Pfeile und viele interessante Dinge!
Hinweis: Dieses Lernprogramm richtet sich an Benutzer, die mit der Unity-IDE vertraut sind und über Programmiererfahrung in C # verfügen. Wenn Sie nicht über solche Kenntnisse verfügen, lesen Sie zuerst die Tutorials Einführung in die Unity-Benutzeroberfläche und Einführung in Unity Scripting .
Sie benötigen eine Version von Unity, die nicht niedriger als 2017.3.1 ist. Die neueste Version von Unity kann hier heruntergeladen werden . In diesem Lernprogramm wird ein benutzerdefinierter Editor verwendet. Weitere Informationen hierzu finden Sie im Lernprogramm zum Erweitern des Unity-Editors .
An die Arbeit gehen
Machen Sie sich zunächst mit den Grundbegriffen der 3D-Grafik vertraut, damit Sie das Tutorial besser verstehen.
Grundlegende Fachbegriffe für 3D-Grafiken:
- Scheitelpunkte : Jeder Scheitelpunkt ist ein Punkt im 3D-Raum.
- Netz : Enthält alle Eckpunkte, Kanten, Dreiecke, Normalen und UV-Daten des Modells.
- Netzfilter : Speichert Modellnetzdaten.
- Mesh Renderer : Rendert die Mesh-Daten in der Szene.
- Normalen : Der Vektor eines Scheitelpunkts oder einer Oberfläche. Es ist senkrecht zur Oberfläche des Netzes nach außen gerichtet.
- Linien / Kanten : Unsichtbare Linien, die Eckpunkte miteinander verbinden.
- Dreiecke : gebildet durch Verbinden von drei Spitzen.
- UV-Karte : Hängt Material an ein Objekt an und erstellt eine Textur und Farbe dafür.
Die Anatomie eines 3D-Objekts beginnt mit seinem Netz. Die Erstellung dieses Netzes beginnt an seinen Spitzen. Unsichtbare Linien, die diese Eckpunkte verbinden, bilden Dreiecke, die die Grundform des Objekts definieren.
Dann legen die Normalen und UV-Daten die Schattierung, Farbe und Textur fest. Netzdaten werden in einem Netzfilter gespeichert, und der Netzrenderer verwendet diese Daten, um ein Objekt in der Szene zu zeichnen.
Das heißt, der Pseudocode zum Erstellen eines 3D-Modells sieht folgendermaßen aus:
- Erstellen Sie ein neues Netz mit dem Namen "myMesh".
- Fügen Sie Daten zu den Eigenschaften der Eckpunkte und Dreiecke myMesh hinzu.
- Erstellen Sie einen neuen Netzfilter mit dem Namen "myMeshFilter".
- Setzen Sie die Mesh-Eigenschaft myMeshFilter auf myMesh.
Wenn Sie die Grundlagen beherrschen, laden Sie das
Projekt herunter, entpacken Sie die Dateien und führen Sie das Werkstück des Projekts in Unity aus. Sehen Sie sich die Ordnerstruktur im
Projektfenster an :
Beschreibung der Ordner:
- Prefabs : Enthält das Sphere-Prefab, mit dem das 3D-Netz während der Anwendungsausführung gespeichert wird.
- Szenen : Enthält die drei Szenen, die wir in diesem Tutorial verwenden.
- Editor : Die Skripte in diesem Ordner geben uns die Superfunktionen im Editor, die wir in der Entwicklung verwenden.
- Skripte : Hier sind die Laufzeitskripte, die an das GameObject angehängt und ausgeführt werden, wenn Sie auf " Spielen" klicken.
- Materialien : Dieser Ordner enthält das Material für das Netz.
Im nächsten Abschnitt erstellen wir einen benutzerdefinierten Editor, um die Erstellung eines 3D-Netzes zu visualisieren.
Ändern Sie die Netze mit dem benutzerdefinierten Editor
Öffnen Sie die
01 Mesh Study Demo im Ordner "
Scenes ". Im
Szenenfenster sehen Sie einen 3D-Würfel:
Bevor wir uns mit dem Netz befassen, werfen wir einen Blick auf das benutzerdefinierte Editor-Skript.
Bearbeiten eines Editor-Skripts
Wählen Sie den
Editor- Ordner im
Projektfenster . Die Skripte in diesem Ordner erweitern den Editor (Editor) während der Entwicklung um Funktionen und sind im Erstellungsmodus nicht verfügbar.
Öffnen Sie
MeshInspector.cs und zeigen Sie den Quellcode an. Alle Editor-Skripte müssen die
Editor
Klasse implementieren. Das
CustomEditor
Attribut teilt der
Editor
Klasse mit, für welchen Objekttyp sie bestimmt ist.
OnSceneGUI()
ist eine Ereignismethode, die das Rendern im
OnSceneGUI()
ermöglicht.
OnInspectorGUI()
können Sie dem Inspector zusätzliche GUI-Elemente hinzufügen.
Fügen Sie in
MeshInspector.cs vor dem Starten der
MeshInspector
Klasse Folgendes hinzu:
[CustomEditor(typeof(MeshStudy))]
Code Erläuterung: Das
CustomEditor
Attribut teilt Unity mit, welchen Objekttyp die benutzerdefinierte
CustomEditor
ändern kann.
OnSceneGUI()
in
OnSceneGUI()
vor
EditMesh()
Folgendes hinzu:
mesh = target as MeshStudy; Debug.Log("Custom editor is running");
Codeerklärung: Die
Editor
Klasse verfügt über eine Standardzielvariable.
target
ist hier eine Konvertierung in
MeshStudy
. Jetzt zeichnet der benutzerdefinierte Editor alle GameObjects im Szenenfenster und die
daran angehängten
MeshStudy.cs . Durch Hinzufügen von Debugging-Meldungen können Sie in der Konsole überprüfen, ob der benutzerdefinierte Editor tatsächlich ausgeführt wird.
Speichern Sie die Datei und kehren Sie zu Unity zurück. Gehen Sie zum Ordner "
Scripts " und ziehen Sie
MeshStudy.cs auf den GameObject-
Cube in der
Hierarchie , um ihn anzuhängen.
Jetzt sollte die Meldung "Benutzerdefinierter Editor läuft" in der Konsole angezeigt werden. Dies bedeutet, dass wir alles richtig gemacht haben! Sie können die Debug-Nachricht löschen, damit sie uns in der Konsole nicht stört.
Klonen und Dumping des Netzes
Achten Sie beim Arbeiten mit einem 3D-Netz im Bearbeitungsmodus mit dem benutzerdefinierten Editor darauf, das Standard-Unity-Netz nicht zu überschreiben. In diesem Fall müssen Sie Unity neu starten.
Um das Netz sicher zu klonen, ohne das ursprüngliche Formular zu überschreiben, erstellen Sie eine Kopie des Netzes aus der Eigenschaft
MeshFilter.sharedmesh
und weisen Sie es dem Netzfilter erneut zu.
Doppelklicken Sie
dazu im Ordner
Scripts auf
MeshStudy.cs , um die Datei im Code-Editor zu öffnen. Dieses Skript erbt von der
MonoBehaviour
Klasse und seine
Start()
-Funktion wird im Bearbeitungsmodus nicht ausgeführt.
Fügen Sie in
MeshStudy.cs vor dem Starten der
MeshStudy
Klasse Folgendes hinzu:
[ExecuteInEditMode]
Erläuterung des Codes: Nach dem Hinzufügen dieses Attributs wird die Funktion
Start()
sowohl im Wiedergabemodus als auch im Bearbeitungsmodus ausgeführt. Jetzt können wir zuerst das Netzobjekt instanziieren und es klonen.
InitMesh()
in
InitMesh()
den folgenden Code hinzu:
oMeshFilter = GetComponent<MeshFilter>(); oMesh = oMeshFilter.sharedMesh;
Code Erläuterung:
- Ruft das ursprüngliche
oMesh
Netz aus der MeshFilter
Komponente ab. - Kopiert
cMesh
in eine neue Mesh- cMesh
. - Weist den kopierten Maschennetzfilter erneut zu.
- Aktualisiert lokale Variablen.
Speichern Sie die Datei und kehren Sie zu Unity zurück. Die Meldung "Init & Cloned" sollte in der Debug-Konsole angezeigt werden. Wählen Sie den GameObject-
Cube
in der
Hierarchie aus und überprüfen Sie seine Eigenschaften im
Inspektor .
Der Netzfilter sollte ein Netzelement namens
Klon anzeigen. Großartig! Dies bedeutet, dass wir das Netz erfolgreich geklont haben.
Navigieren
Sie im Editor-Ordner zu
MeshInspector.cs .
OnInspectorGUI()
in
OnInspectorGUI()
nach der zweiten Codezeile Folgendes hinzu:
if (GUILayout.Button("Reset"))
Code Erläuterung:
- Dieser Code zeichnet eine Schaltfläche zum Zurücksetzen im Inspektor .
- Wenn diese Taste gedrückt wird, wird die Funktion
Reset()
in MeshStudy.cs aufgerufen .
Speichern Sie die Datei, öffnen Sie
MeshStudy.cs und fügen Sie der Funktion
Reset()
den folgenden Code hinzu:
if (cMesh != null && oMesh != null)
Code Erläuterung:
- Überprüfen der Existenz der Quelle und des geklonten Netzes.
cMesh
auf das ursprüngliche Netz zurück.- Zuordnung zu
cMesh
oMeshFilter
. - Lokale Variablen aktualisieren.
Speichern Sie die Datei und kehren Sie zu Unity zurück. Klicken Sie im
Inspektor auf die Schaltfläche
Test bearbeiten , um das Würfelnetz zu verzerren. Klicken Sie anschließend auf die Schaltfläche
Zurücksetzen . Der Würfel sollte in seine ursprüngliche Form zurückkehren.
Erklärung von Eckpunkten und Dreiecken in Unity
Ein Netz besteht aus Eckpunkten, die durch Kanten in Dreiecken verbunden sind. Dreiecke definieren die Grundform des Objekts.
Mesh-Klasse:
- Die Eckpunkte werden als Array von
Vector3
Werten gespeichert. - Dreiecke werden als ganzzahliges Array gespeichert, das den Indizes des Vertex-Arrays entspricht.
Das heißt, in einem einfachen Quad-Netz, das aus vier Eckpunkten und zwei Dreiecken besteht, sehen die Netzdaten folgendermaßen aus:
Vertex-Mapping
Hier wollen wir die Eckpunkte des Würfels als blaue Punkte anzeigen.
In
MeshInspector.cs gehen wir in die Funktion
EditMesh()
und fügen Folgendes hinzu:
handleTransform = mesh.transform;
Code Erläuterung:
handleTransform
Transformationswerte aus dem mesh
.handleRotation
den Rotationsmodus des aktuellen Gelenks ab.- Durchqueren Sie die Eckpunkte des Netzes und zeichnen Sie die Punkte mit
ShowPoint()
.
ShowPoint()
Funktion
ShowPoint()
unmittelbar nach dem Kommentar
//draw dot
Folgendes hinzu:
Vector3 point = handleTransform.TransformPoint(mesh.vertices[index]);
Code Erläuterung: Diese Linie konvertiert die lokale Position des Scheitelpunkts in eine Koordinate im Weltraum.
Fügen Sie in derselben Funktion im
if
Block unmittelbar nach der gerade hinzugefügten Codezeile Folgendes hinzu:
Handles.color = Color.blue; point = Handles.FreeMoveHandle(point, handleRotation, mesh.handleSize, Vector3.zero, Handles.DotHandleCap);
Code Erläuterung:
- Legt die Farbe, Größe und Position eines Punkts mithilfe der
Handles
. Handles.FreeMoveHandle()
erstellt einen unbegrenzten Bewegungsmanipulator, der das Ziehen und Ablegen vereinfacht, was für uns im nächsten Abschnitt nützlich ist.
Speichern Sie die Datei und kehren Sie zu Unity zurück. Überprüfen Sie die Cube-Eigenschaft im
Inspektor und stellen Sie sicher, dass die Option
Vertexpunkt verschieben aktiviert ist. Sie sollten jetzt sehen, dass das Netz auf dem Bildschirm mit mehreren blauen Punkten markiert ist. Hier sind sie - die Spitzen des Würfelnetzes! Versuchen Sie dies mit anderen 3D-Objekten und beobachten Sie die Ergebnisse.
Verschieben Sie einen einzelnen Scheitelpunkt
Beginnen wir mit dem einfachsten Schritt der Manipulation des Netzes - dem Verschieben eines einzelnen Scheitelpunkts.
Gehen Sie zu
MeshInspector.cs .
ShowPoint()
der
ShowPoint()
-Funktion unmittelbar nach dem
//drag
Kommentars und direkt vor den schließenden Klammern des
if
Blocks Folgendes hinzu:
if (GUI.changed)
Code Erläuterung:
GUI.changed
verfolgt alle Änderungen, die an Punkten auftreten, und arbeitet gut mit Handles.FreeMoveHandle()
, um einen Drag & Drop-Vorgang zu erkennen.- Für den ziehbaren Scheitelpunkt erhält die Funktion
mesh.DoAction()
ihre Index- und Transformationswerte als Parameter. Da sich die Transformationswerte des Scheitelpunkts im Weltraum befinden, konvertieren wir sie mit InverseTransformPoint()
in den lokalen Raum.
Speichern Sie die Skriptdatei und gehen Sie zu
MeshStudy.cs .
DoAction()
in
DoAction()
nach den öffnenden Klammern Folgendes hinzu:
PullOneVertex(index, localPos);
PullOneVertex()
der
PullOneVertex()
Funktion Folgendes
PullOneVertex()
:
vertices[index] = newPos;
Code Erläuterung:
- Wir aktualisieren den Zielscheitelpunkt mit dem Wert
newPos
. cMesh.vertices
aktualisierte Scheitelpunktwerte zu.- In
RecalculateNormals()
berechnen RecalculateNormals()
das Netz neu und zeichnen RecalculateNormals()
neu, sodass es den Änderungen entspricht.
Speichern Sie die Datei und kehren Sie zu Unity zurück. Versuchen Sie, Punkte auf den Würfel zu ziehen. Hast du ein gebrochenes Netz gesehen?
Es scheint, dass einige der Scheitelpunkte dieselbe Position haben. Wenn wir also nur einen ziehen, bleiben die verbleibenden Scheitelpunkte dahinter und das Netz bricht. Im nächsten Abschnitt werden wir dieses Problem beheben.
Alle ähnlichen Eckpunkte finden
Visuell besteht ein Würfelnetz aus acht Eckpunkten, sechs Seiten und 12 Dreiecken. Lassen Sie uns überprüfen, ob dies so ist.
Öffnen Sie
MeshStudy.cs ,
werfen Sie einen Blick vor die Funktion
Start()
und suchen Sie die Variable
vertices
. Wir werden folgendes sehen:
[HideInInspector] public Vector3[] vertices;
Code Erläuterung:
[HideInInspector]
verbirgt eine gemeinsam genutzte Variable im
Inspector- Fenster.
Kommentieren Sie dieses Attribut aus:
Hinweis: Das Ausblenden von Scheitelpunktwerten hilft [HideInInspector]
bei komplexeren 3D-Netzen. Da die Größe des Scheitelpunktarrays Tausende von Elementen erreichen kann, kann dies zu einer Hemmung der Einheit führen, wenn versucht wird, den Arraywert im Inspektor anzuzeigen.
Speichern Sie die Datei und kehren Sie zu Unity zurück. Gehen Sie zum
Inspektor . Jetzt wurde unter der
Skriptkomponente "Netzstudie" die Eigenschaft "
Vertices" angezeigt. Klicken Sie auf das Pfeilsymbol daneben. Sie
Vector3
Array der
Vector3
Elemente.
Sie können sehen, dass die Größe des Arrays 24 beträgt, dh es gibt Scheitelpunkte mit derselben Position! Bevor Sie fortfahren, müssen Sie
[HideInInspector]
.
Warum gibt es 24 Eckpunkte?Es gibt viele Theorien zu diesem Thema. Die einfachste Antwort lautet jedoch: Der Würfel hat sechs Seiten, und jede Seite besteht aus vier Eckpunkten, die eine Ebene bilden.
Daher lautet die Berechnung wie folgt: 6 x 4 = 24 Eckpunkte.
Sie können nach anderen Antworten suchen. Im Moment ist es jedoch einfach zu wissen, dass einige Netze Scheitelpunkte haben, die dieselbe Position haben.
Ersetzen Sie in
MeshStudy.cs den
gesamten Code in der
DoAction()
Funktion durch Folgendes:
PullSimilarVertices(index, localPos);
Gehen wir in die
PullSimilarVertices()
-Funktion und fügen Folgendes hinzu:
Vector3 targetVertexPos = vertices[index];
Code Erläuterung:
- Wir erhalten die Position des Zielscheitelpunkts, der als Argument für die
FindRelatedVertices()
-Methode verwendet wird. - Diese Methode gibt eine Liste von Indizes zurück (die Scheitelpunkten entsprechen), die dieselbe Position wie der Zielscheitelpunkt haben.
- Die Schleife durchläuft die gesamte Liste und setzt die entsprechenden Eckpunkte auf
newPos
. cMesh.vertices
aktualisierte vertices
zu. Dann rufen wir RecalculateNormals()
auf, um das Netz mit den neuen Werten neu zu zeichnen.
Speichern Sie die Datei und kehren Sie zu Unity zurück. Ziehen Sie einen der Scheitelpunkte. Jetzt sollte das Netz seine Form behalten und nicht kollabieren.
Nachdem wir den ersten Schritt zum Bearbeiten der Netze abgeschlossen haben, speichern Sie die Szene und fahren Sie mit dem nächsten Abschnitt fort.
Netzmanipulation
In diesem Abschnitt erfahren Sie, wie Sie Netze in Echtzeit bearbeiten. Es gibt viele Möglichkeiten, aber in diesem Tutorial werden wir uns die einfachste Art der Netzmanipulation ansehen, nämlich das Verschieben der zuvor erstellten Netzscheitelpunkte.
Ausgewählte Indizes sammeln
Beginnen wir mit der Auswahl der Eckpunkte, die wir in Echtzeit verschieben werden.
Öffnen Sie Szene
02 Herznetz aus dem Ordner
Szenen erstellen . Im Szenenfenster sehen Sie eine rote Kugel. Wählen Sie
Sphere in the
Hierarchy und gehen Sie zu
Inspector . Sie werden sehen, dass die
Heart Mesh-Skriptkomponente an das Objekt angehängt ist.
Jetzt benötigen wir das Editor-Skript für dieses Objekt, um die Eckpunkte des Netzes im Szenenfenster anzuzeigen. Gehen Sie zum
Editor- Ordner und
doppelklicken Sie auf
HeartMeshInspector.cs .
ShowHandle()
in der
ShowHandle()
-Funktion im
if
Block Folgendes hinzu:
Handles.color = Color.blue; if (Handles.Button(point, handleRotation, mesh.pickSize, mesh.pickSize, Handles.DotHandleCap))
Code Erläuterung:
- Legt die Eckpunkte des Netzes fest und zeigt sie als Typ
Handles.Button
. - Wenn Sie darauf
mesh.selectedIndices
, wird der ausgewählte Index zur mesh.selectedIndices
der gedrückten mesh.selectedIndices
.
OnInspectorGUI()
in
OnInspectorGUI()
vor der schließenden Klammer Folgendes hinzu:
if (GUILayout.Button("Clear Selected Vertices")) { mesh.ClearAllData(); }
Erläuterung des Codes: Auf diese Weise fügen wir dem
Inspektor eine Schaltfläche zum Zurücksetzen hinzu, um
mesh.ClearAllData()
.
Speichern Sie die Datei und öffnen Sie
HeartMesh.cs im Ordner
Scripts .
ClearAllData()
Funktion
ClearAllData()
Folgendes hinzu:
selectedIndices = new List<int>(); targetIndex = 0; targetVertex = Vector3.zero;
Code Erläuterung: Der Code löscht die Werte in
selectedIndices
und
targetIndex
. Außerdem wird
targetVertex
.
Speichern Sie die Datei und kehren Sie zu Unity zurück. Wählen Sie
Sphere aus und
rufen Sie den
Inspector für die
HeartMesh-Skriptkomponente auf . Erweitern Sie
Ausgewählte Indizes, indem Sie auf das Pfeilsymbol daneben klicken. Auf diese Weise können wir jeden zur Liste hinzugefügten Scheitelpunkt verfolgen.
Aktivieren Sie
Ist Bearbeitungsmodus über das Kontrollkästchen daneben. Aus diesem Grund werden die Eckpunkte des Netzes im Szenenfenster gezeichnet. Durch Klicken auf die blauen Punkte in den
ausgewählten Indizes sollten die Werte entsprechend geändert werden. Testen Sie auch die Schaltfläche
Ausgewählte Scheitelpunkte löschen , um sicherzustellen, dass alle Werte
gelöscht werden.
Hinweis: Im geänderten benutzerdefinierten
Inspektor haben wir die Möglichkeit, den Transformationsmanipulator mithilfe des
Transformationshandles anzeigen ein- / auszublenden. Keine Panik, wenn Sie den Transformationsmanipulator in anderen Szenen nicht finden! Schalten Sie es vor dem Beenden ein.
Eine Kugel in ein Herz verwandeln
Das Ändern von Netzscheitelpunkten in Echtzeit besteht im Wesentlichen aus drei Schritten:
- Kopieren Sie die aktuellen
mVertices
(vor der Animation) nach mVertices
. mVertices
Berechnungen durch und ändern die Werte in mVertices
.- Aktualisieren Sie die aktuellen
mVertices
mit mVertices
wenn Sie sie bei jedem Schritt ändern, und lassen Sie Unity die Normalen automatisch berechnen.
Öffnen Sie
HeartMesh.cs und die folgenden Variablen vor der Funktion
Start()
:
public float radiusofeffect = 0.3f;
Code Erläuterung:
- Der Radius des vom Zielscheitelpunkt betroffenen Bereichs.
- Kraft ziehen.
- Die Dauer der Animation.
- Der aktuelle Index der Liste
selectedIndices
.
Init()
Funktion
Init()
vor dem
if
Block Folgendes hinzu:
currentIndex = 0;
Erläuterung des Codes: Zu Beginn des Spiels wird
currentIndex
auf 0 gesetzt, den ersten Index der Liste
selectedIndices
.
Init()
derselben
Init()
Funktion vor der schließenden Klammer des
else
Blocks Folgendes hinzu:
StartDisplacement();
StartDisplacement()
: Führen Sie die Funktion
StartDisplacement()
aus, wenn
isEditMode
false ist.
StartDisplacement()
Funktion
StartDisplacement()
Folgendes hinzu:
targetVertex = oVertices[selectedIndices[currentIndex]];
Code Erläuterung:
- Wählen Sie
targetVertex
, um die Animation zu starten. isAnimate
Sie die Startzeit ein und ändern Sie den Wert von isAnimate
in true.
Erstellen Sie nach der Funktion
StartDisplacement()
Funktion
FixedUpdate()
mit dem folgenden Code:
void FixedUpdate()
Code Erläuterung:
- Die Funktion
FixedUpdate()
wird in einer festen FPS-Schleife ausgeführt. - Wenn
isAnimate
false ist, überspringen Sie den folgenden Code. runtime
ändern.- Wenn die
runtime
innerhalb der duration
, erhalten wir die Weltkoordinaten von targetVertex
und DisplaceVertices()
, wobei der Zielscheitelpunkt mit den radiusofeffect
pullvalue
und radiusofeffect
. - Ansonsten ist die Zeit abgelaufen. Fügen Sie einen zu
currentIndex
. - Überprüfen Sie, ob
currentIndex
zu selectedIndices
. Gehen Sie mit StartDisplacement()
zum nächsten Scheitelpunkt in der Liste. - Andernfalls ändern
oMesh
am Ende der Liste die oMesh
Daten in das aktuelle Netz und isAnimate
auf false, um die Animation zu stoppen.
DisplaceVertices()
in
DisplaceVertices()
Folgendes hinzu:
Vector3 currentVertexPos = Vector3.zero; float sqrRadius = radius * radius;
Code Erläuterung:
- Das Quadrat des Radius.
- Wir durchlaufen jeden Scheitelpunkt des Netzes.
sqrMagnitude
zwischen currentVertexPos
und targetVertexPos
.- Wenn
sqrMagnitude
überschreitet, fahren Sie mit dem nächsten Scheitelpunkt fort. - Andernfalls bestimmen Sie den
falloff
, der vom distance
aktuellen Scheitelpunkts vom Mittelpunkt des falloff
abhängt. Vector3
neue Vector3
Position und wenden Sie ihre Transformation auf den aktuellen Scheitelpunkt an.- Wenn Sie die Schleife verlassen, weisen wir den
mVertices
die geänderten mVertices
Werte zu und erzwingen, dass Unity die Normalen neu berechnet.
Quelle der Falloff-Technologie
Die ursprüngliche Formel stammt aus der Asset-Paketdatei " Verfahrensbeispiele" , die kostenlos aus dem Unity Asset Store heruntergeladen werden kann.
Speichern Sie die Datei und kehren Sie zu Unity zurück. Wählen Sie
Sphere aus ,
wechseln Sie zur
HeartMesh- Komponente und versuchen Sie, der Eigenschaft
Selected Indices einige Scheitelpunkte hinzuzufügen. Deaktivieren Sie den
Bearbeitungsmodus und klicken Sie auf
Wiedergabe , um das Ergebnis Ihrer Arbeit anzuzeigen.
Experimentieren Sie mit den Werten für
Radiusofeffekt ,
Pullvalue und
Dauer , um unterschiedliche Ergebnisse zu erhalten. Wenn Sie bereit sind, ändern Sie die Einstellungen gemäß dem folgenden Screenshot.
Klicken Sie auf
Spielen . Hat sich deine Kugel in ein Herz verwandelt?
Glückwunsch! Im nächsten Abschnitt speichern wir das Netz als Fertighaus für die zukünftige Verwendung.
Speichern des Netzes in Echtzeit
Um ein herzförmiges prozedurales Netz im Wiedergabemodus zu speichern, müssen Sie ein Fertighaus vorbereiten, dessen Kind ein 3D-Objekt ist, und dann sein Netzelement mithilfe eines Skripts durch ein neues ersetzen.
Suchen
Sie im
Projektfenster CustomHeart im Ordner
Prefabs . Klicken Sie auf das Pfeilsymbol, um den Inhalt zu erweitern, und wählen Sie
Kind aus . Sie sehen jetzt ein Sphere-Objekt im
Inspektor- Vorschaufenster. Dies ist das Fertighaus, in dem die Daten für das neue Netz gespeichert werden.
Öffnen Sie
HeartMeshInspector.cs .
OnInspectorGUI()
Funktion
OnInspectorGUI()
vor der schließenden Klammer Folgendes hinzu:
if (!mesh.isEditMode && mesh.isMeshReady) { string path = "Assets/Prefabs/CustomHeart.prefab";
Code Erläuterung:
- Legt den
path
zum Pfad zum CustomHeart- Fertighausobjekt fest . - Erstellt zwei Objekte aus dem CustomHeart- Fertighaus , eines zum Erstellen einer Instanz als GameObject (
pfObj
) und das zweite als Links ( pfRef
). - Erstellt eine Instanz des pfMesh-Mesh-
pfMesh
. Wenn es nicht gefunden wird, wird ein neues Netz erstellt, andernfalls werden die vorhandenen Daten bereinigt. pfMesh
mit neuen pfMesh
und fügt sie dann CustomHeart als Asset hinzu .
- Füllt ein Mesh-Asset in
gameObj
Wert pfMesh
. - Ersetzt CustomHeart durch
gameObj
bereits vorhandene Verbindungen gameObj
. gameObj
.
Speichern Sie die Datei und gehen Sie zu
HeartMesh.cs .
SaveMesh()
in der allgemeinen
SaveMesh()
-Methode nach dem Erstellen der
nMesh
Instanz Folgendes hinzu:
nMesh.name = "HeartMesh"; nMesh.vertices = oMesh.vertices; nMesh.triangles = oMesh.triangles; nMesh.normals = oMesh.normals;
Code Erläuterung: Gibt ein Netzelement mit Werten aus einem herzförmigen Netz zurück.
Speichern Sie die Datei und kehren Sie zu Unity zurück. Klicken Sie auf
Wiedergabe . Nach Abschluss der Animation wird im
Inspektor die Schaltfläche
Netz speichern angezeigt . Klicken Sie auf die Schaltfläche, um das neue Netz zu speichern, und stoppen Sie den Player.
Gehen Sie zum Ordner
Prefabs und sehen Sie sich das CustomHeart-
Prefab an . Sie sollten sehen, dass es jetzt im CustomHeart-
Fertighausobjekt ein völlig neues herzförmiges Netz gibt.
Ausgezeichnete Arbeit!Alles zusammenfügen
In der vorherigen Szene verwendete die Funktion
DisplaceVertices()
die Falloff-Formel, um die Widerstandskraft zu bestimmen, die auf jeden Scheitelpunkt innerhalb eines bestimmten Radius angewendet wurde. Der Punkt des „Abfalls“, an dem die Widerstandskraft abzunehmen beginnt, hängt von der Art des verwendeten Abfalls ab: Linear, Gauß oder Nadel. Jeder Typ erzeugt unterschiedliche Ergebnisse im Netz.
In diesem Abschnitt sehen wir uns eine andere Möglichkeit an, Scheitelpunkte zu bearbeiten: die Verwendung einer bestimmten Kurve. Unter der Regel, dass die Geschwindigkeit gleich der durch die Zeit geteilten Entfernung (d = (v / t)) ist, können wir die Position des Vektors anhand seiner durch die Zeit geteilten Entfernung bestimmen.
Verwenden der Kurvenmethode
Speichern Sie die aktuelle Szene und öffnen Sie
03 Customize Heart Mesh aus dem Ordner
Scenes . Sie sehen eine
Hierarchieinstanz des CustomHeart-
Fertighauses . Klicken Sie auf das Pfeilsymbol daneben, um den Inhalt zu erweitern, und wählen Sie
Kind aus .
Zeigen Sie die Eigenschaften im
Inspektor an .
Sie sehen die Netzfilterkomponente mit dem Heart Mesh Asset . Hängen Sie ein benutzerdefiniertes Herzskript als Komponente an Child an . Jetzt sollte das Asset von HeartMesh zu Klon wechseln .Öffnen Sie anschließend CustomHeart.cs im Ordner Scripts . Fügen Sie vor der Funktion Start()
Folgendes hinzu: public enum CurveType { Curve1, Curve2 } public CurveType curveType; Curve curve;
Erläuterung des Codes: Hier wird eine allgemeine Aufzählung unter dem Namen erstellt CurveType
, nach der sie vom Inspektor zur Verfügung gestellt wird .Gehen Sie zu CurveType1()
und fügen Sie Folgendes hinzu: Vector3[] curvepoints = new Vector3[3];
Code Erläuterung:- Eine einfache Kurve besteht aus drei Punkten. Stellen Sie die Punkte für die erste Kurve ein.
- Mit Hilfe der Hilfe erzeugen wir die erste Kurve
Curve()
und weisen ihre Werte zu curve
. Die gezeichnete Kurve kann in der Vorschau angezeigt werden, wenn Sie als letzten Parameter true angeben.
Gehen Sie zu CurveType2()
und fügen Sie Folgendes hinzu: Vector3[] curvepoints = new Vector3[3];
Code Erläuterung:- Stellen Sie die Punkte für die zweite Kurve ein.
- Wir erzeugen die zweite Kurve mit
Curve()
und weisen ihre Werte zu curve
. Die gezeichnete Kurve kann in der Vorschau angezeigt werden, wenn Sie als letzten Parameter true angeben.
B StartDisplacement()
Fügen Sie vor der schließenden Klammer Folgendes hinzu: if (curveType == CurveType.Curve1) { CurveType1(); } else if (curveType == CurveType.Curve2) { CurveType2(); }
Codeerklärung: Hier überprüfen wir die vom Benutzer ausgewählte Option curveType
und generieren sie entsprechend curve
.B DisplaceVertices()
, for
fügen Sie in der Schleifenanweisung vor den schließenden Klammern Folgendes hinzu: float increment = curve.GetPoint(distance).y * force;
Code Erläuterung:- Wir erhalten die Position der Kurve bei der gegebenen
distance
und multiplizieren ihren Wert y
mit force
, um zu erhalten increment
. - Erstellen Sie einen neuen Datentyp
Vector3
, um die neue Position des aktuellen Scheitelpunkts zu speichern, und wenden Sie dessen Transformation entsprechend an.
Speichern Sie die Datei und kehren Sie zu Unity zurück. Überprüfen Sie die Eigenschaften des Bauteils CustomHeart Spielobjekt Kind . Hier finden Sie eine Dropdown-Liste sehen , wo Sie auswählen können , die Kurve den Typ . In der Dropdown- Typen bearbeiten wählen hinzufügen Indizes oder den Remove - Indizes , die Liste der Eckpunkt zu aktualisieren und mit verschiedenen Einstellungen zu experimentieren.Geben Sie die Werte gemäß dem Screenshot ein, um detaillierte Ergebnisse für verschiedene Kurventypen anzuzeigen:Eine Liste der Kurventyp , wählen Sie Curve1 , stellen Sie sicher , zu bearbeiten Typ wählen Sie Keine , und klicken Sie auf den Play . Sie sollten sehen, dass das Netz in das Muster abweicht. Rollen Sie das Modell, um es in der Seitenansicht zu sehen, und vergleichen Sie die Ergebnisse für beide Kurventypen. Hier sehen Sie, wie sich der ausgewählte Kurventyp auf den Netzversatz auswirkt.Das ist alles!
Sie können auf Ausgewählte Scheitelpunkte löschen klicken , um Ausgewählte Indizes zurückzusetzen und mit Ihren eigenen Mustern zu experimentieren. Vergessen Sie jedoch nicht, dass es andere Faktoren gibt, die das Endergebnis des Netzes beeinflussen, nämlich:- Der Wert des Radius.
- Die Verteilung der Eckpunkte im Bereich.
- Die Musterposition der ausgewählten Scheitelpunkte.
- Die für den Offset ausgewählte Methode.
Wohin als nächstes?
Dateien des fertigen Projekts befinden sich im Archiv des Lernprojekts.Hör hier nicht auf! Probieren Sie die komplexeren Techniken aus, die im Lernprogramm zur Erstellung von Unity Procedural Maze verwendet werden .Ich hoffe, Ihnen hat dieses Tutorial gefallen und Sie fanden die Informationen hilfreich. Ein besonderer Dank spricht ich Jasper Flick von Catlike Coding für seine hervorragend Tutorials , die mir geholfen , eine Demo für mein Projekt zusammenzustellen .