- Home /
Rotate object so a specific axis faces another object, while also relative to the parent direction
I'm needing to rotate a specific axis (down, left, right etc) of object A towards object B's position, but relative to the rotation of a mutual parent/ancestor object, rather than to a world axis. This answer helped me solve the first part.
Vector3 direction = objB.position - objA.position;
Quaternion toRotation = Quaternion.FromToRotation(Vector.down, direction);
objA.rotation = toRotation;
Vector.down (negative y) will point at object B, except that the forward (z) axis will always point towards world forward (z). I have tried a lot of different things, but I haven't been able to crack it.
So how do I modify this to point the specific axis at the vector while keeping the forward (z) axis facing the forward axis of a shared parent/ancestor object? Thanks.
Do I need to do another rotation afterwards the FromToRotation that aligns the objects z with the ancestor z? This is mostly what I've been trying, but with my limited knowledge it seems to get very messy.
Or can I some how modify this FromToRotation method to achieve it?
Or is there another method I should be using that does this elegantly? Thanks
Okay, let's see if I have all of this in order:
You have a parent object (Let's call it Object C).
This parent has two children, Objects A and B.
A needs to be oriented so that its negative Y-axis is pointed at B, but then its alignment otherwise matches its parent, C?
Or, alternately, is the parent intended to take priority, so that A faces the same way as C, but then its Y-axis faces away from B as much as possible otherwise?
Beyond this, anyway, a "FromToRotation()" is intended to be multiplied by another Quaternion to apply a relative change. For instance:
objA.rotation = objA.rotation * toRotation;
... or maybe it's
objA.rotation = toRotation * objA.rotation;
ins$$anonymous$$d? I always forget which order a Quaternion's non-commutative order of operations is under various criteria.
A and B are the child of C yes, and A's y-axis will be pointing at B with the code I posted. A's Z-axis should then point at the Z-axis, not of C, but another ancestor object further up the hierarchy - the root if you will. C's rotation could be anything, but it can be disregard I think (unless using localRotation - which I tried also).
The code I showed perfectly rotates A's Y to point at B, but A's Z points at world Z and changes as the root rotates, so I'd like to point it to the root objects Z ins$$anonymous$$d. I think I need to do a rotation around the Y after the above code (as I can manually do that in the inspector to line it up), but I can't work out how to apply this correctly in code - 3d rotation does my head in.
I've seen an explanation of the "relative change" code you mention elsewhere and had tried it, but this makes A no longer point at B properly, and doesn't actually take the root objects rotation into account.
Thanks for your time.
Answer by Eno-Khaon · Dec 06, 2015 at 10:11 PM
Well, if you need to base it on the rotation of a base object higher up (or at the top?) of the hierarchy, you'll need information on that, since any given local rotation is relative only to its immediate parent.
For example:
// Returns the Transform at the very top of the hierarchy
Transform GetParent(Transform current)
{
Transform result = current;
if(current.parent != null)
{
result = GetParent(current.parent);
}
return result;
}
Otherwise, you'll need a stricter definition which would require tags, layers, manual definition or anything similar.
Now, for the resulting rotation, then, you'll want to do something along the lines of:
// This ensures that A's down points at B's position
Quaternion rotationOffset = Quaternion.AngleAxis(90.0f, Vector3.right);
// Point straight towards B with secondary emphasis on the root's forward vector
// Then, apply offset to align the downward axis instead
objA.rotation = Quaternion.LookRotation(objB.position - objA.position, objRoot.forward) * rotationOffset;
As an alternative, if facing forward is more important than downward facing towards B, implementation is a much simpler:
objA.rotation = Quaternion.LookRotation(objRoot.forward, objA.position - objB.position);
Thanks, this got me where I needed.
$$anonymous$$y objects class has a reference to it's root, so I was sorted there.
I found that it was -90 to point the down axis at B.
And then to point the left or right axis at B ins$$anonymous$$d, it was easiest to just add another AngleAxis rotation on the forward axis. Here's the full answer for my needs:
//A rotation to point A's down axis at B's position
Quaternion rotationOffset = Quaternion.AngleAxis(-90f, Vector3.right);
//Add an extra rotation if you need to point A's left or right axis at B ins$$anonymous$$d
if (axisToPoint == Vector3.left)
rotationOffset *= Quaternion.AngleAxis(90f, Vector3.forward);
else if (axisToPoint == Vector3.right)
rotationOffset *= Quaternion.AngleAxis(-90f, Vector3.forward);
Vector3 direction = objB.position - objA.position;
objA.rotation = Quaternion.LookRotation(direction, objRoot.forward) * rotationOffset;
It might be possible to combine the left/right axis rotation into the first axis rotation, but I couldn't work that out.
I also just realised that I could have used the code in my question, if I just aligned the root object with Quaternion.identity, did the child rotations, and then rotated the root back to where it was. This would only work if you weren't doing it at run time while the object was visible (which I'm not). This answer is more robust though.