- Home /
 
How to have different materials on one GameObject?
Hi there,
first: I'm totally new to Unity3D, but not neccessary to game development.
I'm following this tutorial series to get into Unity.
So far I've understand everything - currently at episode 12 - but it seems this tutorial will only use a single material.
The tutorial creates some kind of minecraft clone.
It uses chunks to generate a theoretical infinite world. One chunk has a width and a height.
The whole world is created from one Unity GameObject with a script.
The script does the following (simplified):
 map[,,] = createChunk(); // create a terrain with noise function, not a big deal
 StartCoroutine (CreateVisualMesh ());
 CreateVisualMesh ();
 
 public virtual IEnumerator CreateVisualMesh ()
     {
         visualMesh = new Mesh ();
         
         List<Vector3> verts = new List<Vector3> ();
         List<Vector2> uvs = new List<Vector2> ();
         List<int> tris = new List<int> ();
         
         
         for (int x = 0; x < width; x++) {
             for (int y = 0; y < height; y++) {
                 for (int z = 0; z < width; z++) {
                     if (map [x, y, z] == 0)
                         continue;
                     
                     byte brick = map [x, y, z];
                     // Left walls
                           BuildFace (brick, new Vector3 (x, y, z), Vector3.up, Vector3.forward, false, verts, uvs, tris);
                     // Right wall
                                  BuildFace (brick, new Vector3 (x + 1, y, z), Vector3.up, Vector3.forward, true, verts, uvs, tris);
                     
                     // Bottom wall
                     BuildFace (brick, new Vector3 (x, y, z), Vector3.forward, Vector3.right, false, verts, uvs, tris);
                     // Top wall
                     BuildFace (brick, new Vector3 (x, y + 1, z), Vector3.forward, Vector3.right, true, verts, uvs, tris);
                     
                     // Back
                     BuildFace (brick, new Vector3 (x, y, z), Vector3.up, Vector3.right, true, verts, uvs, tris);
                     // Front
                     BuildFace (brick, new Vector3 (x, y, z + 1), Vector3.up, Vector3.right, false, verts, uvs, tris);                    
                 }
             }
         }
 //        renderer.material.color = new Color (1, 0, 0);
         visualMesh.vertices = verts.ToArray ();
         visualMesh.uv = uvs.ToArray ();
         visualMesh.triangles = tris.ToArray ();
         visualMesh.RecalculateBounds ();
         visualMesh.RecalculateNormals ();
         visualMesh.Optimize ();
         meshFilter.mesh = visualMesh;
         meshCollider.sharedMesh = null;
         meshCollider.sharedMesh = visualMesh;
         
         yield return 0;        
     }
    
 
 
     public virtual void BuildFace (byte brick, Vector3 corner, Vector3 up, Vector3 right, bool reversed, List<Vector3> verts, List<Vector2> uvs, List<int> tris)
     {
         int index = verts.Count;
         
         verts.Add (corner);
         verts.Add (corner + up);
         verts.Add (corner + up + right);
         verts.Add (corner + right);
 
         Vector2 uvWidth = new Vector2 (0.25f, 0.25f);
         Vector2 uvCorner = new Vector2 (0.00f, 0.75f);
 
         uvs.Add (uvCorner);
         uvs.Add (new Vector2 (uvCorner.x, uvCorner.y + uvWidth.y));
         uvs.Add (new Vector2 (uvCorner.x + uvWidth.x, uvCorner.y + uvWidth.y));
         uvs.Add (new Vector2 (uvCorner.x + uvWidth.x, uvCorner.y));
         
         if (reversed) {
             tris.Add (index + 0);
             tris.Add (index + 1);
             tris.Add (index + 2);
             tris.Add (index + 2);
             tris.Add (index + 3);
             tris.Add (index + 0);
         } else {
             tris.Add (index + 1);
             tris.Add (index + 0);
             tris.Add (index + 2);
             tris.Add (index + 3);
             tris.Add (index + 2);
             tris.Add (index + 0);
         }
     }
 
               So my actual question is: How can I use different Materials (Textures) for single faces? Actually a couple of faces, one cube.
Since I am not sure if it is okay to post the link of the source code: The source code of this tutorial is attached for every episode below the actual YouTube video. Episode 5 introduces materials.
I've tried to set the color of the MeshRenderer - but obviously this colored the whole chunk in a color.
I don't need any code as answer (well, I wouldn't be mad if you post some.. ) but some keyword or topics I've to check.
Answer by robertbu · Jul 30, 2014 at 05:45 PM
This problem is almost always solved by using a texture atlas and setting the uv values in the mesh to map to different places in the atlas. Here is a question that shows it being done for a built-in cube:
http://answers.unity3d.com/questions/542787/change-texture-of-cube-sides.html
You'll need to educate yourself on uv coordinates and how they map to a texture. Just to be clear, you are not changing the material. By setting the uvs, you are setting what part of a large texture maps to a particular side.
Thanks for your answer. Well I understand this technique basically so far and this makes absolutely sense.
But would it even be possible to use different materials for a voxel/face?
Let's imagine I want to have different shaders, material colors, whatever on a single face. I think this wouldn't be possible using a single material, right?
Yes it is possible. Look up submeshes (in a mesh) and the $$anonymous$$aterial.materials[] array. Each submesh gets assigned a material from the materials array. But there can be significant performance implications with using the materials array. As long as you only use a single material, the entire mesh will draw in a single draw call.
Your answer