Hello, I’m struggling with getting the correct rotation of an object moving along a spline. I want the object to rotate along a spline but with a rotation offset that is the difference in rotation between the first spline tangent and the initial transform.forward of the object. The object is kinematic.
It works perfectly fine as long as the object rotation is around Vector3.up, but if it’s around any other axis (instead of, or in addition to Vector3.up), it starts doing weird things.
Here’s the code :
private void Awake() {
RB = GetComponent<Rigidbody>();
RB.useGravity = false;
// These 2 are just to get the spline information (positions and tangents)
spline.ParametrizeSpline();
CreateSplineObjData();
initRotation = Quaternion.FromToRotation(data.tangents[0].Flatten(), transform.forward);
}
private void FixedUpdate() {
SetOrientationAndVelocity();
}
private void SetOrientationAndVelocity() {
// Index of the closest position on spline
int i = GetIndex();
int posIndex = i + 1;
Quaternion targetRotation = initRotation * Quaternion.LookRotation(data.tangents[i].Flatten()); // Flatten is a little helper that just gets the normalized projected Vector onto a plane that has Vector3.up as "up"
RB.MoveRotation(Quaternion.Slerp(RB.rotation, targetRotation, lerpSpeed));
Vector3 targetVelocity = data.tangents[i] * lerpSpeed;
Vector3 targetPosition = RB.position + targetVelocity;
RB.MovePosition(targetPosition);
}
Pretty sure your use of Flatten in both cases is why it only works for upright objects. You’re considering the tangent as projected on the X Z plane, not the actual tangent.
Instead of using the 1-argument LookRotation(), you definitely should use the two-argument form with the spline-follower’s transform.up to allow for the follower to lean in the curves or hills.
Instead of using Quaternion.FromToRotation(), you should be able to calculate the desired additional rotation as the inverse of its original rotation relative to the tangent-facing 2-argument LookRotation(). Then you can apply it with multiplication as you already do.
Thing is, I actually don’t want the object to completely rotate following the tangent, I want it to be able to rotate in space around Vector3.up only in the end. This is why the Flatten is here.
I mean that, regardless of the orientation of the object initially, or the spline, the object should only ever rotate around the global Vector3.up in the end.