I'm currently working on an isometric city builder game. It took me awhile to figure out how to depth sort all assets properly and quickly. I have walls that sit on the edge of a tile, i.e. they take up almost no floor space. Since my game will display the interior of buildings, this means the typical approach of sorting everything by the screen.y position (so long as every asset is a cube (or stack of cubes), or broken up into cubes) fails, because the bottom of the wall texture can be a whole tile-size away from the bottom of the asset.
I had to implement "snap to grid" calculations in the background for moving units inside buildings, meaning for the depth sorting algorithm, I pretend they are on a different tile (when needed). Unfortunately I dont have a video of this yet.
As for efficiency, I implemented static quads (for non moving items) and only draw items within the quads on screen. And for units/vehicles, I do a rectangle collision check (unit rectangle compare to screen space rectangle). It's very fast!
> the typical approach of sorting everything by the screen.y position
Shouldn't that be sorting by the world.y position? Ie, northness, rather than northness + altitude = world.y + world.z = screen.y.
I'm not sure about how much it matters for your game particularly (you don't seem to have world.z coordinates), but in general screen-space operations are a recipe for that sort of bugs, and should be avoided whenever practical.
Caveat: I dont have any experience with 3D games, so we may not be speaking the same dialect.
My game is an "old fashioned" isometric game, meaning it is a 2D game through and through. All assets are square (for top down) or rectangle (for isometric) sprites. Of course, since it's pretending to be a 3D game, you have to draw/place the isometric tiles oddly so the inner rhombus (or hexagon, which is what an isometric cube is without shading) are drawn flush, since the graphics engine is working with rectangles. Thus the sprite's rectangles overlap like this: https://i.imgur.com/NTNHvbL.png
In order to simulate a camera looking into a 3D world, I need to draw everything from the top of the screen to the bottom, in that order, so assets with height are drawn over everything behind it (in world space)
For simulating world height (e.g. something flying one tile off the ground), you just need to move the sprite's screen.y position up the sprite's height (i.e. the height of the rectangle) per tile of height.
I have yet to implement terrain height into my game, but I think there are a couple ways to accomplish this.
1.) I can store the part of the asset touching the ground for all assets stacking upwards (like a multistory building). Thus I can keep the depth sorting algorithm I have.
2.) Or I can add the asset's world height multiplied by asset's (rectangle) height to the screen.y position (again, just for the depth sorting part)
For both cases, I may need to add micro adjustments if I need a specific order within the tile stack itself (seems unlikely). edit: this wont be needed unless I have overlap in the stacking, and I wanted to e.g. have something lower down on the stack be drawn over something above the stack, like an antenna or w/e.
Lastly, this only works if all assets are the same size (thus larger ones are a combination of smaller sprites).
To be fair, I was pilfering loanwords like "screen-space"(adj) from the 3D dialect.
> In order to simulate a camera looking into a 3D world, I need to draw everything from the top of the screen to the bottom
Right, the point I was trying to make was that, technically, you need to draw things from the north edge of the world to the south. If you have a asset with height, you need to draw it at a higher screen position, but also a later time, than a low/short asset that's at norther world position but lower screen position. (Presumably you know that already; I was mostly asking/objecting about confusing the screen position versus the world position.)
> I can add the asset's world height multiplied by asset's (rectangle) height to the screen.y position (again, just for the depth sorting part)
My point was that you'd add[0] the world height plus the world.y position, in order to get the screen.y, but depth sort based only on world.y, independently of height or screen position. That way things that are vertically on top of each other have the same world x and y coordinates (differing only in z), even though they're draw at different screen.y coordinates to provide isometric simulation of height.
0: give or take factors of -1 depending on which way the various coordinate axes go
Most 2d engines use shader system underneath, it easier to write a shader to solved all the z-sorting problems. Only minimal 3d maths and billboarding(tile) are all you need.
I had to implement "snap to grid" calculations in the background for moving units inside buildings, meaning for the depth sorting algorithm, I pretend they are on a different tile (when needed). Unfortunately I dont have a video of this yet.
As for efficiency, I implemented static quads (for non moving items) and only draw items within the quads on screen. And for units/vehicles, I do a rectangle collision check (unit rectangle compare to screen space rectangle). It's very fast!
You can find progress updates on: https://www.reddit.com/r/Archapolis/
Or a few video logs at https://www.youtube.com/channel/UCUYLstskSLNcSkFg1giTBtQ