/// <summary> Late update. </summary> public void LateUpdate() { // Grab the rotation amount. We do the inverse tilt so we calculate the rotation in // "natural up" space. Later we'll use the tilt to put it back into "anchor up" space. Quaternion invTilt = Anchor.up.FromToRotation(Vector3.up); // Yaw is simple as we can go 360 Quaternion yaw = Quaternion.AngleAxis(InputSource.GetCameraTwoAxis().x *degreesPerTick, invTilt * transform.up); // Pitch is more complicated since we can't go beyond the north/south pole float pitchAngle = Vector3.Angle(toCameraDirection, invTilt * Anchor.up); float pitchDelta = (invertPitch ? -1f : 1f) * InputSource.GetCameraTwoAxis().y; if (pitchAngle < minPitch && pitchDelta > 0f) { pitchDelta = 0f; } else if (pitchAngle > maxPitch && pitchDelta < 0f) { pitchDelta = 0f; } Quaternion pitch = Quaternion.AngleAxis(pitchDelta, invTilt * transform.right); // Calculate the new "natural up" direction toCameraDirection = pitch * yaw * toCameraDirection; // Update our tilt to match the anchor's tilt tilt = tilt.Up().FromToRotation(Anchor.up) * tilt; // Put the new direction relative to the anchor's tilt Vector3 tiltedTocameraDirection = tilt * toCameraDirection; if (tiltedTocameraDirection.IsApproximatelyVectorZero()) { tiltedTocameraDirection = -Anchor.forward; } // Calculate the new orbit center (anchor) and camera position transform.position = OffsettedAnchorPosition + tiltedTocameraDirection.normalized * radius; transform.rotation = Quaternion.LookRotation( OffsettedAnchorPosition - (OffsettedAnchorPosition + tiltedTocameraDirection.normalized * radius), Anchor.up); }