3D Tile Auto-Height Placement -- Can it be based on a 3D Mesh's Geometry?

When placing 3d tiles, such as coins, etc., is there an easy way to make them Raycast before placement to let them take into account the height or distance from an underlying mesh’s normals (and then place them at that y/z height?) while still placing them at the same x/z location on the tilemap otherwise?

For example, say I created a mesh that has nice 3d slopes and edges in its geometry (blue lines in my attached example), but that geometry was mostly 2d-aligned to the Tilemap grid (black/grey lines in attached example). As you can see, it’s a 2D tilemap grid, but each tile’s vertical (or depth) placement is the only thing that’s altered from the standard behaviour when placing tiles with the brush tools:

2673303--188687--Tilemap Feature 3D.png

In its layout, this example mesh uses ~1 to 2 units of the tilemap per facet [mostly] across the 3d mesh (even on slopes!) with an optional maximum height/depth distance for the raycast to test before canceling the potential placement of a tile (currently being the orange/yellow coin in the attached image, for example), all aligned mostly to the tilemap grid in every way EXCEPT for accounting for specific depths or heights during placement, as that RayCast test would decide this instead of placing the coins/tiles at a default height everytime). If one were to place a block of those tiles/coins, the raycast check would take place at every cell and place them en-mass on all the geometry that passes that check (assuming it’s enabled), and picking tiles to copy would also account for the Tilemap’s RayCast max distance check too. This could possibly even use the attached collider to Cast to the geometry below in order to check the whether it touches geometry below it instead of using the raycast.

Theoretically, this could even handle hills and smooth sloping terrains made out of such stuff as heightmaps, but using a grid to place stuff on top of it squarely instead of manually placing it and trying to optimize for it later.

In cases where there is overlapping geometry, for example just behind the slope near the “No Geometry” area where the top of that slope overlaps the tile below, one could even specify a “startingHeight” to determine at what vertical location the RayCast/Cast takes place so that if you really need to place something below an overlapping section, you could specify the height the tile placement will start looking (ignoring anything above that height, assuming geometry is not colliding while using the Cast functionality).

No idea whether this can be done yet or not with the system, but it would be incredibly awesome to have such an option for those of us who’d love to use the built-in tilemap and brush system to do this sort of thing!

It is a bit overwhelming. Maybe if you ask more specific questions, we can answer more accurately?

Right now the brush API gives you OnPaint callback. Internally its fixed to 2D, though. Basically it is raycast against grid plane. The callback API does have 3D coordinates, but we are not actually using the Z for now. I guess we could expose the actual raycast logic for the brush to override. Will think about it.

We did experiment with 3D raycast painting against voxels, but this is future tech and probably not included in first release.

2 Likes

Yep, what’s in that video is very awesome! Very impressive indeed! It’s really great for tile-based 3d levels (which is something I’m super-interested in creating and there are no good solutions available to do it with Unity that I’ve found!). So now I’m wondering if it’s possible to do that in the Unity Tilemaps build right now? If so, that’d be excellent!

What I was mainly trying to illustrate is placement of 3d tiles (like the Tilemap3D video above) but using a raycast to find the top of uneven or bumpy geometry (say, perhaps, a Unity terrain!) and place tiles on it at various heights across the bumps/contour of it while still following the 2D grid and having the option to set a maximum distance (up or down) that the ray would look for some geometry (up and down a maximum distance) before it decides whether a tile should be placed or not. At the very minimum, exposing the raycast logic would at least allow us to piggy-back from the existing Tilemap3D system (hopefully that’s going to be included in Unity soon!) and apply our own logic (perhaps in addition to the existing rulesets we create!)

As shown in my image (quite poorly), this would allow placement of stuff like coins/collectibles on uneven, non-grid-based, geometry while still maintaining a semblance of the 2D grid in positioning, regardless of the shape of the ground, allowing grid-placement to contour anything 3D, from a heightmap terrain, voxelized terrain (both smooth and blocky), to even a sculplted 3d model with edges and overhangs. This could be useful for RTS, platformers, or really any kind of 3d game that has a loose connection to a grid. It’d be useful to be able to choose between the 3 types of raycasting logic (i.e. 2d grid w/ ruleset logic, 3d tiles raycast w/ ruleset logic, or simply 2d grid w/ Geometry Raycast up and down at a max distance logic)

So there are two systems that are kind of separate: Brush and tilemap.

Brush system lets you paint on a grid. It is not dependent on tilemap. You can paint some other data/component/stuff. It is really open-ended. The API is 3D, but currently we force the Z to 0. Simply exposing the raycast would probably go a long way. I think we will do that.

Tilemap system on the other hand is fully 3D. In the video we did some internal batching magic that isn’t there right now, though. This means that doing what we see in video might potentially slow down the game and especially the editor quite fast. When you operate in 3D, the object count explodes.

So to your question “if it’s possible to do that in the Unity Tilemaps build right now?”, I’d answer “Yes, but not carefully supported like 2D”.

@keely
Thanks for clearing that up! Two separate systems are definitely better, and exposing the raycast would be a step in the right direction!

IMO, that tilemap system, even in it’s current state, would be a great addition to Unity! I don’t care what it takes – that is the stuff of legends right there! I’ve been needing something like what’s in that video for a long time, but indeed, the performance aspect has been holding me back indefinitely!

Speaking of performance – just some thoughts if you’re interested:

Not sure if you’ve done this in the Tilemap3D system, but, aside from the batching optimization (and assuming each tile is somewhat of a 1x1 cube or slope), have you tried welding vertices within a certain distance from (rule-specified) adjacent tiles (perhaps with a little UV stretch if necessary)? If not, you could have an option, per tile rule, for all six (6) sides of the ‘cube’ (and any edges touching another tile) that would decide various welding options. Some of these could be whether to weld by adding vertices nearby where necessary (to avoid heavy uv-stretching, and act as a sort of ‘smoothing’ algorithm between tiles), or instead use only existing vertices from the adjacent tile if near enough to the current tile, otherwise adding the options “don’t weld this side/edge” or only “match vertex for vertex exactly”, and possibly give the option whether to weld each one of the 4 edges of the ‘face’ of each side of the cube.

You might even give control of weld-averaging to the user in the way something like “Terrain Stitcher” does in letting the user decide how to stitch terrain edges – but for each side of the cube, and then each edge of each side of the “cube” determined by different rules. If you’re already setting up rules for each tile interaction, why not allow one to set up rules that determine how that geometry meshes too? If you haven’t already, take a look at Terrain Stitcher: Unity Asset Store - The Best Assets for Game Making

Adding a giant cube of 3d tiles would be nice too, but even then, each tile (at least on the edges) would double-check its ruleset upon being added. You’d probably create it something akin to the way 3dsmax does its cube creation. A feature like this would be unique to Unity AFAIK and is sorely missed from many games. Combining this with Unity’s terrain editor would make it simple to create both organic AND artificial structures (in the same game!) quickly and easily!

In my opinion, making a tilemap act like any other mesh, would increase performance greatly if it was done at runtime. You could always keep track of the tile data until the user says “Convert to Mesh” which, internally, tells Unity to forget about the tile data – the user wishes to use this mesh solely as a mesh now and no longer cares about the tile data. It might not be a bad idea to let users represent tiles as indexes and let the mesh algorithm do its thing based on ruleset data when tiles are added and removed. If players wanted more control over the generated meshes, they could simply export the mesh, then tweak it wherever they require in case UV sets aren’t perfect.

@keely

Still following the progression of this system – any updates at all?

I would think internal optimization would be much easier if you implemented something like this as a type of terrain. The user would only define the prefabs he wants, and the internal system would use the GPU to instance/disable/rotate them across the visible world.

Thoughts?

1 Like