I am making a tile based game where different tile types are represented by prefabs. Levels are built at run time by instantiating tile prefabs and setting their transform (using level files). Tiles can also be moved, rotated, destroyed and created while playing. Some of the tiles are based on cubes and when there are several of them adjacent to each other, there are sometimes black gaps between them. They appear at certain zoom levels or camera positions. Antialiasing makes it happen less often but often the gaps just change place.
So I assume the problem could be that due to floating point inaccuracies and rounding errors, adjacent tiles end up having slightly different vertex positions? But how can I verify and/or fix that? I can access the mesh filter and mesh of an object but the vertex data there seems to be untransformed; the vertex data is the same for all the cube tile objects in different places. So what should I do? Set the transform for each cube tile to 0,0,0 and handle moving by changing vertex data? Surely there must be a better way…
I don’t know that it would be easy to verify, as the computations in question generally occur on the hardware side. But in general, geometry undergoing arbitrary transforms can’t be expected to align exactly.
That’s right; the transform is applied later in the pipeline.
Personally I’d probably work with the mesh data directly in order to ensure deterministic results. Doing so isn’t entirely trivial, but it might be the best choice for a tile-based game of this sort.
Maybe someone else will be able to offer a better suggestion though.
screenshots of your problem might help but maybe it’s not geometry gaps you’re actually experiencing. If the problem appears at certain zoom levels or camera positions it may just be a problem of texture filtering, If your tile maps are not padded.
The camera position and zoom has to be exactly right for the gaps to appear at certain places. If the camera is moving smoothly, this causes flickering as there is often one-frame gaps somewhere (either fully vertical or fully horizontal).
The prefabs are made from cubes of size 1 so all the vertex coordinates are either +0.5 or -0.5.
…
I Removed stuff from here since I found a bug in the code I was describing. I learned that if I access prefab’s mesh even for reading, it will cause the prefab to lose its link to the mesh. But should it be possible to modify the mesh vertex data of an instantiated prefab without it affecting other instances of the prefab or the prefab itself? I have not managed to make it work yet but there can be a trivial bug somewhere, I will continue to debug it later…
There was a stupid little bug but I got the relative->absolute vertex coordinate conversion to work now. Unfortunately, it didn’t help the actual problem at all. Tiles are now instantiated prefabs of cubes whose the transform position is set to 0,0,0. The mesh vertex data of each instance is set to absolute coordinates, they don’t have any rotation and scale is 1. Tiles are in right places but there are still those gaps once in a while. I am running out of ideas to try…
The image links don’t seem to work, but regarding the problem in question, are you sure that the shared vertices match exactly? Remember, if there’s any math involved (e.g. addition, subtraction, etc.), that can be enough to cause the vertices not to match. To ensure that they match, you really need to ensure specifically that vertices that should have the same value actually do have the same value by using the same value (or the exact same sequence of arithmetic operations) for each.
Yes the images don’t work for me either any more, there is clearly something I don’t get in the attachment system in this forum, either :).
I will debug the issue further later today but I am pretty certain the vertices matched exactly. The coordinates were all like 0.5, 1.5, 2.5, 3.5 etc. and since there was no scaling or rotation, I was just adding small integers to them (which should work accurately even with floating point numbers since 0.5f is 1/2). To be more sure I also tried to multiply every vertex coordinate by two, rounded the result and divided by two again. I could try once more by using just rounded integer coordinates but I can’t really see how that would change anything.
Maybe I should make a small simple example project that demonstrates the problem…
There is one prefab named Box and TestScript instantiates it several times to make a grid. Transform for each instance is set to (0,0,0) and vertex data is rounded to integers. Camera is moved automatically when run. When I run it, I keep getting lots of annoying horizontal and vertical black lines appearing here and there all the time.
Here are working links to the earlier screenshots:
Well, it is still a problem that I have to solve at some point even though I will be focusing on other things for a while now. If you or anyone has time to check that project and can find a fix, it is definitely appreciated! The code in that project is quite simple and in my opinion, it looks like this could be a bigger issue that could affect other projects, too.
I noticed that setting near clipping distance to 0 made the problem even worse but setting the value bigger than the default didn’t help. What I might try myself next is to see what happens if only the front faces of the cubes were rendered…
I took a look at it. I played around with it a bit, and as far as I can tell, the problem actually seems to be caused by the lighting (if I turn off the directional light and set the ambient light to identity, the problem disappears).
It’s not immediately obvious to me why the lighting would cause this effect, but if I happen to think of anything, I’ll let you know.
I haven’t download the project, but a common problem is that you need to average the vertex normals of the overlapping verts or else you’ll get a seam.
I’ve been messing around with your project. I may be wrong but I think what you’re experiencing is just plain good old Z-fighting. The black lines are in fact the faces of the cubes along the depth axis ‘intersecting’ with the visible faces. Just place a colored light toward these sides faces to see how the line artifacts change color. Another hint is that if you make your material alpha blended, you won’t see anymore the glitches : no z-write, no z-fight. I expected that modifying the near clipping and far clipping planes would improve the situation but as you’ve already stated, it can only make thing worse not really better…
I don’t think welding the front faces of the cubes will make it better cause I’ve been able to reproduce the same effect with orthogonal planes ‘crossing’ inside a polygon and not along some edge. Maybe you should use planes instead of cubes for the elements of your grid which are not on the border.
It is probably a good idea anyway to prune those invisible cube faces for optimization reasons. Things can get a bit complicated, though, since new cubes can be added and removed dynamically. So I have to make a system that keeps adding and removing polygons to objects when their neighbors change. I don’t know what happens under the hood when a mesh is modified but I guess that adding and removing polygons is not a super slow thing to do?
By the way, when I was debugging the issue, I noticed that the cube meshes generated by Unity had more than 8 vertices. I didn’t dig deeper into this but it was probably because each vertex has many instances of itself with different normals for different faces. Niosop suggested averaging those normals but I guess that would screw up vertex level lighting for cubes, right?
That depends whether the Unity engine optimizes the rendering to only take visible triangles into account.
The default mesh generation methods assign brand new vertices to each triangle you create. Basically how a mesh works is by assigning three vertices to each triangle. So: add three vertices in the vertices array, then create one triangle in the triangles array and immediately assign those new vertices to it.
If you need to weld vertices in a mesh, the brute-force solution I used for my marching cubes project is to check, when creating each vertex, whether a vertex already exists at the same position. If it exists, then instead of adding a new vertex, I assign the existing one to the triangle.
I run this during triangle creation loops, but it gets very slow with larger meshes (involves a few ifs, which can bring quite some lag when trying to do it in realtime, because it iterates 3 vertices then 6 then 9, etc… adds up pretty fast). I didn’t start noticing the effect until I looped through more than 3000 vertices at a time though, which is probably irrelevant in your case unless your combined mesh is made of thousands of tiles and you want to change it every update or something.
Also, averaging normals looks wonky on 90° edges, and will not really work with separate triangles without normal smoothing math which might be just as complex, if not more, than merging vertices.
You could also create the 16 variants of each block (with or without a neighbor in each cardinal direction) and feed the mesh used by your gameobject with the correct one. It would be cheaper that way.
You’re right. The cube needs more than 8 vertices in Unity to preserve the hard edges and you certainly don’t want smoothing for your cubes.
This is what I ended up doing. It was not a trivial thing to do since the scene is dynamic and meshes need to be updated when cubes are moved, created or removed. But anyway, it seems to work now and the artifacts are gone!
Im searching through the forums to see if anyone else has these problems and I found this page. Im using tiling to create my levels and I have run in to this problem even though I used vertex snapping. I read the thread but I still don’t understand how you solved. Help? Here is a pic
My problem was that my tiles were in fact cubes and the different sides of the same cube had z fight issues. It would seem that your scene is not made of cubes but of just front facing polygons? In that case, the problem is probably something else than mine but I don’t know.