void tryTeleport() { if (validTeleport) { // Call any events, fade screen, etc. BeforeTeleportFade(); Vector3 destination = TeleportDestination.position; Quaternion rotation = TeleportMarker.transform.rotation; // Override if we're looking at a teleport destination DestinationObject = _hitObject.GetComponent <TeleportDestination>(); if (DestinationObject != null) { destination = DestinationObject.DestinationTransform.position; if (DestinationObject.ForcePlayerRotation) { rotation = DestinationObject.DestinationTransform.rotation; } } StartCoroutine(doTeleport(destination, rotation, AllowTeleportRotation)); } // We teleported, so update this value for next raycast validTeleport = false; aimingTeleport = false; hideTeleport(); }
void calculateParabola() { validTeleport = false; bool isDestination = false; Vector3[] segments = new Vector3[SegmentCount]; segments[0] = teleportTransform.position; // Initial velocity Vector3 segVelocity = teleportTransform.forward * SimulationVelocity * Time.fixedUnscaledDeltaTime; _hitObject = null; for (int i = 1; i < SegmentCount; i++) { // Hit something, so assign all future segments to this segment if (_hitObject != null) { segments[i] = _hitVector; continue; } // Time it takes to traverse one segment of length segScale (careful if velocity is zero) float segTime = (segVelocity.sqrMagnitude != 0) ? SegmentScale / segVelocity.magnitude : 0; // Add velocity from gravity for this segment's timestep segVelocity = segVelocity + Physics.gravity * segTime; // Check to see if we're going to hit a physics object if (Physics.Raycast(segments[i - 1], segVelocity, out hit, SegmentScale, CollisionLayers)) { // remember who we hit _hitObject = hit.collider; // set next position to the position where we hit the physics object segments[i] = segments[i - 1] + segVelocity.normalized * hit.distance; // correct ending velocity, since we didn't actually travel an entire segment segVelocity = segVelocity - Physics.gravity * (SegmentScale - hit.distance) / segVelocity.magnitude; _hitAngle = Vector3.Angle(transform.up, hit.normal); // Align marker to hit normal TeleportMarker.transform.position = segments[i]; // hit.point; TeleportMarker.transform.rotation = Quaternion.FromToRotation(TeleportMarker.transform.up, hit.normal) * TeleportMarker.transform.rotation; // Snap to Teleport Destination DestinationObject = _hitObject.GetComponent <TeleportDestination>(); if (DestinationObject != null) { isDestination = true; TeleportMarker.transform.position = DestinationObject.transform.position; TeleportMarker.transform.rotation = DestinationObject.transform.rotation; } _hitVector = segments[i]; } // Nothing hit, continue line by settings next segment to the last else { segments[i] = segments[i - 1] + segVelocity * segTime; } } validTeleport = _hitObject != null; // Make sure teleport location is valid // Destination Targets ignore checks if (validTeleport && !isDestination) { // Angle too steep if (_hitAngle > MaxSlope) { validTeleport = false; } // Hit a grabbable object if (_hitObject.GetComponent <Grabbable>() != null) { validTeleport = false; } // Hit a restricted zone if (_hitObject.GetComponent <InvalidTeleportArea>() != null) { validTeleport = false; } // Something in the way via raycast if (!teleportClear()) { validTeleport = false; } } // Render the positions as a line TeleportLine.positionCount = SegmentCount; for (int i = 0; i < SegmentCount; i++) { TeleportLine.SetPosition(i, segments[i]); } if (!validTeleport) { _invalidFrames++; } else { _invalidFrames = 0; } }