top of page

Fast Chunks - 3 - UVs and Database

Dernière mise à jour : 19 avr. 2018



What we have now is chunks with the same texture applied everywhere. Why don't we add more blocks?


Let's create a basic Database!

In my project folder, i created 2 other folders next to my scripts :

- "Type", where i created a script called "Block" :

Here, i will store the type of objects that can exists like Blocks, Items, Mobs, ...

- "Databases", where i created a script called "DB_Blocks" :

Here i will create databases for my objects, where i store every existing Block, Item, Mob, ...


Here is my Script folder :

My Constructors folder :

My Databases folder :

My Types folder :

Open the "Block" script. This is where we will setup a Block type object with it's properties :

First let's add some variables :

Notice that the script won't depend on MonoBehaviour. We will create instances of it from another script.

- First, we need a name for our block.

Then two booleans :

The block is solid

The block is transparent


- Then we will give the block it's textures positions in the atlas :

If it is a full block with the same texture on each side, we will give it to the variable "texture".

If it is a multitexture block, each texture will be given in the other variables.

- Finally, to let the others scripts know if it is a multitexture block, we have a boolean.


Now, we will need constructors to create new blocks. We will use multiple constructors.

Let me explain :

When we create an instance of a class, here a block, we will give values to it.

Meaning that when a new block is created in the database it will have a name, a texture, booleans.


Using multiple constructors will help having different types of blocks generated but still called "blocks".

- There will be a constructor for a block with the same texture for each side.

- A constructor for a block with multiple textures.

- A constructor for an empty block (Air).


So, when we create a new block in the database, we give values to it. It's the basic constructor.

If we add more values to the block, the other texture values, it becomes the second constructor.

If we don't give values, it is air.

Here are the three constructors. We give values when they are called and those values are stored into the block instance we created in the database.

The air constructor already has values.


Now you can go to the "DB_Block" script. We will add blocks to the database.

First, we will need a List to contain all the blocks of the database. It will contain Instances of the Block class, meaning each block we add with it's values.


Now, in the Start method, we will generate our block instances and store them in the List :

First, we create the air block. It is an empty constructor.

Then, i created a Dirt block :

We give the name : "Dirt"

isSolid : true

isTransparent : false

texture (full) : position 0,0 in the atlas.


Next, the Grass block which has multiple textures :

Name : "Grass"

isSolid : true

isTransparent : false


here, we give three more values, it will automatically switch to the second constructor with 3 texture values :

textureUp : position 1,0

textureSide : position 2,0

textureBot : position 0,0


And we do the same for the Stone block and the Bedrock.

So, when the game starts, all those blocks will be generated to in the Database.


Now we have a Database. But what if we need to find a specific block in the it?

We will create a new method :

This method will return a Block :

We give it the Block name.

It will loop in the list of the database and if the block with the same name exists, it will give the whole Block with it's values.

If it doesn't exists or the name is not the same, it will return nothing.


- Save and go to the Block_Cube script, used to generate a cube :

- First, we add a block variable of type Block. It will be the block contained at the new cube position, the one we will work with and get values.

- In the Block_Cube constructor, we will also ask for the Block which will be at this position, the one we will store in the new variable. And give it to the variable from the constructor.


Go to the CreateCubeSide method and remove the UV lines we created. Let's add a new way to have UVs.

The new UV system is a big part to explain, i made a post here to explain how it works.

It's not that hard, Unity calculates automatically our values.


After we have set the vertices for each face, we will add the UVs system. There are a few lines to add here :

- I will use a 4x4 texture, we create an offset of 1/4.


- Then, we will need the texture stored in the block we are creating. Remember that the block is given by the chunk. The chunk finds the block in the Database, gives it to the block generator, here, and now we have the block stored with it's texture values. Also, when this "CreateCubeSide" is called, it doesn't generate the whole cube at once. It is called for each side of it.

We look at the multitexture boolean of the block. If it is a multitexture, we look at the side we are making and for each side, we find the position we have in the atlas.

If the block is not multitexture, we will look at the texture we have in the block.


- Finally, we add UVs to the list again but this time we won't have "1,1", "0,1", ..., instead we have calculated values i explained in the post about it. Unity will calculate them.


Now we will change things in the Chunk script :

We won't store IDs in the chunk anymore, now it will be blocks with values.


But don't forget to change the array initialization :

- Now let's change the GenerateVirtualMap method :

Let me explain how this will work :

Now, for each chunk, if we are at World.chunkSize - 1 in the y loop (the top of the chunk),

we find the Grass block in the database and then we store it int the chunk map array.

If we are not at the top of the chunk, we will do the same with the Dirt block.


- Go to the GenerateBlocksMap method :

Remember, here we a a line which was "If the id of the block i am looking at is 1, we make a block".

Now we will have "If the block i am looking at is not air, we generate the block supposed to be here".

if the block is not air, make a new cube at this position which is the cube we previously stored in the chunk map array.


- The last thing to do is in the BlockExistsAtPos method, this is where we checked if there was a block at a position :

Remember, we had a line which said "If the block here is 0, we return false. Because there is air".

Now we look at the block stored at the position and at it's boolean "isTransparent". If it is transparent, we return False, like "There is no block here, you can draw".


- Go back to Unity and give the Database script to the World object :

Remember to change your terrain material to use a texture atlas.


Now you can test your game :

You'll see that each chunk is the same.

We will fix this in the next part, when we add noise to the chunks.


It is possible that nothing appears. This is because the chunks are created before the database, so we automatically have no block returned. You should use it even if it already works because any lag can make a lot of issues.

- Go to your DB_Blocks script :




We replace the start method with a public "GenerateDB" method. It will manually build the Database.


- Now go to the World script :





In the Start method, just after we initialize the chunk dictionary, we generate the Database attached to the world object.


- Now it should work.


_____________________


BONUS :

Some of you have noticed holes between blocks in the chunk.

To fix this, go to your camera and disable "MSAA" :


This is the MultiSampling Anti Aliasing used by the camera renderer.

69 vues0 commentaire

Posts récents

Voir tout
bottom of page