Portals?
A portal is a gateway to another place, however, in our game its often the place you just came from. Its a teleportation device, you walk though it and end up somwhere completely different.
In our game we wanted to make areas that would go around and around in a circle, but only in one direction. Teleportation was the obvious answer, but to make this a seamless experience for the player we needed a way to teleport them without them noticing.
Teleportation
Teleportation seemed quite straight forward. When an object collides with the portal collider, it finds the point of collision and teleports the object to the same relative position on the exit portal. In practice this proved quite frustrating, and required several iterations and rethinks. In our case we were using physics, navmeshes and custom controllers to move things around, this meant that the portal system had to make allowances for each of them. All objects also had to be rotated to be facing the correct direction relative to the exit.
In the case of navmesh agents, they needed to have Warp()
called on them, RigidBody
objects had to have the velocities rotated as well so they continued to move the intended direction. This was finally all worked out and I eventually settled on Matrix TRS (transform/rotation/scale) solution, with specific allowances for the above.
Render textures
In order to keep the player in the dark, I used a 2nd camera, a render texture. The 2nd camera is tied to the exit portal, and changes its position based on where the main camera is relative to the entry portal. The 2nd camera then sends its output to a rendertexture on the entry portal surface.
In the example below, every doorway is a portal in an L shaped room:
Issues
A camera looking at a rendertexture is not much of a problem, but when you have a large chain, or a portal that can see its self from the exit, then we have a problem with render order. To address this, rather than over engineering a solution, we made sure to not have this occur by using careful placement.
Instantaneous transport back through another portal (when used as a bi-directional door) was a problem, so I added a portal lockout item that stops it from working until you exit the collider on the exit side (usually 2-3 frames).