Unity, the Terrain and me, Part 2

After having the basics for this, see part 1, I created a plane and subdivided it a few times in Blender to have enough vertices in the mesh. I probably could use ProBuilder and do the subdivide there, but I try it first this way.

I imported the mesh as fbx into Unity3D and scaled it and moved it over the terrain. Now I want that every vertics of the mesh has the same y-axis height than the terrain at its x/z position.

Since I want to change vertices in the mesh, I have to set it to Read/Write Enabled in its importing settings on the model file.

First thing is to get the mesh data. But, and here I stucked last time I was trying this, the imported plane mesh asset only has a MeshFilter. What is a MeshFilter ?

„The Mesh Filter takes a mesh from your assets and passes it to the Mesh Renderer for rendering on the screen.“ (Unity3D – Documentation)

Since it is an instance, I am still not sure if I can change it at all. This is a basic flaw in my understanding of Unity3D. Please be patient with me here. 😀

But after reading the documentation, I noticed that last time I was trying this, I did it in editor mode. And there you are advised to use the sharedMesh field of the MeshFilter. And using that, you actually change the asset itself ! Unity3D clearly states, that you should not use sharedMesh for changing the mesh verticies.

If you use the mesh field of MeshFilter durching Run-Time, it creates a duplicate and every time you use mesh, this duplicate is returned. Also sharedMesh then points to this duplicate. So I will do that then. Here I only use one mesh, but for the planed used this is important, since there I will change a lot of instances of the same mesh.

And actually, this worked on the spot :

  MeshFilter meshFilter;
    Mesh mesh;

    meshFilter = terrainCoveringMesh.GetComponent<MeshFilter>();
    mesh = meshFilter.mesh;

    Vector3[] verts = mesh.vertices;

    Debug.Log("Found " + verts.Length + " Vertices for Tile " + terrainCoveringMesh.name);


    for (int i = 0; i < verts.Length; i++)
    {

        Vector3 vertPos = terrainCoveringMesh.transform.TransformPoint(verts[i]);

        Vector3 pos = vertPos;
        pos.y = Terrain.activeTerrain.SampleHeight(vertPos);

        vertPos.y = pos.y;

        Vector3 backToLocal = terrainCoveringMesh.transform.InverseTransformPoint(vertPos);

        verts[i] = backToLocal;

    }

    mesh.vertices = verts;

    meshFilter.sharedMesh = mesh;

    meshFilter.sharedMesh.RecalculateBounds();
    meshFilter.sharedMesh.RecalculateNormals();
I made the covering mesh smaller so you can see the underlaying structure.

Important here is that you convert the vertices position from local space to world space and then back to localspace, using the transform of the mesh you want to lay over the terrain.

So this is done. Now how to get this working in Editor Mode is another question and the final problem.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.