- Home /
UV mapping
Hello guys.
I am making a game similar to minecrafts graphic style. I only work as a programmer, so I am a total noob when it comes to 3D models. So for example: I have a grass block where the sides are going to be the same, but the top and bottom have different textures. So I was wondering if I could UV map the standard cube in Unity from within my script.
Thanks a lot.
It would be ten times easier with a free modelling software like Blender. Just download it, create a cube and look for any uv mapping tutorial.
@Sarper Soher You can't do that, because different blocks need different textures, and you can't have one texture per block because they all need to combine into a single mesh in each chunk.
@Sarper Soher No, if you are making $$anonymous$$inecraft-style graphics each cube needs to have only certain faces rendered, and each face a different texture. So no, you can't create anything in blender for this because voxels are never actually cubes. Voxels are hypothetical cubes that are rendered completely in code. I am working on a voxel engine too (although it will be smooth, eventually), and if you made each block an actual block, you would destroy your computer's GPU. A voxel contains UV data for the different sides, and applies it to whatever faces it actually renders. So yes, texture atlasing is required, but I am pretty sure that is what this guy is doing, anyway, given that you need only one mesh per chunk, but each block can have a different texture, and you can only have one texture per mesh. No, Blender or anything else is pointless when making a voxel engine, because there are no cubes to begin with.
@Zarenityx you might as well get used to typing this over and over because there is about one question per hour on making $$anonymous$$ecraft here :)
and every single questioner has the same confusion, they think $$anonymous$$ecraft is made by "stacking up cubes"
it's fascinating observation that $$anonymous$$ecraft does not contain one cube. if I'm not mistaken there has never ever been a cube rendered in $$anonymous$$ecraft!!! (I believe when you play you can't have just "one cube" right? even if you did they'd probably only render the facing faces, heh!)
the whole thing is doubly-confused because there is a free complete $$anonymous$$ecraft starter kit kicking around on the forums, heh !
Answer by AlucardJay · Aug 24, 2012 at 04:51 AM
I have listed all the ways to custom UV map a unity cube here : http://answers.unity3d.com/questions/294165/apply-uv-coordinates-to-unity-cube-by-script.html
Imagine looking at the front of the cube, the first 4 vertices are arranged like so
// 2 --- 3
// | |
// | |
// 0 --- 1
then the UV's are mapped as follows :
theUVs[2] = Vector2( 0, 1 );
theUVs[3] = Vector2( 1, 1 );
theUVs[0] = Vector2( 0, 0 );
theUVs[1] = Vector2( 1, 0 );
// 2 3 0 1 Front
// 6 7 10 11 Back
// 19 17 16 18 Left
// 23 21 20 22 Right
// 4 5 8 9 Top
// 15 13 12 14 Bottom
So where the UV's for Vertices 2 is ( 0, 1 ), so is 6, 19, 23, 4, 15.
You can test this by replacing all the zero's with 0.5, then check every face of the cube has the same portion of the image, and rotated the correct way (not inverted) . Note if standing at the origin looking up the positive Z-Axis, Right is your right.
for example this script would map the TOP of the cube to any UV coordinates of a texture you like :
#pragma strict
// TOP
function Start()
{
// Get the mesh
var theMesh : Mesh;
theMesh = this.transform.GetComponent(MeshFilter).mesh as Mesh;
// Now store a local reference for the UVs
var theUVs : Vector2[] = new Vector2[theMesh.uv.Length];
theUVs = theMesh.uv;
// set UV co-ordinates
theUVs[4] = Vector2( 0.5, 1.0 );
theUVs[5] = Vector2( 1.0, 1.0 );
theUVs[8] = Vector2( 0.5, 0.5 );
theUVs[9] = Vector2( 1.0, 0.5 );
// Assign the mesh its new UVs
theMesh.uv = theUVs;
}
EDIT, In reply to : So if I create a texture atlas and assign sections to the different sides of the cube, is it possible to tile each side differently? Or would everything get tiled by the same amount? Cheers for the help, Muzzstick.
Me : I think an example scene would be a good visual demonstration. First, grab this texture : http://metaverse.mitsi.com/Secondlife/posts/uvmaps/images/uv_checker%20large.png
Now create a new scene, create a cube and attach that texture as a material. Create a new script and attach it to the cube. Copy in the below code, then hit play.
You see for each face a different part of the texture has been assigned, this is basically UV mapping. Change the values in the cube Inspector, then hit the Left mouse button. First try changing the width and height just to see the effects. Then change the x and the y for different start positions on the texture.
Hopefully this shows what UV mapping is, and how it usually applies to one texture atlas (sometimes called a texture map). Again, for a different texture, the plane method is the way to do it.
Anyway, here is the code :
#pragma strict
// using an image that is an 8x8 grid
// each image is 0.125 in width and 0.125 in height of the full image
// UVs in this example are given as a Rect
// uvs : start position X, start position y, width, height
// start positions are staggered to show different images
// width and height are set to 0.125 (1/8th square of the full image)
public var uvsFront : Rect = new Rect( 0.0, 1.0, 0.125, 0.125 );
public var uvsBack : Rect = new Rect( 0.125, 0.875, 0.125, 0.125 );
public var uvsLeft : Rect = new Rect( 0.25, 0.75, 0.125, 0.125 );
public var uvsRight : Rect = new Rect( 0.375, 0.625, 0.125, 0.125 );
public var uvsTop : Rect = new Rect( 0.5, 0.5, 0.125, 0.125 );
public var uvsBottom : Rect = new Rect( 0.625, 0.375, 0.125, 0.125 );
private var theMesh : Mesh;
private var theUVs : Vector2[];
private var xOffset : float = 0.0;
function Start()
{
theMesh = transform.GetComponent(MeshFilter).mesh;
theUVs = new Vector2[theMesh.uv.Length];
theUVs = theMesh.uv;
SetUVs();
}
function Update()
{
// change the UV settings in the Inspector, then click the left mouse button to view
if ( Input.GetMouseButtonUp(0) )
{
SetUVs();
}
}
// 2 --- 3
// | |
// | |
// 0 --- 1
function SetUVs()
{
// - set UV coordinates -
// FRONT 2 3 0 1
theUVs[2] = Vector2( uvsFront.x, uvsFront.y );
theUVs[3] = Vector2( uvsFront.x + uvsFront.width, uvsFront.y );
theUVs[0] = Vector2( uvsFront.x, uvsFront.y - uvsFront.height );
theUVs[1] = Vector2( uvsFront.x + uvsFront.width, uvsFront.y - uvsFront.height );
// BACK 6 7 10 11
theUVs[6] = Vector2( uvsBack.x, uvsBack.y );
theUVs[7] = Vector2( uvsBack.x + uvsBack.width, uvsBack.y );
theUVs[10] = Vector2( uvsBack.x, uvsBack.y - uvsBack.height );
theUVs[11] = Vector2( uvsBack.x + uvsBack.width, uvsBack.y - uvsBack.height );
// LEFT 19 17 16 18
theUVs[19] = Vector2( uvsLeft.x, uvsLeft.y );
theUVs[17] = Vector2( uvsLeft.x + uvsLeft.width, uvsLeft.y );
theUVs[16] = Vector2( uvsLeft.x, uvsLeft.y - uvsLeft.height );
theUVs[18] = Vector2( uvsLeft.x + uvsLeft.width, uvsLeft.y - uvsLeft.height );
// RIGHT 23 21 20 22
theUVs[23] = Vector2( uvsRight.x, uvsRight.y );
theUVs[21] = Vector2( uvsRight.x + uvsRight.width, uvsRight.y );
theUVs[20] = Vector2( uvsRight.x, uvsRight.y - uvsRight.height );
theUVs[22] = Vector2( uvsRight.x + uvsRight.width, uvsRight.y - uvsRight.height );
// TOP 4 5 8 9
theUVs[4] = Vector2( uvsTop.x, uvsTop.y );
theUVs[5] = Vector2( uvsTop.x + uvsTop.width, uvsTop.y );
theUVs[8] = Vector2( uvsTop.x, uvsTop.y - uvsTop.height );
theUVs[9] = Vector2( uvsTop.x + uvsTop.width, uvsTop.y - uvsTop.height );
// BOTTOM 15 13 12 14
theUVs[15] = Vector2( uvsBottom.x, uvsBottom.y );
theUVs[13] = Vector2( uvsBottom.x + uvsBottom.width, uvsBottom.y );
theUVs[12] = Vector2( uvsBottom.x, uvsBottom.y - uvsBottom.height );
theUVs[14] = Vector2( uvsBottom.x + uvsBottom.width, uvsBottom.y - uvsBottom.height );
// - Assign the mesh its new UVs -
theMesh.uv = theUVs;
}
That's a great example! Thanks
How would you then load your texture into those coordinates? (assu$$anonymous$$g you want the top side texture to be different from the rest)
This is where the UV coordinates come in. They take a piece of the material(texture) you are using. For the above example (Top of cube), I used :
theUVs[4] = Vector2( 0.5, 1.0 ); // top left
theUVs[5] = Vector2( 1.0, 1.0 ); // top right
theUVs[8] = Vector2( 0.5, 0.5 ); // bottom left
theUVs[9] = Vector2( 1.0, 0.5 ); // bottom right
looking at top left : x is 0.5 so this is the middle of the texture, y is 1.0 so this is the top of the image.
now looking at bottom right : x is 1.0 so this is the right of the texture, y is 0.5 so this is the middle of the image.
these UV coordinates would show the top right quarter of a material(texture/image). Is that what you were asking?
Edit : Looking at your comment on the other question, I think you are asking how to put a whole separate texture on a single face. UVs are for using a portion of a single texture, not adding other textures, sorry. What you could do is either create a texture atlas so that you can UV map, or create a plane and size/position that to replace one of the cube faces. Then you can put your separate texture on the plane (acting as a single face on the cube).
Thanks for the reply! Yes, loading a seperate texture for one side was actually what I was hoping for.
I'd thought about creating a plane to cover the cube on one side but hoped there was a more efficient way. (Although in all honesty it probably won't make much difference).
So if I create a texture atlas and assign sections to the different sides of the cube, is it possible to tile each side differently? Or would everything get tiled by the same amount?
Cheers for the help.
Answer by DaveA · Aug 23, 2012 at 09:16 PM
You can modify the mesh, yes. But really, there are many voxel systems available, I would strongly suggest getting one of them, it will save you a LOT of work. Voxelform, for example, uses tri-planar world-space shaders so it gets grass on top and dirt underneath and seamless textures.
Answer by electricsauce · Feb 18, 2013 at 04:29 AM
I would UV unwrap and texture in Blender.
Like I told @Sarper Soher , creating something in blender wouldn't work because there are no actual cubes. Every face is procedurally generated from a 3d array of hypothetical voxels, giving the illusion of blocks. And as each block needs different textures, but there can only be one texture per 'block'. This really needs to be done in code.
indeed. there would have to be 1000 explanations on here that $$anonymous$$ecraft has no cubes whatsoever, it only has conceptual cubes in the software .. just arrays and so on, like a database - $$anonymous$$ecraft has no cubes, it does not have one cube, it contains zero cube models, $$anonymous$$ecraft has never shown one cube, ever .. $$anonymous$$ecraft simply shows large horizontal or vertical surfaces that happens to have drawings on them that look like they are cubes ..if they were painted differently nobody would ever raise the cube issue" ... heh so that's 1001
$$anonymous$$y first attempt at a voxel engine involved cubes that shut off their behaviors and renderers at certain distances. It didn't quite work... It's probably the most common misconception that $$anonymous$$inecraft uses cubes.
Answer by jethrogillgren · May 31, 2018 at 08:16 AM
In 2018, this can be done using Unity's free ProBuilder add-on.
This example shows how to do that with a cube, and other shapes.
No. See above. The many posts by myself and Fattie explain why the meshes can't be premade in any way. The importance of UV mapping in code is so that they can be created procedurally. Personally I like the way they put it better:
$$anonymous$$ecraft has no cubes whatsoever, it only has conceptual cubes in the software .. just arrays and so on, like a database - $$anonymous$$ecraft has no cubes, it does not have one cube, it contains zero cube models, $$anonymous$$ecraft has never shown one cube, ever .. $$anonymous$$ecraft simply shows large horizontal or vertical surfaces that happens to have drawings on them that look like they are cubes ..if they were painted differently nobody would ever raise the cube issue