Instantly rotating and changing an object's velocity relative to another (probably quaternion mistake!)

Hi,

I have a player walking down a corridor A and at a certain point they are teleported into a visually-identical corridor B, however corridor B is at a different orientation than corridor A. The idea is that this should be seamless: the player has no awareness that the teleportation has occurred.

At the end of each corridor is a “keyhole” object that has been instantiated from a prefab. The intended plan is to:

  1. compute player’s location in keyhole A’s local space, change player’s location to have the same location in keyhole B’s local space.
  2. do the same for player’s rotation.
  3. compute the angle between keyhole A and keyhole B’s rotations, then use this to modify the player’s current velocity.

I think if I do 1, 2 and 3 properly then everything should appear seamless as desired.

I’ve got 1 working, I thought I had 2 but the rotation now seems to “jump”, and the velocity part definitely isn’t working. I’m 90% sure that I’ve got the basic way of solving each of these problems done in a nice Unity-friendly manner, but I’ve got two elements in the wrong order or something like that.

Here’s my code, using my terminology above keyhole A is teleportKeyhole below, and keyhole B is newKeyhole. Any help with this is much appreciated.

					Vector3 playerFromKeyholePos = gameObject.transform.InverseTransformPoint(player.transform.position);
			Quaternion playerFromKeyholeRot = Quaternion.FromToRotation(player.transform.forward, gameObject.transform.forward);
			Quaternion newKeyholeFromTeleportKeyholeRot = Quaternion.FromToRotation (gameObject.transform.forward, newKeyhole.transform.forward);
			float newKeyholeFromTeleportKeyholeAngle = Vector3.Angle(gameObject.transform.rotation.eulerAngles,newKeyhole.transform.rotation.eulerAngles);
			player.transform.position = newKeyhole.transform.TransformPoint(playerFromKeyholePos);
			player.transform.rotation = Quaternion.Inverse(player.transform.rotation) * playerFromKeyholeRot * newKeyholeFromTeleportKeyholeRot;
			player.GetComponent<Rigidbody>().velocity = Quaternion.Euler(0, newKeyholeFromTeleportKeyholeAngle,0) * player.GetComponent<Rigidbody>().velocity;
		}

OK, I realized that I had completely misread two other Unity Answers posts when writing the above code. I’ve fixed the problem, using the far simpler code below. Sorry for any confusion.

Vector3 playerFromTeleportKeyholePos = gameObject.transform.InverseTransformPoint(player.transform.position);
Quaternion newKeyholeFromTeleportKeyholeRot = Quaternion.FromToRotation (newKeyhole.transform.forward,gameObject.transform.forward);
Vector3 playerFromTeleportKeyholeVelocity = gameObject.transform.InverseTransformDirection(player.GetComponent<Rigidbody>().velocity);
player.transform.position = newKeyhole.transform.TransformPoint(playerFromTeleportKeyholePos);
player.transform.rotation = Quaternion.Inverse(newKeyholeFromTeleportKeyholeRot) * player.transform.rotation;
player.GetComponent<Rigidbody>().velocity = newKeyhole.transform.TransformDirection(playerFromTeleportKeyholeVelocity);