Parent Rotation to Get Target Child Rotation

Assuming that I have a parent transform that is a parent to a child transform (not necessarily a direct parent though, could be several levels between parent and child), I need a function to calculate the proper world rotation of the parent transform in order to achieve a specific target world rotation of the child transform.

So, this would look something like…

// Should return the correct value for parent.rotation such 
// that child.rotation equals targetChildRotation
// (assuming that parent is a direct or indirect parent of child)
public static Quaternion CalculateParentRotation(Transform parent, Transform child, Quaternion targetChildRotation) {
    // What goes here?
}

Probably a simple problem but the answer is escaping me. What does this function look like?

Turns out to be just basic matrix math – here is the solution…

C = P * R

where C is child, P is parent, and R is relative rotation between parent and child then you can solve for P or R as follows…

P = C * Quaternion.Inverse(R)

R = Quaternion.Inverse(P) * C

You must find the children rotation relative to the root object at Start: “divide” the children rotation by the root rotation. If you find the target rotation somehow (with LookRotation or FromToRotation, for instance), you can just “divide” it by the relative rotation:

Quaternion relRot;
public Transform rootObj;

void Start(){
  relRot = Quaternion.Inverse(rootObj.rotation) * transform.rotation;
}

void AlignParent(Quaternion targetChildRot){
  rootObj.rotation = Quaternion.Inverse(relRot) * targetChildRot;
}

Maybe the “division” order is reversed (should it be Inverse * rotation?) - I can’t test this right now, but will do it soon and edit the question if there’s any error.

EDITED: In fact, the order was reversed - it’s fixed now. Alternatively, it’s possible to avoid one Inverse operation if relRot is calculated in the reverse order, because this would be the result of rootObj.rotation/transform.rotation:

Quaternion relRot;
public Transform rootObj;

void Start(){
  relRot = transform.rotation * Quaternion.Inverse(rootObj.rotation);
}

void AlignParent(Quaternion targetChildRot){
  rootObj.rotation = relRot * targetChildRot;
}