I have a tile-based top-down adventure game where the camera follows the player. I want to make it so the map wraps around on it's edges. So, when my character stands on the corner of such a map, you actually see all four corners instanced.

Most of the tutorials I've seen for sprites and so on that wrap suggest making copies of the graphics nodes in such situations. This seems like a lot of overhead to duplicate an entire tile-map and keep it's state synced across 4 copies for what is, in essence, a rendering issue. I could render the tilemap to a back-buffer, but then I lose all Z-index information, which causes problems because I'm layering tilemaps.

What's the suggested solution to solve this problem?

I'd go with rendering it on a custom viewport. Not sure why would that result in loss of z information.

Individual tiles in a tilemap can have separate Z indexes. When you render to the viewport, it renders as a texture. To the best of my knowledge, Textures don't have support for Z indexes in their individual pixels.

If Tile A's index is below object B, but C's tile index is above A (The object is a character walking behind a pillar, say), then this won't be represented in the viewport texture. The entire tilemap will have the option of going above or below C, the character object, which is wrong.

You render characters into the viewport too.

What I would do is make duplicate tiles in the tilemap equal to one screen size (or slightly larger to give some room for error). So as the player walks to the edge, it will appear as if they are on the other side, though they are really not. Then once they are fully in the border area, quickly move the player (and any relevent objects like enemies that are on the screen) to the real position on the other side of of the map. You'd have to get the math perfect, so there is not a jump, and it might mess with the physics a little bit, but should be possible.

Another way is to have 4 cameras (at different points in the map). The background you see in the game would be a combination of the 4 viewports (though normally you would just see one if you are not on the border). But if you are on the border, you show the main real camera viewport, and then the 1 (or 3) fake camera viewports and line it up so they are exactly touching. You are not rendering the tilemap to a texture. This is a live feed of the game camera, so it will work with everything Godot supports and it will look exactly the same.

I wasn't aware you could have multiple cameras rendering the same scene at different points of view. How is this done exactly? My understanding was a viewport will just renders it's children, and that a scene can't have more than one parent, but I'd love to know if there's another way.

This sounds like an ideal solution though. I've already got the math down for this using a mockup that just instances three extra copies, but it'd be much easier to do this with just rendering.

This was just an idea. You can have as many cameras as you want, but only one can be the main camera at a particular time. Let me do a test to see if you can still render to secondary cameras simultaneously.

So you can have multiple cameras and as many viewports as you want. Here is the basic idea (for a split screen game, but it's the same technique). https://kidscancode.org/godot_recipes/2d/splitscreen_demo/

It's a little hard to work with, though. Once you put everything in a viewport container it becomes hard to work like that in the editor (you can't click on objects anymore, it just selects the viewport). So I think the concept is supported, but it's not user friendly. I'm still messing with it though.

I got the split screen working, it is indeed seamless. However, I realized that you still need to teleport the player and all objects to the new wrapped position. So it doesn't solve the main problem with the first (easier) solution of just making a duplicated "buffer zone" that is the same on both sides. And it's impossible to work on the game once everything is in a viewport, though there may be a way to automate this with code (rather than moving all your game to a child of the viewport).

If you are wanting to render the same scene from multiple Viewports, I believe as long as you don't have "own world" enabled and have a Camera/Camera2D with enabled set to true, it will be able to render to the ViewportTexture of the current scene. It's been awhile since I've tested though, so I'm not 100% sure.

My hunch would still vote for a tilemap copy solution. Something along the lines of @cybereality's first suggestion. Especially if there is no much (or any) persistent state held in the map itself.

I'd go with maintaining 4 adjacent tilemap chunks, each the size of the screen, with data copied from the main large map. The main map is not visible at runtime and serves only as a data source. When a chunk scrolls out of the screen it's reused at the other side with newly copied data. Data copying happens relatively rarely so it shouldn't be much of an issue.

Actually, you could easily script the tilemap on game load to generate the buffer zone automatically, just using get/set tile functions. So you wouldn't need to manually edit them (and also be more robust if you modify the level you don't have to worry about modifying all the duplicate areas as well). This seems like the optimal solution.

But @xyz 's idea would be more optimized for performance if your level is large.

a year later