Jump to content
Unity Insider Forum

Terep

Members
  • Gesamte Inhalte

    9
  • Benutzer seit

  • Letzter Besuch

Alle erstellten Inhalte von Terep

  1. Hallo Nach einer mehrjährigen Pause habe ich auf die aktuelle Unity Version 5.5.4p4 Personal (64bit) aktualisiert. Um wieder ein Gefühl für Unity zu bekommen, habe ich das Tutorial SpaceShooter gestartet. Dabei stelle ich fest, dass in der Hierarchy so gut wie keine Gameobjekte gezeigt werden. ich habe die Complete-Game Version gestartet. Dort tauchen nur die Licht-Objekte auf. Dies kann ich nicht nachvollziehen. Warum ist das so? Muss ich in der Scene auf das Objekt klicken, damit ich es im Inspector bearbeiten kann? Nach meiner Sicht war die strukturierte Auflistung aller Gameobjekte sehr nützlich. Terep Erledigt: Ich hatte im Filter Ligthing stehen. So war alles ausgeblendet.
  2. Hallo In meinem ersten Posting „Einfache Funktions-Landschaft mit XY-Koordinaten generieren“ war ich von unity noch zu weit weg. Jetzt habe ich mich mit tile-mapping beschäftigt und versucht, mir dies zu erarbeiten. Am besten klappt es, wenn ich es als Tutorial formuliere. Dann bleibe ich besser am Thema. Dies hat auch alles gut geklappt. Was mich interessieren würde ist die Frage, ob ich die Sachen richtig beschreibe oder ob ich wegtriffte. Es folgt meine Ausarbeitung: Text-Tutorial Eine 2D-Welt mit tiles also mit einer Tilemap erstellen Teil 1 Die Map darstellen Wer mit der Überschrift nichts anfangen kann, bitte nach dem Stichwort Bilder zu einer Tilemap surfen. Der erste Gedanke ist es, hier Gameobjekte vom Typ Plane als Basis zu verwenden. Diesen kann man mit einer Textur versehen und mit Scale soweit verkleinern, dass es möglich ist, so eine Landschaft zu generieren. Nur sind diese tiles als klein gedacht. Ein Landschaftsausschnitt mit der Fläche 100 * 100 hat schon 10.000 Gameobjekte vom Typ Plane. Jede Plane hat per Definition eine Größe von 10 * 10 Quards. Ein Quard besteht aus 2 Tris (Dreiecken). Das heißt bei 10.000 Gameobjekten * 200 Tries mal 60 Framerate pro Sekunde. Eine gewaltige Zahl. Folglich ist die Performance schon miserabel, obwohl noch nichts passiert ist. Dieser Lösungsweg wird zur Sackgasse. Hier gibt es natürlich Alternativen. Zum Beispiel werden wir jetzt ein eigenes Mesh generieren. Einfach gesagt, besteht ein Mesh im Wesentlichen aus Dreiecken. Für unsere Landkarte brauchen wir also nur 2 Dreiecke zu einem Rechteck zusammenfügen, unsere vorbereitete Karte als Textur verwenden und fertigt ist es. Ist dies vorbereitet, merkt man nicht, was für ein Aufwand dahinter steht. Man klickt halt zusammen und ist vielleicht irritiert, dass so viele Spiele ganz ähnlich daherkommen. Individuelle Spiele verlangen entsprechenden persönlichen Einsatz. Das sollte Grund genug sein, das Folgende zu Lesen. Vorweg, inspiriert hat mich die englisch gesprochene Unity 3D Tutorial Serie von quill18creates TileMaps #2 und das Buch „Spiele entwickeln mit Unity“ von Carsten Seifert. Wir beginnen in unity in einer 3D-Umgebung in dem wir ein leeres Gameobject (create empty) erstellen und es in „TileMap“ umbenennen. Danach ziehen wir es aus der Historie in die Assets und erhalten so ein Prefab Was gehört jetzt eigentlich inhaltlich in das noch leere Gameobjekt? Im ersten Gedankengang hatten wir das Gameobjekt Plane verwendet. Nur aus Performancegründen haben wir dies nicht weiterverfolgt. Die Plane hat all dass, was wir brauchen: Mesh -Filter, -Collider und -Renderer. Wir werden jetzt sehen, wie funktional Scripte sind. Jetzt erzeugen wir ein c-sharp Script mit der Bezeichnung „TileMap“ und fügen es als Komponente dem Gameobjekt TileMap zu. Wir rufen das Script auf. Um Komponenten per Script hinzuzufügen, müssen wir unter den using-Anweisungen die benötigten Komponenten Mesh -Filter, -Collider und -Renderer nur anfordern. Wir löschen die void-Update-Methode und formulieren eine bildeMesh Methode. Da diese Methode nur einmal aufgerufen werden darf, kommt der Methodenaufruf in Start() auf. Das Script sieht jetzt wie folgt aus: using UnityEngine; using System.Collections; [RequireComponent(typeof(MeshFilter))] [RequireComponent(typeof(MeshRenderer))] [RequireComponent(typeof(MeshCollider))] public class TileMap : MonoBehaviour { void Start () { bildeMesh (); } void bildeMesh () { } } Testweise starten wir und prüfen so, ob Fehler vorliegen. Sehen tuen wir im Game-Schirm noch nichts. Was auffällt, die required-Komponenten sind jetzt im Gameobjekt vorhanden. Wenn nicht, einmal das Script entfernen und erneut als Komponente hinzufügen. Es geht im Script innerhalb von bildeMesh weiter Wir wollen ein Mesh Objekt erzeugen auf dem wir auf einem Rechteck die Landkarte darstellen. Das Rechteck wird durch zwei Dreiecke gebildet. Die Eckpunkte der Dreiecke sind die vertices. Da wir in 3D arbeiten, werden die vertices mit Vector3 Variablen angegeben. Wichtig ist die Reihenfolge bei der Nennung der Eckpunkte. Diese müssen im Uhrzeigersinn erfolgen. Konkret: das Rechteck: oben links = 0, oben rechts = 1, unten links = 2, unten rechts = 3 Das erste Dreieck: Oben = 0, unten rechts = 3, unten links = 2 Das zweite Dreieck: Oben links = 0, oben rechts = 1, unten = 3 Die erforderlichen Daten müssen wir vor der Mesherzeugung angeben. Dies machen wir in der bildeMesh-Methode mit Arrays. Vector3[] vertices = new Vector3[4]; int[] triangle = new int[6]; Jetzt benötigen wir noch normals für die Ausrichtung. Vector3[] normals = new Vector3[4]; Die einzelnen Arraydaten sind im Script unten gelistet. Jetzt können wir das Objekt erzeugen und die Daten übergeben Mesh mesh = new Mesh (); mesh.vertices = vertices; mesh.triangles = triangles; mesh.normals = normals; Wir schaffen Zugriffe auf die Komponenten: MeshFilter mesh_filter = GetComponent<MeshFilter> (); MeshRenderer mesh_renderer = GetComponent<MeshRenderer> (); MeshCollider mesh_collider = GetComponent<MeshCollider> (); mesh_filter.mesh = mesh; Die bisherige bildeMesh () Methode void bildeMesh () { // Das Rechteck benötigt 4 Punkte im 3dimensionalen Raum Vector3[] vertices = new Vector3[4]; vertices [0] = new Vector3 (0, 0, -1); vertices [1] = new Vector3 (1, 0, -1); vertices [2] = new Vector3 (0, 0, 0); vertices [3] = new Vector3 (1, 0, 0); // Ein Dreieck benötigt 3 Punkte mal 2 Dreicke = 6 int[] triangles = new int[6]; triangles [0] = 0; triangles [1] = 3; triangles [2] = 2; triangles [3] = 0; triangles [4] = 1; triangles [5] = 3; // Ausrichtung, hauptsächlich für die Lichtberechnung Vector3[] normals = new Vector3[4]; // die ausführliche Schreibweise: normals [0] = new Vector3(0, 0, 0); normals [0] = Vector3.up; normals [1] = Vector3.up; normals [2] = Vector3.up; normals [3] = Vector3.up; // Mesh wird erzeugt Mesh mesh = new Mesh (); // die Basis-Daten werden den Mesh-Membern mitgeteilt mesh.vertices = vertices; mesh.triangles = triangles; mesh.normals = normals; // Die Daten unseren Komponenten übergeben MeshFilter mesh_filter = GetComponent<MeshFilter> (); MeshRenderer mesh_renderer = GetComponent<MeshRenderer> (); MeshCollider mesh_collider = GetComponent<MeshCollider> (); mesh_filter.mesh = mesh; } Wenn wir jetzt starten, kommt ein rosa Rechteck. Es ist nur schräg sichtbar. Stellen wir im Gameobjekt Tilemap Rotation x auf 90 bzw. auf 270, schon ist es besser. Warum, es fehlt das „material“ auf dem die Textur kommt, unsere persönlich erstellte Karte. Wenn wir keine haben, können wir ein x-beliebiges Bild nehmen und es als Textur wie folgt verwenden. Wir create material und benennen es MatKarte. Wir klicken auf MatKarte und es erscheint im Inspector. Jetzt können wir unsere Textur darauf ziehen. MatKarte fügen wir als Komponente der TileMap zu. Wir starten und sehen zwar nicht mehr pink aber auch nicht unsere Textur. Das liegt daran, dass wir unity sagen müssen, wo genau die Karte hin muss. Wir sehen zwar eindimensional die Karte, unity arbeitet aber mehrdimensional. Stichwort UV-Map. Wir erzeugen einen Vector2 Array. Wir müssen die 4 Eckpunkte unseres Rechtecks angeben. Wir ergänzen unser Listung um Vector2[] uv = new Vector2[4]; uv[0] = new Vector2(0, 0); uv[1] = new Vector2(1, 0); uv[2] = new Vector2(0, 1); uv[3] = new Vector2(1, 1); Jetzt sollte es aber klappen. Ist das Bild noch verzerrt, hängt es an der Größe der TileMap. Im Verhältnis der Bildgröße (Breite, Höhe) in Transform Scale verkleinern und die Position anpassen. Das komplette Script: using UnityEngine; using System.Collections; [ RequireComponent(typeof(MeshFilter) ) ] [ RequireComponent(typeof(MeshRenderer) ) ] [ RequireComponent(typeof(MeshCollider) ) ] public class TileMap : MonoBehaviour { // Use this for initialization void Start () { bildeMesh (); } // Update is called once per frame void bildeMesh () { Vector3[] vertices = new Vector3[4]; int[] triangles = new int[6]; Vector3[] normals = new Vector3[4]; Vector2[]uv = new Vector2[4]; vertices [0] = new Vector3 (0, 0, 0); vertices [1] = new Vector3 (100, 0, 0); vertices [2] = new Vector3 (0, 0, -100); vertices [3] = new Vector3 (100, 0, -100); triangles [0] = 0; triangles [1] = 3; triangles [2] = 2; triangles [3] = 0; triangles [4] = 1; triangles [5] = 3; // die ausführliche Schreibweise: normals[0] = Vector3 (0, 0, 0); normals[0] = Vector3.up; normals[1] = Vector3.up; normals[2] = Vector3.up; normals[3] = Vector3.up; uv [0] = new Vector2 (0, 0); uv [1] = new Vector2 (1, 0); uv [2] = new Vector2 (0, 1); uv [3] = new Vector2 (1, 1); Mesh mesh = new Mesh (); mesh.vertices = vertices; mesh.triangles = triangles; mesh.normals = normals; mesh.uv = uv; MeshFilter mesh_filter = GetComponent<MeshFilter> (); MeshRenderer mesh_renderer = GetComponent<MeshRenderer> (); MeshCollider mesh_collider = GetComponent<MeshCollider> (); mesh_filter.mesh = mesh; } } Das ist mein Einstieg ins Tile-Mapping Terep
×
×
  • Neu erstellen...