Procedural Generation

Overview

Procedural Generating a mesh from code.

The video talks and shows you how to create a simple wall just by using code.

We build up the wall, polygon by polygon and, apply UV to define how the textures are used.



Files

CreateMesh.cs
using UnityEngine;

namespace eWolf.CodeExamples.ProceduralGeneration
{
    public class CreateMesh : MonoBehaviour
    {
        public Material material;
        private MeshBuilder _meshBuilder = new MeshBuilder();

        public void BuildMesh()
        {
            _meshBuilder = new MeshBuilder();
            UVSet uvSet = new UVSet(1, 1);

            float size = 1f;
            float width = 0.1f;

            Vector3 xy = new Vector3(0, 0, 0);
            Vector3 xytop = xy + Vector3.up * size;
            Vector3 xyFar = xy + Vector3.forward * size;
            Vector3 xytopFar = xytop + Vector3.forward * size;
            _meshBuilder.BuildQuad(xy, xyFar, xytop, xytopFar, uvSet);

            xy = new Vector3(width, 0, 0);
            xytop = xy + Vector3.up * size;
            xyFar = xy + Vector3.forward * size;
            xytopFar = xytop + Vector3.forward * size;
            _meshBuilder.BuildQuad(xytop, xytopFar, xy, xyFar, uvSet);

            UVSet uvSetEnd = new UVSet(width, 1);
            xy = new Vector3(0, 0, 0);
            xytop = xy + Vector3.up * size;
            xyFar = xy + Vector3.right * width;
            xytopFar = xytop + Vector3.right * width;
            _meshBuilder.BuildQuad(xytop, xytopFar, xy, xyFar, uvSetEnd);


            _meshBuilder.ApplyMeshDetails(gameObject, material);
        }

        public void ClearMesh()
        {
            _meshBuilder = new MeshBuilder();
            _meshBuilder.ApplyMeshDetails(gameObject, material);
        }
    }
}


MeshBuilder.cs
using System;
using System.Collections.Generic;
using UnityEngine;

namespace eWolf.CodeExamples.ProceduralGeneration
{
    public class MeshBuilder
    {
        private List MeshUVs { get; set; } = new List();
        private List MeshVertices { get; set; } = new List();
        private List Triangles { get; set; } = new List();

        public void ApplyMeshDetails(GameObject baseobject, Material material)
        {
            Mesh mesh = new Mesh
            {
                name = $"MyMesh {DateTime.Now.ToShortDateString()}"
            };
            baseobject.GetComponent().mesh = mesh;

            mesh.vertices = MeshVertices.ToArray();
            mesh.uv = MeshUVs.ToArray();

            Renderer r = baseobject.GetComponent();
            r.sharedMaterial = material;

            mesh.SetTriangles(Triangles.ToArray(), 0);

            mesh.subMeshCount = 1;

            mesh.RecalculateNormals();
            mesh.RecalculateBounds();
        }

        public void BuildQuad(Vector3 a, Vector3 b, Vector3 c, Vector3 d, UVSet uvset)
        {
            int indexA = AddVectorUVSets(a, uvset.BR);
            int indexB = AddVectorUVSets(b, uvset.TR);
            int indexC = AddVectorUVSets(c, uvset.BL);
            int indexD = AddVectorUVSets(d, uvset.TL);

            Triangles.AddRange(new int[] { indexA, indexB, indexC });
            Triangles.AddRange(new int[] { indexD, indexC, indexB });
        }

        private int AddVectorUVSets(Vector3 points, Vector2 uvs)
        {
            MeshVertices.Add(points);
            MeshUVs.Add(uvs);
            return MeshVertices.Count - 1;
        }
    }
}


UVSet.cs
using UnityEngine;

namespace eWolf.CodeExamples.ProceduralGeneration
{
    public class UVSet
    {
        ///
        /// The Bottom left position
        ///

        public Vector2 BL;

        ///
        /// The bottom right postion
        ///

        public Vector2 BR;

        ///
        /// The top left position
        ///

        public Vector2 TL;

        ///
        /// The top right position
        ///

        public Vector2 TR;

        ///
        /// The Standard constructor
        ///

        /// The top left UV
        /// The top right UV
        /// The bottom left uv
        /// The bottom right uv
        public UVSet(Vector2 topLeft, Vector2 topRight, Vector2 botLeft, Vector3 botRight)
        {
            TL = topLeft;
            TR = topRight;
            BL = botLeft;
            BR = botRight;
        }

        ///
        /// The Standard constructor
        ///

        public UVSet()
        {
        }

        ///
        /// The Standard constructor
        ///

        /// The X position
        /// The Y position
        public UVSet(float x, float y)
        {
            TL = new Vector2(0, 0);
            TR = new Vector2(0, y);
            BL = new Vector2(x, 0);
            BR = new Vector2(x, y);
        }
    }
}