I have stumbled upon this problem ending up with much too many draw calls for what seems to be pretty simple stuff. Basically what i have is a grid that consists of 100 planes, and i need each plane (tile if you will) on the grid to have a random color. But unfortunately for each color another draw call is added which adds up to 100 draw calls for just this grid of planes (2 poly, planes) which have random colors on them. I would be very curious to know,if someone could help me figure out how to reduce this ridiculous amount for something so simple.
Someone suggested me create a separate array of materials create random colors on those and then assign those to the sharedMaterials attribute of the grid. But that did not make a difference when it comes to draw calls, so i’m a bit on a dead end here. Here is a screenshot, http://i.imgur.com/En6Kz.jpg
As for the script, this is basically all it is
public GameObject[] TileGrid;
for (int i=0;i<TileGrid.Length;i++)
{
TileGrid[i].renderer.material.color = new
Color(Random.Range(0.2f,0.9f),Random.Range(0.2f,0.9f),Random.Range(0.2f,0.9f));
}
As for the material itself, just Diffuse gives 100 draw calls as does Transparent/Diffuse or Vertexlit. So there is no difference there.
You should implement the grid as a single combined mesh. That will require becoming familiar with the Mesh class, but it will be far faster. Or you could get one of the existing sprite or tilemap tools, which would do pretty much the same thing.
Each material is a new draw call – so each material that has a different color generates a draw call. You can reduce that by using one Material with a texture atlas, or as Eric suggested make the whole thing a solid mesh.
Use a texture atlas if you need a decent bit of individual variation.
Alternatively, as Jessy suggested above, vertex color attributes should accomplish exactly what you want.
I have experimented with combined mesh before although not much so i might be wrong here, but doesn’t this also make it impossible to transform ‘the’ individual tiles ? Like in this video, http://www.youtube.com/watch?v=pZaKl_NZn6I .
Also i’d like to try figure out the texture atlas solution, could you perhaps provide me with some more information on how to go about this ?
Someone suggested also to me making use of vertex colors, but this would mean the tiles would have to be meshes that are then drawn with Graphics.DrawMesh correct ? I tried this but drawing an individual mesh also takes 1 draw call so for a 100 tiles you also end up with 100 draw calls, at least this is what happened in my experiment. Perhaps i’m doing something wrong here, i’m not sure what to do about it though.
No. Just make a class that represents a tile, and create a rotation method for it (altering vertex positions). Then make a function that assembles that data into a new array of positions, and assign it.
You mean a class like this, i’m not sure what you mean. [System.Serializable] public class SpriteObj { public Mesh - Pastebin.com This is a class i use to draw sprites basically, but i don’t understand what rotation would do to color the tiles. As for the texture atlas i haven’t tried that before so i’m curious how it works and what it does.
You need everything in the class that you need in the class. A color, some positions, and a rotation method sound like pretty good candidates to me.
I don’t know if “atlas” is the right word here. I’m fuzzy on when a texture becomes an “atlas”. You can assign UVs to your mesh, and look up colors in a texture, but if each tile is a single color, then you’re better off not using UVs, and just storing colors directly. (Unless your workflow is centered around Photoshop, instead of picking/scripting colors in Unity.)
Right so with this class, like i mentioned before if a plane mesh (2 poly) is assigned to the Mesh attribute of this class and you draw this on screen 100 times in a for loop on the positions of the grid you’d still end up with 100 draw calls.
One for each plane, same goes for the materials. So how exactly would i assign a random color to each individual mesh and put 100 planes on screen without adding a draw call for each single mesh ? Combining them all into one mesh, i think there is a script in Unity that takes care of that but would it then be possible to transform individual members of the sprite array or would they all be regarded as one ?
One draw call. The class will not store a Mesh. It will store data that the mesh uses. A class (or struct) is appropriate due to the fact that you have so many similar items.
Alright so please help me out here, i’ve this setup using the sprite class …
So spriteTemplate is a public Mesh var which i’ve a assigned a plane to. And tileGrid position is simply the positions of the imported grid i showed earlier, tileGrid is then set to inactive so its not visible.
for (int x=0;x<tileGrid.Length;x++)
{
tileSprite[x].Transform_Sprite();
tileSprite[x].Render_Sprite();
}
As you can see in this screenshot, this will take 100 draw calls Imgur: The magic of the Internet . You said this should all be combined in one, how should i do this ?
Or more specifically “Then make a function that assembles that data into a new array of positions, and assign it.” Assign it to what exactly ?
I don’t think you understand that you need to make a new class. There are not pre-built components for this, and this “sprite” class is not appropriate. You will be dealing with one mesh, but I don’t think your class should know about it. Put it together how you like.
Ok i think i might have misinterpreted your post, there should be another class. But this one mesh, you mean this should consist of one plane with 100 tiles instead of 100 separate tiles ?
That doesn’t look like your original screenshot. That looks like you’re just altering the colors of the plane mesh. You need to create your own mesh, that consists of 400 vertices/200 triangles. (i.e. 100 rectangles. You can’t share vertices at the edges because you need different colors on each side of the edge, and colors get interpolated between vertices, like every other attribute.)
The difference in this Mesh and the one in the other screenshot is that this is a solid plane made up of 100 rectangles … The other is 100 separate objects (planes) i exported both in a 3d package… I don’t understand though why it is necessary to create your own mesh ? If i create a plane made up of 100 rectangles in say Blender and export that… isn’t that exactly the same ?
for (int n=0;n<planeMesh.vertexCount;n++) // in start
{
col[n] = new Color(Random.Range(0.0f,1.0f),Random.Range(0.0f,1.0f),Random.Range(0.0f,1.0f));
}
for (int n=0;n<planeMesh.vertexCount;n+=2) // in update
{
col[n] = new Color(Mathf.PingPong(Time.time,0.2f),Mathf.PingPong(Time.time,0.4f),Mathf.PingPong(Time.time,0.6f));
}
planeMesh.colors = col;
planeMat = Matrix4x4.TRS(Target.transform.position,Quaternion.identity,new Vector3(3.0f,1.0f,3.0f));
Graphics.DrawMesh(planeMesh,planeMat,tileMaterial,0);
The difference in this video and the previous one is that each individual tile is colored with its own material, and in this video the colors are assigned with vertex colors.
Is the reason to create (generate) your own mesh with code that vertices can’t share at the edges ? , can’t this be done in a 3dpackage ?
But like you said if for example a select number of vertices are rotated they’re always attached to another so it won’t appear as if individual tiles are rotated instead it becomes a mess because the vertices neighbouring the ones that are rotated stretch out.