- Home /
Efficient use of texture files
I'm working on a tile-based puzzle game for tablet systems. One of my goals is to have a visually beautiful game, and having many kinds of beautiful tiles necessarily requires a fair number of high-res textures. Before I get too far down the line, I want to make sure I've got an efficient framework in place, one that makes good use of both processing power and memory. I don't yet understand enough about the internals of Unity to make optimal choices, and I'd appreciate your help in figuring this out.
The issue is complicated by the fact that I want to support modding. I want to allow players to import and use their own image files to create new types of game tiles. This means that I need to be able to do all texture-mapping via scripting, and the script-accessible texture mapping appears fairly limited. It seems that the only thing you can do is affect materials, and you can only do that in two ways: a) change the texture associated with a material b) set the x/y tiling and x/y offset values.
Question: Should I use one texture file per tile, or should I use a more complex (but maybe more computationally efficient) 3 texture files per tile?
The tile model is a 3-D hexagonal prism. Imagine a 2-D hexagon, then extrude it just a bit into the 3rd dimension. This gives you the tile model. Then, cut along the edges of that model, unfold it, lay it flat, and you get a rectangular-ish array of polygons that you can map onto a texture. At this moment, each tile uses a different material with a different 1024x1024 texture. When you put the rectangular-ish UV polygon map onto the square-shaped texture, you end up with a lot of blank space. So in each 1024x1024 texture, something like 40% of the pixels go unused. That mapping looks like this:
One alternative would be to use three texture files for each tile-model: one for the hexagonal top face, one for the hexagonal bottom face, and one for the edge faces (repeated, so that each rectangular edge face would have the same texture). There would still be some unused space on each texture/image, but not as much, and I imagine that fewer wasted pixels means less wasted system memory.
So, to go the 3-texture route, and still have all the texture-mapping doable via scripting, I think I'd need to split my tile models into three parts: a top, a bottom, and a side-ring. Each part would have a separate material, but each material would have a simple texture mapping: x/y tiling = 0,0 ; x/y offset = 0,0. Since the texture mappings were simple, I could hot-swap texture files with ease, thereby making it easy for players to add their own images to the game.
Returning to the question: Regarding memory usage - is it better to use one texture per game tile, or three textures per game tile? Or is there some other option that would be even better? Or does it maybe not even matter that much?
Technically, it would likely be more efficient to use one texture per game tile. It's usually faster to use a single large texture per object than several smaller textures as this reduces the number of draw calls required to render the object (every time the texture changes, another draw call is needed).
However, if you're not planning to render an excessive amount of game tiles at the same time, it might be worth using multiple textures per object if it allows the individual textures to make better use of the space available.
Generally, if there will be many instances of an object, it's best to use a single texture. If the number is limited, multiple textures might make more sense (both in terms of wasted space and convenience).
A given game will include 20-30 tiles of 10-20 different types. So there will only be a few instances of each object.
And speaking of draw calls, after some further reading, I'm thinking that the proper solution may be a texture atlas. I can create one texture for each tile, then sew together multiple textures into an atlas. If I do that in an intelligent way, I can $$anonymous$$imize the number of unused pixels in the atlas.
According to my understanding of drawcalls, if I've got multiple models, each of which use a different part of the atlas, the automated draw call batcher can combine those into a single call. Thus, I'd be able to draw different kinds of tiles with a single draw call, as long as all of those tiles used the same atlas.
If you're okay with the creation workflow associated with using a texture atlas and your individual textures are small enough that a texture atlas containing all of them wouldn't be too large (2048x2048 is often cited as a reasonable upper limit), that could indeed be a good option.
the script-accessible texture mapping appears fairly limited. It seems that the only thing you can do is affect materials, and you can only do that in two ways: a) change the texture associated with a material b) set the x/y tiling and x/y offset values.
No, you can also change the UV coords of all vertices within meshes.
I think I'm O$$anonymous$$ with the atlas creation workflow, as long as I can automate it through scripting, which I think I can do.
However, I should have looked into texture size limits. Given that I need most of 1024x1024 for each tile, I'd get maybe 4-5 tiles per 2048x2048 atlas. Then, as most draw calls in this game will be for tiles, using tile atlases would give a factor of 2-3 reduction in draw calls, and a slight increase in memory usage efficiency - all of which seems like a worthwhile payoff.
Your answer
Follow this Question
Related Questions
The name 'Joystick' does not denote a valid type ('not found') 2 Answers
Blender to unity, importing UV mapped image textures 1 Answer
Distorted/Warped Textures On Character Model After Bundling For Tabletop Simulator/In A Build 1 Answer
'.' is not a valid texture file name on asset warning/error 1 Answer