(Edit: Adjusted the question to clarify it, based on helpful feedback below)
Hi there,
I’m working on a 3D game. The world is a flat square world. I want it so that when the player flies north, they will appear on the south side of the map; when they fly too far south they will appear on the north. And the same situation for east/west.
For example, when the player flies directly east, she reappears on the west side of the map, at the same north/south position.
The world will be roughly 5000 metres by 5000 metres. But sparsely populated, mostly by flying things.
Assume the game is single-player. Assume the game doesn’t need PhysX rigidbody collisions.
Ok, here’s my understanding of how to implement the wrapping world. When the player flies from one terrain to another, the terrains (and all their GameObjects) are moved from behind the player, to in front of the player:
…and probably, all the terrains should be moved so that #5 is always centred at Vector.zero – so that the floats representing position don’t grow too large.
This seems like a perfectly functional wrapping world to me.
So, now for my issue.
In my game, a fireball consists of two parts.
The round part is yellow and burning and pretty – when it collides with a dragon, the dragon takes damage.
The big schnoz in front of it doesn’t have a MeshRenderer; it’s invisible. It’s a trigger collider. Call it the FireballNotifier. It’s about 20 metres long. When it collides with a dragon, 2 things happen:
- The dragon realises there’s a fireball coming, and starts doing evasive maneuvers/counterattacks.
- The fireball starts homing in toward the dragon.
So basically, it’s just a way for both the fireball and the dragon to detect the case that: there’s a fireball getting really close to its target.
From a collision-detection perspective, the dragon is just a sphere. Maybe a 10 metre diameter.
So, suppose an NPC wizard is fighting a dragon, at the edge of the map. The wizard is on the eastern side of terrain #3; the dragon is on the western side of terrain #1.
If we assume the world is wrapped, then that wizard and dragon are about 50 metres away from one another – really close.
But in Unity engine, they’re really far apart – they’re on opposite sides of the world.
If the wizard shoots a fireball to the east, that fireball will wrap around to the other side of the world. It’s going to suddenly appear next to the dragon, who won’t have time to properly react. This is bad. (And just one example of AI/spell problems that will arise with this wrapping.)
So.
The solution as I understand it, and which seems to be the one both Fattie and Matt Downey are suggesting, is to make “shadow copies” of all the objects near the world boundary. So for example:
The white squares are the “real” world. The grey ones are a copy of the world.
Now, while the FireballNotifier doesn’t collide with the real dragon, it is colliding with the shadow copy of the dragon (which exists in the northeastern copy of terrain #1).
Each of the grey zones contains a copy of all the GameObjects within that terrain, or at least the ones closest to the north & west borders.
The shadow copies of GameObjects are dumb – they are simply objects that have the same collision shape as their source object, with no AI or behaviour other than to set their position 5000m to the east (or south, or southeast) of their source object in every FixedUpdate.
Any time a shadow object collides with a real object, the game simply reacts as though both the real objects collided. But shadow/shadow collisions will all be silently ignored.
These shadow copies will also help with a million other operations, especially in the AI. For example: when a wizard asks, “where is the nearest dragon relative to my current position?” – this will allow an answer to be generated.
Is this the solution being suggested?
It seems… like a lot of work. But probably effective.
When I started this project, I never would have guessed that world wrapping would be such a major issue… I’m still hoping that someone is going to call me an idiot and show me a much, much simpler solution
The old question is below, but probably obsolete now
Hi there,
I’m working on a 3D game that features a torus world – if you keep walking in one direction you’ll arrive back at the place you started at.
(Eventually I’ll change it to a spherical world, like Magic Carpet, but torus will be simpler while I’m sorting out issues like this one)
The game will feature multiplayer.
What are some ways to implement the torus 3D world?
Some ideas I’ve considered:
1: Create the world as a 5x5 grid of terrain objects, then whenever the player steps onto one terrain object, pick up all the other terrain objects and place them so that the player is always on the centre of the 5x5 grid.
Problems: This should work pretty well for terrains. But when it’s done for all the monsters in the world too, problems arise – two monsters on adjacent terrains will not necessarily be “near” each other. This causes AI and collision issues.
2: Make Portals at all the world boundaries; so that when the player moves near the northwestern corner of the world, they will be able to see a projection of the southeastern corner of the world – and they won’t realise it’s a projection. When they step into the projection they’ll be transported to the other side of the world.
Problems: Same as #1.
Should I make “copies” of the monsters when they move near terrain boundaries, and have the collision detection/AI routines detect those copies as though they were the real monsters? It seems messy and error-prone, but I’m not sure what other methods exist.