Creating a mesh.

A 3D object is created using a mesh that consists of vertices and triangles. A vertex is a point whose position is represented by axes x, y, and z. With such simple primitives as vertices and triangles, it is possible to create complex 3D objects like animals, terrain, streets, etc. The next figure shows a cube and its vertices numbered from 0 to 7. Numbering can start from any vertex and can be done in any direction.

cube-vertices

Mesh vertices are stored in an array of Vector3 objects like in the next code snippet, in this example cube edge lenght is equal to one.

var vertices = new[]
{
     new Vector3 (0, 0, 0), // vertex 0
     new Vector3 (1, 0, 0), // vertex 1
     new Vector3 (1, 1, 0), // vertex 2
     new Vector3 (0, 1, 0), // vertex 3
     new Vector3 (0, 1, 1), // vertex 4
     new Vector3 (1, 1, 1), // vertex 5
     new Vector3 (1, 0, 1), // vertex 6
     new Vector3 (0, 0, 1), // vertex 7
};

A cube has 6 square faces and if every face is split diagonally into 2 parts, then a cube can be represented by 12 triangles. Triangles are stored in a separate integer array, every item keeps an index from the previously created vertices array. Each series of 3 vertices represents one triangle. Triangle vertices are numbered in a clockwise direction, the next figure shows how to define the first 4 triangles.

first cube triangles
Defining all triangles can look like in the next code snippet.
var triangles = new[]
{
     0, 2, 1, 
     0, 3, 2,
     2, 3, 4, 
     2, 4, 5,
     1, 2, 5, 
     1, 5, 6,
     0, 7, 4, 
     0, 4, 3,
     5, 4, 7, 
     5, 7, 6,
     0, 6, 7, 
     0, 1, 6
};

The last mesh component is an array of normals. A normal is a vector perpendicular to the mesh and it is used by the Unity engine for shading calculation. If both, light direction and the normal are perpendicular to a surface then the surface will be displayed at maximum brightness. Normals are assigned to vertices and not to triangles. Unity has a method called RecalculateNormals() that will generate normals based on vertices and triangles previously created.

The final step is assigning vertices and triangles to the mesh and calling the normals recalculation function:

// get GameObject mesh
Mesh mesh = GetComponent().mesh;
mesh.Clear();
// assign vertices and triangles to the mesh
mesh.vertices = vertices;
mesh.triangles = triangles;
mesh.RecalculateNormals();

Putting all together.

Open Unity editor and create an empty game object, add a MeshFilter and a MeshRenderer components to it. And finally add a script component containing code for mesh creation:

using UnityEngine;

[RequireComponent(typeof(MeshFilter))]
[RequireComponent(typeof(MeshRenderer))]
public class CubeFromMesh: MonoBehaviour
{
    Vector3[] vertices;
    int[] triangles;

    void Start()
    {
        vertices = new[]
        {
            new Vector3 (0, 0, 0), // vertices 0
            new Vector3 (1, 0, 0), // vertices 1
            new Vector3 (1, 1, 0), // vertices 2
            new Vector3 (0, 1, 0), // vertices 3
            new Vector3 (0, 1, 1), // vertices 4
            new Vector3 (1, 1, 1), // vertices 5
            new Vector3 (1, 0, 1), // vertices 6
            new Vector3 (0, 0, 1), // vertices 7
        };

        triangles = new[]
        {
            0, 2, 1,
            0, 3, 2,
            2, 3, 4,
            2, 4, 5,
            1, 2, 5,
            1, 5, 6,
            0, 7, 4,
            0, 4, 3,
            5, 4, 7,
            5, 7, 6,
            0, 6, 7,
            0, 1, 6
        };

        Mesh mesh = GetComponent().mesh;
        mesh.Clear();
        mesh.vertices = vertices;
        mesh.triangles = triangles;
        mesh.RecalculateNormals();
    }

    void Update() { }
}
Play the scene and notice that the cube faces are displayed improperly, the cube looks like made from metal.
cube wrong normals shading

Cube with 24 vertices.

In our case the same vertices were used multiple times to create different triangular faces, hence the Unity engine cannot correctly calculate the normals of the triangles. To display the cube correctly, it is necessary to create it again, but this time with a unique vertex for every triangle face, as a result, the number of vertices will increase from 8 to 24 like in the next figure.

cube 24 vertices
Next code shows a new way of creating a cube.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[RequireComponent(typeof(MeshFilter))]
[RequireComponent(typeof(MeshRenderer))]
public class CubeFromMesh: MonoBehaviour
{
    Vector3[] vertices;
    int[] triangles;

    // Start is called before the first frame update
    void Start()
    {
        var v = new[]
        {
            new Vector3 (0, 0, 0), // vertices 0
            new Vector3 (1, 0, 0), // vertices 1
            new Vector3 (1, 1, 0), // vertices 2
            new Vector3 (0, 1, 0), // vertices 3
            new Vector3 (0, 1, 1), // vertices 4
            new Vector3 (1, 1, 1), // vertices 5
            new Vector3 (1, 0, 1), // vertices 6
            new Vector3 (0, 0, 1), // vertices 7
        };

        vertices = new Vector3[]
        {
            v[0], v[3], v[2], v[1],   // front:   from 0 to 3
	    v[2], v[3], v[4], v[5],   // top:     from 4 to 7
	    v[7], v[4], v[3], v[0],   // left:    from 8 to 11
	    v[1], v[2], v[5], v[6],   // right:   from 12 to 15
	    v[5], v[4], v[7], v[6],   // back:    from 16 to 19
	    v[6], v[7], v[0], v[1]    // bottom:  from 20 to 23
        };

        triangles = new int[]
        {
            0, 1, 2,        0, 2, 3,       // front	
	    4, 5, 6,        4, 6, 7,       // top
	    8, 9, 10,       8, 10, 11,     // left
	    12, 13, 14,     12, 14, 15,    // right
	    16, 17, 18,     16, 18, 19,    // back
	    20, 21, 22,     20, 22, 23,    // bottom
        };

        Mesh mesh = GetComponent().mesh;
        mesh.Clear();
        mesh.vertices = vertices;
        mesh.triangles = triangles;
        mesh.Optimize();
        mesh.RecalculateNormals();
    }

     void Update() {}
}
Play the scene again using new script and notice that this time the cube faces are correctly shaded, the next figure shows two cubes and only the one from the right side is correctly displayed.
cube with normals