I’m currently working on a game that’s 2D, top-down, tile-based completely made of 16x16 textures. When I started I simply made 1x1 quads and applied the material for each texture. I’m worried that I’m gonna end up with huge amounts of materials and textures which will make things cluttered and messy. I did some research and stumbled upon texture atlases. Seems like the best idea. Reduces draw-calls to 1 per atlas and only 1 material too. The only thing I have problems with, is the generated UV mesh.
If I understand this correctly, there needs to be 1 generated mesh instance per texture used of the texture atlas. I managed to create and save the mesh instances as assets but here’s my main worry:
Does this mean if any of the textures in the texture atlas shift, the mesh would need to be remapped?
I just want to get some input on what would be the best way to go about making this? Which method is better? Single material/textures or texture atlases? Or is there an even better way?
To get the best out of that system you would have to create new mesh every time you change a tile; (Actually, same mesh with new UV map)
You could create “tile editor” in Unity, that should not be a problem.
That would render extremely fast, go for it if you have time to work on such system.
Yes, you absolutely want to use a texture atlas if you have many objects and are worried about drawcalls.
If you make the atlas yourself, then set the UVs of your objects, then change the texture : yes, you will have to reset all the UVs for your objects.
There is another way : use Texture packer as it outputs a file with all the names and locations of the images on that texture. Then you just have to make a reader to read this file, and assign the UVs to your objects from there. I did this a while ago, but I can help fill in all the gaps once I get feedback on what you did and didn’t understand from that =]
Well that’s a funny coincidence. I actually started with your example and just edited it a bit to fit my needs. I use TexturePacker as well. Love that program. The only issue with TexturePacker is that it moves/sorts the textures around every time a new one is added.
So I guess I need to figure out how to manage the UV mesh assets and refresh them every time the atlas gets updated.
That example got developed into my own GUI system. What I have is a ‘manager’ script that has 2 arrays : one for the quads, and one for the name of the texture to go on that quad. Then I use ContextMenu to run the manager script without hitting play, and it updates all the quads with the new UV information. I’m just about to sign off, but if you are really stuck then post back and I shall make an example for you this weekend.
I’ve actually just finished a similar manager script as well.
I simply select the json file in the project view and hit update in the context menu. It then generates all the quads in a folder for me. The tiles that have been created already simply update themselves that way
Here’s the code, probably not optimized to the max but for now it seems to work.
As stated above, you are probably best off approaching this exactly the same way you would in 2D, which is moving a theoretical viewport around and updating parts of it as needed to reflect newly visible tile data.
This is actually a lot easier in 3D than it used to be in 2D. If you keep a static mesh and treat it as a sheet that follows the camera around in worldspace (in gridsnapped increments of course) and has a separate pair of tris for each tile, then you’re just updating UVs based on the tile definitions currently visible (a sinmple grid walk).
As for atlasing, you’re just going to be storing a (presumably nicely packed) tile type definition, like a gigantic array or 2D array, and some map that knows which tile types get which UV offsets for the current atlas. Change the atlas, change the type->UV map, update UVs, done.
Looking over the code you just posted, it seems like you’re dynamically reconstructing this map from string data. I would definitely recommend approaching it as described above.
Here’s an example of something similar, although it isn’t exactly what you’re doing: This is a quick sketch of a Minecraft surfacing system I wrote in a couple hours last week: http://forum.unity3d.com/threads/177831-MineCraft-style-game?p=1218902&viewfull=1#post1218902. If you download the project files linked there, you’ll see how the maps are set up. Yes, the type->offsets are hardcoded, but could easily be spat out as a float[ ] in a .bytes TextAsset. The important things are cell type storage, type->offset storage, and fast grid walking to generate or modify a mesh.
Your approach definitely seems extremely effective and optimized. I’ve downloaded your minecraft project and I’m working my way through it as I’m typing here.
It is currently a bit out of my league because I’ve never worked with many of the techniques you use in your script (You can probably tell I still have lots of learning to do), but I’m gonna try my best to learn from that script.
I think for me right now it might be easier to stick to my current approach because I find it easier to generate and edit a map. Here’s what I’m doing exactly:
I have texture atlases which contain all the separate tiles. Once imported, I made that script above to generate 1 mesh per texture in the texture atlas.
I have another script which is my map editor. It let’s me choose from a few collider options and lets me enter the name of the texture I want to draw on the map. I’m aware I might be ending up with 2000x2000 quad gameobjects, but I thought with some smart culling I might make that work.
I’ll let you know if it works out.
Thanks for the awesome tips
When I made a big area with lots of repetition, I noticed I get sort of like a grid pattern in my textures. I managed to get rid of it by extruding all textures by 1 pixel in texturepacker. Is there any other way of fixing that? Or is it unavoidable?
hi Germanator, I couldn’t help but notice that you’re creating a mesh for each of your tiles, have you consider combining some of those meshes. You would still end up with the same performance if you use one material, but you end up with fewer objects.
This defect is called “Edge Bleeding”, and there are many contributing factors. But essentially, edge bleeding occurs whenever pixels in the source texture are blended since pixels are blended between adjacent tiles.