I’m working on a mechanism to control the position and rotation of an object around an anchorPoint relative to a controlPoint in 3D space. The object can have any initial rotation, necessitating the use of a rotational offset in order to maintain a relative alignment when the controlPoint is moved. Neither the control nor anchor points exist within the unity scene hierarchy as they’re stored as Vector3’s. The object however, utilizes unity’s Transform and may have one or more parent objects each with their own rotation.
The expected behavior is much like that of a local rotation gizmo where you click on the ring of the gizmo to set the rotation of the object.
I've tried without success to implement this using FromToRotation, LookRotation as rotations from identity as well as incremental rotations from the previous rotation state.
The below was the closest i got, however if the object or it's parent have a Z rotation upon calculating the offset, the object then rotates as expected but also includes an undesired roll around the look axis.
public Vector3 anchorPoint = Vector3.zero;
public Vector3 controlPoint = Vector3.left;
Quaternion rotationOffset = Quaternion.identity;
//Called when the object is "attached" to the anchor to store the difference between it's rotation and the directional vector from the control to the anchor
public void StoreOffset() {
//The unit vector pointing from the controlPoint to it's anchorPoint
Vector3 controlFwd = (anchorPoint - controlPoint).normalized;
//Generate a rotation using the direction vector while respecting the objects local up.
Quaternion lookRot = Quaternion.LookRotation(controlFwd, transform.up);
//Subtract the object's rotation from the lookRotation to determine the rotational offset between the two.
//Invert the offset rotation to save on calculations during update
rotationOffset = Quaternion.Inverse(Quaternion.Inverse(transform.rotation) * lookRot);
}
//Called any time the control point is moved to update the objects rotation
public void UpdateRotation() {
//The unit vector pointing from the controlPoint to it's anchorPoint
Vector3 controlFwd = (anchorPoint - controlPoint).normalized;
//Generate a rotation using the above direction vector while respecting the objects local up.
Quaternion lookRot = Quaternion.LookRotation(controlFwd, transform.up);
//Assign the new look rotation to the object then apply the offset rotation.
//ToLocalRotation is a Quaternion extension that converts rotations from world to local space
transform.localRotation = (lookRot * rotationOffset).ToLocalRotation(transform);
}
Example Animations
The first .gif shows the correct functionality so long as the parent object has no rotation.
The second .gif shows errant rotation if the parent has a Z rotation of 10°
controlPoint
is meant to do. Maybe walking through some examples could help. What is supposed to happen if control point is set to be some distance in front of the object, thenStoreOffset
is called, then the control point is set to be directly above the object,UpdateRotation
is called, then some time later, the control point is set so that it is on the opposite side of the object (at this point the back of the object) thenUpdateRotation
is called. How is the object supposed to be oriented afterUpdateRotation
is called each of those times? – RuzihmcontrolPoint
andanchorPoint
are in global space. Is that correct? – RuzihmUpdateRotation
, then the same direction from the control point's original position? or would the local up not change on the 2nd call? We can say the angle is actually only changing 89 degrees then 179 degrees and just speak approximately – Ruzihm