void RecalculateOffset(bool isInsideLongTunnel) { if (isInsideLongTunnel) { //player is inside the long tunnel, so //cameras of the short tunnel must work normally shortS.offset = Vector3.zero; shortN.offset = Vector3.zero; } else { /* * player is outside the long tunnel, (maybe in the area of the short tunnel, looking through it) * so cameras of the short tunnel must work different. * * this is because... when player is looking THROUGH the short tunnel (but seeing the long one), there's this * explicit problem: the other side of the tunnel is not "playing" in the back panel of the long tunnel, * because player is not in the long tunnel, so I have to fake as he was inside, so the short-tunnel cameras * take the back of the short-side and not elsewhere * * Normally, the camera in the other side mimics the player's movement but in the OTHER side. * But, in this particular case, player and the "other" camera are in the SAME side: they're both in the * short-tunnel side, but acting as if player were inside the long tunnel (in the other side) * * This is the only time when I have to adjust the normal placement of cameras */ Vector3 longTunnelLongitude = longTunnelSouthPortal.position - longTunnelNorthPortal.position; Vector3 distShortSouth = playerCamera.position - shortTunnelSouthPortal.position; Vector3 oldPosition = shortTunnelNorthPortal.position + playerCamera.position - longTunnelNorthPortal.position; Vector3 newPosition = shortTunnelNorthPortal.position + longTunnelLongitude + distShortSouth; shortN.offset = newPosition - oldPosition; Vector3 distShortNorth = playerCamera.position - shortTunnelNorthPortal.position; oldPosition = shortTunnelSouthPortal.position + playerCamera.position - longTunnelSouthPortal.position; newPosition = shortTunnelSouthPortal.position - longTunnelLongitude + distShortNorth; shortS.offset = newPosition - oldPosition; } shortS.LateUpdate(); shortN.LateUpdate(); longS.LateUpdate(); longN.LateUpdate(); }
void Teleport(Transform objectToTeleport, bool forceTeleportAndNoEvent = false, bool entering = true) { if ((objectToTeleport.position - transform.position).magnitude > 5) { return; } //which side of the portal is the object? if (!forceTeleportAndNoEvent) { float dotProduct = Vector3.Dot(transform.up, objectToTeleport.position - transform.position); if ((entering && dotProduct < 0) || (!entering && dotProduct > 0)) { //wrong side. Don't teleport. teleportPlayerOnExit = false; return; } } //good side, continue // Teleport the object if (otherScript != null) { otherScript.teleportPlayerOnExit = true; } Vector3 oldPosition = objectToTeleport.position; Vector3 rbOffset = Vector3.zero; Rigidbody rb = objectToTeleport.GetComponent <Rigidbody>(); if (rb != null) { rbOffset = rb.position - transform.position; } //position objectToTeleport.position = reciever.parent.TransformPoint( transform.parent.InverseTransformPoint(objectToTeleport.position) ); //rotation Quaternion rot = reciever.parent.rotation * Quaternion.Inverse(transform.parent.rotation); Quaternion rot2 = rot * Quaternion.Inverse(objectToTeleport.rotation); objectToTeleport.Rotate( (objectToTeleport.CompareTag("Player") ? rot2 : rot).eulerAngles.x, rot.eulerAngles.y, (objectToTeleport.CompareTag("Player") ? rot2 : rot).eulerAngles.z ); //velocity (if object has rigidbody) if (rb != null) { rb.velocity = reciever.parent.TransformDirection( transform.parent.InverseTransformDirection(rb.velocity) ); rb.position = transform.position + rbOffset; //not entirely necessary } if (objectToTeleport.CompareTag("Player")) { //player has crossed. If using clones, may be necessary to swap clones and originals (see documentation) if (setup.clones.useClones && setup.clones.whichOneHasRb == portalSetup.WhichOneHasRb.playerSide) { int howManyOnTheOtherSide = otherScript.originals.Count; SwapSidesOfClonesOnThisSide(originals.Count); otherScript.SwapSidesOfClonesOnThisSide(howManyOnTheOtherSide); } //refresh camera position before rendering, in order to avoid flickering otherScript.cameraScript.LateUpdate(); cameraScript.LateUpdate(); /* * If you need to do something to your player when it's teleporting, this is when. * See online documentation about controller (pipasjourney.com/damianGonzalez/portals/#controller) * and how to adapt Unity's Rigidbody First Person Controller to skewed portals */ } //finally, fire event if (!forceTeleportAndNoEvent) { portalEvents.teleport?.Invoke(setup.groupId, transform.parent, reciever.parent, objectToTeleport, oldPosition, objectToTeleport.position); } }