Jak spłaszczyć teren pod obiektem gry?

10

Mam skrypt, który tworzy obiekt terenu i maluje go teksturami, ale mam problem. Kiedy próbuję umieścić obiekty gry (takie jak prosty obiekt wodny, który zapewnia jedność), używam Raycast, aby określić prawidłową wysokość do umieszczenia obiektu gry, ale to tylko zapewnia, że ​​jest on prawidłowo umieszczony w tym konkretnym punkcie.

Jak miałbym spłaszczać teren pod obiektem gry, aby nie wchodził w teren ani nie spędzał czasu w powietrzu w przypadku wzgórz?

Rapida
źródło
3
Znajdź wszystkie wierzchołki, które tworzą trójkąty terenu pod obiektem gry. Ustaw współrzędną y wszystkich tych wierzchołków tak samo.
MichaelHouse

Odpowiedzi:

6

Jak powiedziałem w moim komentarzu, będziesz chciał znaleźć wszystkie wierzchołki tworzące trójkąty pod twoim obiektem gry i ustawić ich wartość y na tę samą wartość.

Rozszerzę swój komentarz o bardziej szczegółowe kroki. Nie znam się zbytnio na Unity, więc nie znam najlepszych narzędzi do pracy, ale wierzę, że mogę zacząć od właściwej ścieżki.

Metoda brutalnej siły:

  1. Rzuć siatkę promieni prosto z twojego obiektu gry. Siatka powinna być wystarczająco ciasna, aby zapewnić, że nie ominie żadnych trójkątów na powierzchni terenu.
  2. Dla każdego promienia, który trafi w coś, możesz uzyskać trójkąt w siatce terenu w następujący sposób:

    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 i p2 to wszystkie pozycje trzech wierzchołków, które tworzą trafiony trójkąt. Chcesz dopasować każdą z tych pozycji wierzchołków, aby miała tę samą ywartość. Możesz albo zebrać wszystkie wierzchołki, a następnie ustawić je na średnią ywartość, lub możesz użyć początkowej wybranej ywartości znalezionej podczas umieszczania obiektu gry.

Optymalizacje:

  • Zamiast po prostu rzucać siatkę promieni, możesz zmiatać zderzacz z obiektu gry i zbierać punkty kontaktowe kolizji między zderzaczem obiektu gry a siatką kolizji terenu. Następnie dla każdego z tych punktów kontaktowych wykonaj powyższe kroki, aby uzyskać wierzchołki, które chcesz przesunąć.

  • Utwórz swój teren w taki sposób, aby każdy wierzchołek xi zwartości były wyrównane do siatki i różniły się tylko ich ywartością. Teraz możesz łatwo uzyskać granice obiektu gry i zmienić wszystkie wartości y wierzchołków w tych granicach.

Ta ostatnia optymalizacja jest tak naprawdę alternatywną metodą, która prawdopodobnie byłaby łatwa do wdrożenia i dość skuteczna.

MichaelHouse
źródło
Z tego co mogę powiedzieć, że obiekt ( docs.unity3d.com/Documentation/ScriptReference/Terrain.html ) ma obiekt TerrainCollider ( docs.unity3d.com/Documentation/ScriptReference/... ), a nie MeshCollider ( docs.unity3d.com/Documentation / ScriptReference /… ), więc brakuje w nim właściwości sharedMesh, której próbujesz użyć w kroku 2. Zakładałem, że potrzebuję pewnego rodzaju logiki, aby zmodyfikować mapę wysokości przechowywaną przez właściwość terrainData.
Rapida
Możesz sprawdzić tutaj: forum.unity3d.com/threads/... Wygląda na to, że obiekt terenu ma regularną siatkę, więc druga optymalizacja może być najlepszym wyborem.
MichaelHouse
1

Zazwyczaj chce, aby ziemia pod obiektem była płaska, a ziemia wokół niej wygładzona.

Jeśli grunt jest wykonany z siatki, a budynek jest ustawiony w linii osi, jest to o wiele łatwiejsze.

W ogólnym przypadku dzielisz trójkąty, na których znajduje się budynek, a następnie ustawiasz y wszystkich wierzchołków trójkątów, na których stoi budynek, na to samo y , a następnie wygładzasz przesunięcie punktu środkowego dla wszystkich wierzchołków w pewnej odległości, które są nie sami pod budynkiem.

Wykorzystałem to podejście do umieszczania dróg w terenie 3D.

Zazwyczaj chcesz wymusić minimalne odstępy między budynkami, aby mieć wystarczająco dużo gruntów do wygładzenia. Lub możesz tymczasowo uruchomić algorytm przed umieszczeniem i sprawdzić, czy jakiś próg stromości został przekroczony, a więc sprawdzić, gdzie użytkownik może umieścić budynki.

Będzie
źródło