Pings disappearing when going through teleporters in a vehicle, analysis and fixes
Belgarel
Join Date: 2017-07-03 Member: 231570Members, Subnautica Developer
You've probably noticed that when you go through a teleporter in a vehicle that your pings disappear afterwards. I've debugged and fixed it. Instructions on how to fix it below.
Normally when you go through a teleporter without a vehicle, the PrecursorTeleporterCollider sees you collided with the teleporter surface and runs a BeginTeleportPlayer method on the teleporter (PrecursorTeleporter). This generates events TeleportEventStart and TeleportEventEnd which are listened to by every ping, and they enable/disable themselves on receiving them so they aren't on screen while the fancy teleport graphics are playing.
When you normally go through a teleporter with a vehicle (although if you barely brush against it this won't happen), your momentum causes the collider to see two collisions with the surface of the teleporter (I assume both the player and the vehicle collide). This results in the teleporter setting off two TeleportEventStart events before a TeleportEventEnd. The back-to-back TeleportEventStart events confuses PingInstance's StartTeleport handler and it overwrites the 'teleporterDisabledState' that it needed to be able to restore itself when the teleport ended. The pings thus become stuck disabled.
The way I fixed it was to have PrecursorTeleporter remember if it is in use and ignore attempts to run BeginTeleportPlayer if so, thus preventing that doubled start event. It's already almost setup for this as-is - 'warpObject' gets assigned when BeginTeleportPlayer starts but is never cleared. So, the first thing is to set warpObject to null at the end of SetWarpPosition so it's only assigned while in use, and the next is to check for warpObject != null in BeginTeleportPlayer and return if so. Those two changed lines will do the trick - a quick fix.
Videos before/after to demonstrate the bug and the fix. Note I have 3 pings so you'll see the events I mentioned coming from the teleporter and the StartTeleport/StopTeleport handlers on each ping. Note how the start events get doubled in the 'before' video:
before:
after:
Normally when you go through a teleporter without a vehicle, the PrecursorTeleporterCollider sees you collided with the teleporter surface and runs a BeginTeleportPlayer method on the teleporter (PrecursorTeleporter). This generates events TeleportEventStart and TeleportEventEnd which are listened to by every ping, and they enable/disable themselves on receiving them so they aren't on screen while the fancy teleport graphics are playing.
When you normally go through a teleporter with a vehicle (although if you barely brush against it this won't happen), your momentum causes the collider to see two collisions with the surface of the teleporter (I assume both the player and the vehicle collide). This results in the teleporter setting off two TeleportEventStart events before a TeleportEventEnd. The back-to-back TeleportEventStart events confuses PingInstance's StartTeleport handler and it overwrites the 'teleporterDisabledState' that it needed to be able to restore itself when the teleport ended. The pings thus become stuck disabled.
The way I fixed it was to have PrecursorTeleporter remember if it is in use and ignore attempts to run BeginTeleportPlayer if so, thus preventing that doubled start event. It's already almost setup for this as-is - 'warpObject' gets assigned when BeginTeleportPlayer starts but is never cleared. So, the first thing is to set warpObject to null at the end of SetWarpPosition so it's only assigned while in use, and the next is to check for warpObject != null in BeginTeleportPlayer and return if so. Those two changed lines will do the trick - a quick fix.
Videos before/after to demonstrate the bug and the fix. Note I have 3 pings so you'll see the events I mentioned coming from the teleporter and the StartTeleport/StopTeleport handlers on each ping. Note how the start events get doubled in the 'before' video:
before:
after: