Wie mache ich das Gelände unter einem Spielobjekt flach?

10

Ich habe ein Skript, das ein Geländeobjekt erstellt und mit Texturen malt, aber ich habe ein Problem. Wenn ich versuche, Spielobjekte zu platzieren (z. B. das einfache Wasserobjekt, das Unity bereitstellt), verwende ich einen Raycast, um die richtige Höhe zum Platzieren des Spielobjekts zu bestimmen. Dadurch wird jedoch nur sichergestellt, dass es an diesem bestimmten Punkt korrekt platziert wird.

Wie würde ich vorgehen, um das Gelände unter dem Spielobjekt zu glätten, damit es nicht ins Gelände gelangt oder bei Hügeln in der Luft hängt?

Rapida
quelle
3
Finden Sie alle Eckpunkte, die die Geländedreiecke bilden, unter dem Spielobjekt. Machen Sie die y-Koordinate aller dieser Eckpunkte gleich.
MichaelHouse

Antworten:

6

Wie ich in meinem Kommentar sagte, möchten Sie alle Eckpunkte, aus denen die Dreiecke bestehen, unter Ihrem Spielobjekt finden und ihren y-Wert auf denselben Wert setzen.

Ich werde meinen Kommentar mit detaillierteren Schritten erweitern. Ich bin mit Unity nicht allzu vertraut, daher kenne ich nicht die besten Tools für den Job, aber ich glaube, ich kann Sie auf den richtigen Weg bringen.

Brute-Force-Methode:

  1. Wirf ein Strahlengitter direkt von deinem Spielobjekt. Das Gitter sollte eng genug sein, um sicherzustellen, dass keine Dreiecke auf der Geländeoberfläche übersehen werden.
  2. Für jeden Strahl, der auf etwas trifft, können Sie das Dreieck im Geländennetz wie folgt erhalten:

    RaycastHit hit;
    if (!Physics.Raycast(camera.ScreenPointToRay(Input.mousePosition), out hit))
        return;
    
    MeshCollider meshCollider = hit.collider as MeshCollider;
    if (meshCollider == null || meshCollider.sharedMesh == null)
        return;
    
    Mesh mesh = meshCollider.sharedMesh;
    Vector3[] vertices = mesh.vertices;
    int[] triangles = mesh.triangles;
    Vector3 p0 = vertices[triangles[hit.triangleIndex * 3 + 0]];
    Vector3 p1 = vertices[triangles[hit.triangleIndex * 3 + 1]];
    Vector3 p2 = vertices[triangles[hit.triangleIndex * 3 + 2]];
  3. p0, p1 und p2 sind alle Positionen der drei Eckpunkte, aus denen das getroffene Dreieck besteht. Sie möchten jede dieser Scheitelpunktpositionen so anpassen, dass sie denselben yWert hat. Sie können entweder alle Scheitelpunkte sammeln und dann alle auf einen Durchschnittswert setzen y, oder Sie können den ursprünglich ausgewählten yWert verwenden, den Sie beim Platzieren Ihres Spielobjekts gefunden haben.

Optimierungen:

  • Anstatt nur ein Gitter aus Strahlen zu werfen, können Sie einen Kollider vom Spielobjekt nach unten streichen und die Kontaktpunkte der Kollisionen zwischen dem Kollider des Spielobjekts und dem Geländekollisionsnetz sammeln. Führen Sie dann für jeden dieser Kontaktpunkte die obigen Schritte aus, um die Scheitelpunkte zu erhalten, die Sie verschieben möchten.

  • Erstellen Sie Ihr Terrain so, dass die einzelnen Scheitelpunkte xund zWerte an einem Raster ausgerichtet sind und nur in ihrem yWert variieren . Jetzt können Sie leicht die Grenzen Ihres Spielobjekts ermitteln und alle y-Werte der Eckpunkte innerhalb dieser Grenzen ändern.

Diese letzte Optimierung ist wirklich eine alternative Methode, die wahrscheinlich einfach zu implementieren und ziemlich effektiv wäre.

MichaelHouse
quelle
Soweit ich weiß, hat das Terrain- Objekt ( docs.unity3d.com/Documentation/ScriptReference/Terrain.html ) einen TerrainCollider ( docs.unity3d.com/Documentation/ScriptReference/… ) und keinen MeshCollider ( docs.unity3d.com/Documentation) / ScriptReference /… ), daher fehlt eine sharedMesh-Eigenschaft, die Sie in Schritt 2 verwenden möchten. Ich nahm an, dass ich eine Art Logik benötigen würde, um die Höhenkarte zu ändern, die in der TerrainData-Eigenschaft gespeichert ist.
Rapida
Sie können dies hier überprüfen: forum.unity3d.com/threads/… Außerdem scheint das Geländeobjekt ein reguläres Netz zu haben, sodass die zweite Optimierung möglicherweise die beste Wahl ist.
MichaelHouse
1

Normalerweise soll der Boden unter dem Objekt flach und der Boden unmittelbar um ihn herum geglättet sein.

Wenn das Land aus einem Gitter besteht und das Gebäude achsenausgerichtet ist, ist dies viel einfacher.

Im allgemeinen Fall unterteilen Sie Dreiecke, auf denen sich das Gebäude befindet, und setzen dann das y aller Scheitelpunkte auf den Dreiecken, auf denen sich das Gebäude befindet, auf dasselbe y . Anschließend glätten Sie den Mittelpunkt für alle Scheitelpunkte innerhalb eines bestimmten Abstands, die sich befinden nicht sich unter einem Gebäude.

Ich habe diesen Ansatz verwendet, um Straßen auf ein 3D-Gelände zu bringen.

Normalerweise möchten Sie eine Mindesttrennung zwischen Gebäuden erzwingen, um genügend Land zum Glätten zu haben. Oder Sie führen den Algorithmus vorläufig vor dem Platzieren aus und prüfen, ob eine bestimmte Steilheitsschwelle überschritten wird, um zu überwachen, wo der Benutzer Gebäude platzieren kann.

Wille
quelle