Creating an object from scratch

I need help creating a gameobject from scratch, i have this code so far:

    public void GenerateLevel()
    {
        foreach (Vector3 gridPoint in levelGrid)
        {
            GameObject tileObject = new GameObject();
            tileObject.AddComponent<MeshFilter>();

            Mesh mesh = new Mesh();

            //Create vertex one.
            Vector3 vertexOne = new Vector3(0, 1, 0);
            newVertices[1] = vertexOne;
            //Create vertex two.
            Vector3 vertexTwo = new Vector3(-1, 0.5f, 0);
            newVertices[2] = vertexTwo;
            //Create vertex three.
            Vector3 vertexThree = new Vector3(1, 0.5f, 0);
            newVertices[3] = vertexThree;
            //Create vertex four.
            Vector3 vertexFour = new Vector3(-1, -0.5f, 0);
            newVertices[4] = vertexFour;
            //Create vertex five.
            Vector3 vertexFive = new Vector3(1, -0.5f, 0);
            newVertices[5] = vertexFive;
            //Create vertex six.
            Vector3 vertexSix = new Vector3(0, -1, 0);
            newVertices[6] = vertexSix;

            int[] newTriangles =
            {
                1, 2, 3,
                2, 3, 4,
                3, 4, 5,
                4, 5, 6
            };

            mesh.vertices = newVertices;
            mesh.triangles = newTriangles;

            tileObject.GetComponent<MeshFilter>().mesh = mesh;
        }
    }
}

but it creates errors when manually trying to assign vertices.

Arrays are zero-indexed. You start from 0, not 1.

–Eric

Welcome to the exciting world of procedural geometry generation! Poster @Eric5h5 above is correct, arrays are zero-based.

I also recommend you check out a class in the UnityEngine.UI namespace called VertexHelper:

https://docs.unity3d.com/ScriptReference/UI.VertexHelper.html

It gives you some help as far as assembling meshes from scratch.

There are plenty of other resources out there too, so just google around for procedural mesh generation. There’s a million completely different ways to go about it, and most of them are not immediately interchangeable with each other, but you can learn something from everybody’s approach for sure.

I tried that at first, I understand that already. I tried starting at 1 when starting at 0 did not work, forgot to change it back for the example here, haha.

anyway instead of indexing them one at a time I tried doing it the same way I made the triangles, that worked correctly. Now I am having a problem getting my uvs to work correctly, there should be 4 uv triangles or whatever you call em. anyway 2 of them are facing one way teh other two facing the other, I need help getting them all to face one way.

    public void GenerateLevel()
    {
        foreach (Vector3 gridPoint in levelGrid)
        {
            GameObject tileObject = new GameObject();

            tileObject.transform.position = gridPoint;

            tileObject.AddComponent<MeshFilter>();

            Mesh mesh = new Mesh();

            Vector3 vertexOne = new Vector3(0, 1, 0);
            Vector3 vertexTwo = new Vector3(-1, 0.5f, 0);
            Vector3 vertexThree = new Vector3(1, 0.5f, 0);
            Vector3 vertexFour = new Vector3(-1, -0.5f, 0);
            Vector3 vertexFive = new Vector3(1, -0.5f, 0);
            Vector3 vertexSix = new Vector3(0, -1, 0);

            Vector3[] newVertices =
            {
                vertexOne,
                vertexTwo,
                vertexThree,
                vertexFour,
                vertexFive,
                vertexSix
            };

            int[] newTriangles =
            {
                0, 1, 2,
                1, 2, 3,
                2, 3, 4,
                3, 4, 5
            };

            mesh.vertices = newVertices;
            mesh.triangles = newTriangles;

            Vector2[] uvs = new Vector2[newVertices.Length];

            for (int i = 0; i < uvs.Length; i++)
            {
                uvs[i] = new Vector2(newVertices[i].x, newVertices[i].y);
            }

            mesh.uv = uvs;

            tileObject.GetComponent<MeshFilter>().mesh = mesh;

            tileObject.AddComponent<MeshRenderer>();
        }
    }

never mind it was not the uvs that were screwing up it was teh way I was assigning triangles, i reverse teh order of a few of them and it is working correctly now. thanks for the help everyone.

Here’s the science, er, math…:

Oh thanks for that, I dont know how I figured it out exactly but I just sort of messed around and got it right. It is nice to know why though so thanks for sharing that.

currently I cannot figure out how to add normals or uvs properly

I have assigned a material to the object and it is all black, I assume it is because I need to soemhow add proper UVs and normals but I dont know how to do that. any help would be appreciated.

using UnityEngine;
using System.Collections.Generic;

public class LevelGrid : MonoBehaviour
{
    public Transform parent;

    public Camera playerCamera;
    public Vector2 playerPosition;

    public int levelWidth = 256;
    public int levelHeight = 128;

    public Material tileMaterial;

    [HideInInspector]
    public List<Vector3> levelGrid;
    [HideInInspector]
    public List<GameObject> tileGrid;

    void Start()
    {
        GenerateLevelgrid();
        GenerateLevel();
    }

    public void GenerateLevelgrid()
    {
        for (int x = 0; x <= levelWidth; x = x + 2)
        {
            for (int y = 0; y <= levelHeight; y = y + 2)
            {
                Vector3 gridPoint = new Vector3(x, y, 0);
                levelGrid.Add(gridPoint);
            }
        }
    }

    public void GenerateLevel()
    {
        foreach (Vector3 gridPoint in levelGrid)
        {
            if (new Vector2(gridPoint.x, gridPoint.y) != playerPosition)
            {
                GameObject tileObject = new GameObject();

                tileObject.transform.name = ("Tile(" + gridPoint.x + ", " + gridPoint.y + ")");
                tileObject.transform.parent = parent;
                tileObject.transform.position = gridPoint;

                tileGrid.Add(tileObject);

                tileObject.AddComponent<MeshFilter>();
                tileObject.AddComponent<MeshRenderer>();
                tileObject.AddComponent<TileGrid>();

                Mesh mesh = new Mesh();

                Vector3 vertexOne = new Vector3(0, 1, 0);
                Vector3 vertexTwo = new Vector3(-1, 0.5f, 0);
                Vector3 vertexThree = new Vector3(1, 0.5f, 0);
                Vector3 vertexFour = new Vector3(-1, -0.5f, 0);
                Vector3 vertexFive = new Vector3(1, -0.5f, 0);
                Vector3 vertexSix = new Vector3(0, -1, 0);

                Vector3[] newVertices =
                {
                    vertexOne,
                    vertexTwo,
                    vertexThree,
                    vertexFour,
                    vertexFive,
                    vertexSix
                };

                mesh.vertices = newVertices;

                int[] newTriangles =
                {
                    2, 1, 0,
                    1, 2, 3,
                    4, 3, 2,
                    3, 4, 5
                };

                mesh.triangles = newTriangles;

                mesh.RecalculateNormals();

                tileObject.GetComponent<MeshFilter>().mesh = mesh;
                tileObject.GetComponent<MeshRenderer>().material = tileMaterial;
                tileObject.GetComponent<TileGrid>().gridPosition = new Vector2(gridPoint.x, gridPoint.y);
            }
            else
            {
                playerCamera.transform.position = gridPoint;
            }
        }
    }
}

Every vertex has a corresponding normal (Vector3) and a corresponding uv (Vector2). You add these to the mesh the same way you add the array of vertices: as a full array.

I usually cheat and call RecalculateNormals() on my mesh.

https://docs.unity3d.com/ScriptReference/Mesh.RecalculateNormals.html

UVs are a bit trickier. It is analogous to “how many ways can you cut up a piece of paper and wrap it around an object?”

The answer is an infinite number of ways. You can try simple mappings such as world x goes to u and world y goes to v, and you can see how that affects your texturing. Or you can individual give each triangle the same corners of UV space, such as (0,0), (1,0) and (0.1) for instance. But each way you do is going to give different results. Try it and see.

You also want to call RecalculateBounds on your mesh after making it or else the camera may clip you out of existence when in fact your geometry is visible.

Thanks that helped a bit, now that I finally got the texture in the game i was actually able to play around with it, before it was just a blank material with a color assigned. Setting UV was easy once I really sat down and focused on just that. I got my desired effect and it looks amazing couldnt be happier with the results. thanks for the help guys.

1 Like