Proceduralne generowanie siatki w Unity #02 Bryła 3D i kolizje


Hej, witajcie w drugiej części serii postów poświęconych generowaniu siatki w Unity. W tym poście stworzymy trójwymiarową bryłę oraz zajmiemy się stworzeniem mesh collidera, a więc nasz obiekt będzie mógł oddziałować fizycznie na świat!



Poprzednia nudna siatka

Pamiętacie poprzednią siatkę którą stworzyliśmy? Nie ciekawy, dwuwymiarowy obiekt. Dzisiaj stworzymy coś znacznie ciekawszego, mianowicie trochę brył platońskich. No może nie trochę, a jedną ☺. Bowiem sam Platon mawiał: "Trójkąty są najprostszym elementem budulcowym, podstawową cegiełką, z której zbudowany jest Kosmos". Zaskakująco dobrze pasuje to do naszego przypadku. Trójkąty czyli poligony są podstawowym budulcem naszych obiektów!

W poprzednim poście poprosiłem czytelników by sami rozgryźli dlaczego raz poligon zwrócony jest w jedną stronę, a raz w drugą. Tutaj wytłumaczę o co chodzi.
rys.01

Jeżeli chcemy by tworzony poligon był widoczny z naszej strony, musimy dodać punkty składające się na poligon wedle wskazówek zegara. (rys.01)
I tak jak na dołączonym obrazku, jeżeli chcemy by nasz poligon był zwrócony w naszą stronę, musimy poszczególne punkty dodawać według wskazówek zegara, czyli po kolei: wpierw punkt o ID 1, potem 0 i na końcu 2. Równie dobrze mogło by być wpierw 0, potem 2 i na końcu 1. Chodzi tu bardziej o samą zasadę.

Kiedy to mamy już wytłumaczone, zabierzmy się do pracy.

rys.02
Na sam początek dobrym pomysłem będzie stworzenie sześcianu. (Taka bryła jak na drugim rysunku)
rys.03

Sześcian, jak widać to na rysunku trzecim, składa się z 8 punktów. Stwórzmy zatem tablice 8 elementową zawierającą punkty, oraz tablice o rozmiarze 36 przechowującą informacje o poligonach. (36 ponieważ: 6 ścian * 2 poligony * 3 punkty)
  Vector3[] verticles = new Vector3[8];
        verticles[0] = new Vector3(0, 0, 0);
        verticles[1] = new Vector3(1, 0, 0);
        verticles[2] = new Vector3(1, 1, 0);
        verticles[3] = new Vector3(0, 1, 0);
        verticles[4] = new Vector3(0, 0, 1);
        verticles[5] = new Vector3(1, 0, 1);
        verticles[6] = new Vector3(1, 1, 1);
        verticles[7] = new Vector3(0, 1, 1);  

Utwórzmy teraz poligony.
 int[] triangles = new int[36];

        //Przednia ściana
        triangles[0] = 2;
        triangles[1] = 1;
        triangles[2] = 0;
        triangles[3] = 0;
        triangles[4] = 3;
        triangles[5] = 2;

        //Tylnia ściana
        triangles[6] = 4;
        triangles[7] = 5;
        triangles[8] = 6;
        triangles[9] = 6;
        triangles[10] = 7;
        triangles[11] = 4;

        //Lewa ściana
        triangles[12] = 0;
        triangles[13] = 4;
        triangles[14] = 7;
        triangles[15] = 7;
        triangles[16] = 3;
        triangles[17] = 0;

        //Prawa ściana
        triangles[18] = 6;
        triangles[19] = 5;
        triangles[20] = 1;
        triangles[21] = 1;
        triangles[22] = 2;
        triangles[23] = 6;

        //Górna ściana
        triangles[24] = 2;
        triangles[25] = 3;
        triangles[26] = 7;
        triangles[27] = 7;
        triangles[28] = 6;
        triangles[29] = 2;

        //Dolna ściana
        triangles[30] = 5;
        triangles[31] = 4;
        triangles[32] = 0;
        triangles[33] = 0;
        triangles[34] = 1;
        triangles[35] = 5;  
Dodałem komentarze po to, by ładniej było widać która część kodu odpowiada za którą ścianę.
Punktem odniesiania jest pierwsza "przednia ściana".

Tak prezentuje się nasza figura na scenie:


Prawda że wygląda pięknie? ☺
Teraz czas na wisienkę na torcie - kolizje.
Aby sprawić by figura reagowała fizycznie z otoczeniem, musi mieć collider. W naszym przypadku posłużymy się MeshColliderem. Dodajmy go zatem do wymaganych komponentów i uzyskamy do niego dostęp w kodzie.
I teraz cała magia, dodajmy do niego siatkę naszego obiektu. Dodatkowo przypiszmy polu convex wartość true. (Na razie nie będę wyjaśniał czemu, tak ma być i koniec 😈)
sharedMesh = meshToCollider;
meshCollider.convex = true; 

I to wszystko. Teraz wystarczy dodać komponent RigidBody i możemy cieszyć się efektami naszej pracy ☺
Dodajmy jeszcze jakąś powierzchnie i możemy cieszyć się naszym sześcianem fizycznie reagującym z otoczeniem ☺

Tak prezentuje się cały kod:
 using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[RequireComponent(typeof(MeshRenderer))]
[RequireComponent(typeof(MeshFilter))]
[RequireComponent(typeof(MeshCollider))]
[RequireComponent(typeof(Rigidbody))]

public class Szescian : MonoBehaviour {

    MeshRenderer meshRenderer;
    MeshFilter meshFilter;
    MeshCollider meshCollider;
    Mesh mesh;

    // Use this for initialization
    void Start()
    {
        meshRenderer = gameObject.GetComponent();
        meshFilter = gameObject.GetComponent();
        meshCollider = gameObject.GetComponent();
        mesh = new Mesh();

        Vector3[] verticles = new Vector3[8];
        verticles[0] = new Vector3(0, 0, 0);
        verticles[1] = new Vector3(1, 0, 0);
        verticles[2] = new Vector3(1, 1, 0);
        verticles[3] = new Vector3(0, 1, 0);
        verticles[4] = new Vector3(0, 0, 1);
        verticles[5] = new Vector3(1, 0, 1);
        verticles[6] = new Vector3(1, 1, 1);
        verticles[7] = new Vector3(0, 1, 1);

        int[] triangles = new int[36];

        //Przednia ściana
        triangles[0] = 2;
        triangles[1] = 1;
        triangles[2] = 0;
        triangles[3] = 0;
        triangles[4] = 3;
        triangles[5] = 2;

        //Tylnia ściana
        triangles[6] = 4;
        triangles[7] = 5;
        triangles[8] = 6;
        triangles[9] = 6;
        triangles[10] = 7;
        triangles[11] = 4;

        //Lewa ściana
        triangles[12] = 0;
        triangles[13] = 4;
        triangles[14] = 7;
        triangles[15] = 7;
        triangles[16] = 3;
        triangles[17] = 0;

        //Prawa ściana
        triangles[18] = 6;
        triangles[19] = 5;
        triangles[20] = 1;
        triangles[21] = 1;
        triangles[22] = 2;
        triangles[23] = 6;

        //Górna ściana
        triangles[24] = 2;
        triangles[25] = 3;
        triangles[26] = 7;
        triangles[27] = 7;
        triangles[28] = 6;
        triangles[29] = 2;

        //Dolna ściana
        triangles[30] = 5;
        triangles[31] = 4;
        triangles[32] = 0;
        triangles[33] = 0;
        triangles[34] = 1;
        triangles[35] = 5;


        mesh.vertices = verticles;
        mesh.triangles = triangles;
        meshFilter.mesh = mesh;

        meshCollider.sharedMesh = mesh;
        meshCollider.convex = true;
    }
}


Kamil Roszak

Tu miał być mój opis, ale prawdopodobnie nie chciało mi się go napisać :)

2 komentarze: