- Home /
Align Parent object using child object as point of reference
Hierarchy:
Game object 1 with child transform (empty gameobject as a child)
Game object 2 with child transform (empty gameobject as a child)
Goal: Align game object 2's position and rotation with the game object 1 transform. Game object 2 needs to be aligned via its child transform (empty game object with only a transform). Also want to end up with the same hierarchy as we started with as the final result.
Current Approach - hoping for more optimized solution or easier to read / shorter:
make child of game object 2 the 'parent' of game object 2 (it keeps its relative position this way)
move the now 'parent' to game object 2 to the destination game object 1 transform (via transform.position and rotation - easy enough)
make the game object 2 the 'parent' of its original child object transform
Obviously changing the parent / child several times gets old to type (i can make it a function yes) but it still seems slow / not required. Also consider that both game object 1 and 2 are child objects to yet another object in the scene (for both organization and movement). I tried Transform.Translate as it seemed to be the correct thing, but it didn't provide the correct results when testing, I could have just had something misplaced.
I can provide REAL code if required, this is a c# project but I can totally understand javascript, post whatever you feel is appropriate - THANKS!
Edit Image Attached Note that if half the rod is missing (as shown in the image) the overlap is visible in the objects i'm using, thus why i mention the visual issue (besides potential collider, center of mass and other physics issues)
I've read this twice and am not sure what you are looking for. A drawing showing the two objects (and their childeren) before and after alignment/positioning would be very helpful.
I'll try to get 2 images put together. In the mean time... I'd like to know of a more efficient way to move the 2nd object and align it to the first however I can't just use the 2nd objects direct transform. I need to use its child transform as its 'anchor' point. Basically I have game object 1 as a 'connector' with multiple 'points' (child game objects) and I have game object 2 which is a 'rod' that 'clicks' into the 'connector' slots. Its for a game where you can build your vehicle from the ground up. Basically think of lego's technic pieces or k'nex if you are familiar with them.
so i need to align the rod end into the connector slot. i don't want to make the center of the rod align to the connector slot (it looks wrong - as in the mesh are inside each other).
image uploaded and thank you so much for the response!
So the children are "plug-in here" mount points?
Idea is to start at the "target plug." You now know the position and rotation of your plug (will be rotated opposite of the target, since maybe plugs have +Z facing away.)
You then "walk backwards" from the plug to the parent using -localPosition and your plug's real rotation. That gives the parent position. You then adjust the parent rotation for the plug's localRotation (backwards.)
Just a few lines of pure math, but it hurt my head to try to work it out. Could create and move a dummy transform to use more built-ins. I'd keep the parenting tricks, if they are working, until you know they are too slow.
Valid points, i'll try to work something up with this.
To your point about performance. Yes it isn't slow yet but i'm only attaching two objects together. I'm concerned for later when the user is actually attaching multiple things back and forth, moving them, changing which objects the rods / connectors are 'connected' to, etc. Its going to be a vehicle / structure builder with the possibility of having a lot of little pieces making the whole on screen. I will run some tests with a few thousand pieces and see how long it takes to iterate through them and move them to connect to each other.
Answer by robertbu · May 20, 2013 at 05:31 PM
Here is a bit of code that does what I think you want:
// tr1P - Game Object 1 parent transform
// tr1c - Game Object 1 child transform
// tr2P - Game Object 2 parent transform
// tr2C - Game Object 2 child transform
void Alignment(Transform tr1P, Transform tr1C, Transform tr2P, Transform tr2C) {
Vector3 v1 = tr1P.position - tr1C.position;
Vector3 v2 = tr2C.position - tr2P.position;
tr1P.rotation = Quaternion.FromToRotation(v1, v2) * tr1P.rotation;
tr1P.position = tr2C.position + v2.normalized * v1.magnitude;
}
Note I cannot think of anything particularly wrong with the way you are currently doing it.
I think this assumes that, when connected, A, the connectors, and B are always in a straight line. In other words, every object's connector always faces directly away from the center of the object (which is the case in the picture.)
Think would need more math if, say, there was an off-center up-facing socket on the flat part of the disc (but a center-socket on the disc, should work fine.)
I haven't tested your proposed theory, but in my tests its working with my 'plug in here' game object transforms. because its all based on those positions / rotations. And size I keep z forward, it works fine for me. But I can see what you are getting at. I'll make sure I don't have a bug in the works!
No more math needed. Regardless of the relationship of the empty game object to the parent, this code will align the objects. There is a question of the relative rotation of the two visible object along the axes that connects them.
Note, if the socket is always forward, you can simplify the code just a bit. v1 would be -tr1.forward. v2 would be tr2.forward. You would still need the magnitude of v1, but you could calculate it or hard code it. Unless your are going to be doing a lot of these kinds of changes per frame, the simplifications are not necessary.
"...question of the relative rotation..." Yes. Typically, the rotation of a mount point is meant to affect the rotation of the connected object.
The child of the rod might be rotated 90 degrees (but not moved) to indicate it only connects to the disc like a "b" or a duck-foot (rotation of the disc mount point would say which one.)
Answer by EthanF4D · Oct 02, 2019 at 07:06 AM
The following do not need a source parent. and target, targetChild don't have to be direct parent/child. can be ancestor/descendant in the hierachy
public static void Align(Transform target, Transform targetChild, Transform source)
{
if (target && targetChild && source)
{
target.rotation = source.rotation * Quaternion.Inverse(Quaternion.Inverse(target.rotation) * targetChild.rotation);
target.position = source.position + (target.position - targetChild.position);
}
}
This thread helped me solve a problem that was plaguing me for ages - namely lining up coordinate systems of two different 3d tracking systems - thanks a lot! I used EthanF4D's method ultimately - see my reply to this question: https://answers.unity.com/questions/1493924/align-htc-vive-controller-with-optitrack-rigid-bod.html
Answer by ljdp · Sep 04, 2018 at 07:43 PM
I know this is an old question, but I came to a different solution. This also works well when tweening to position.
void Alignment(Transform t1P, Transform t1C, Transform t2) {
t1P.rotation = t2.rotation * Quaternion.Inverse(t1C.localRotation);
t1P.location = t2.position + (t1P.position - t1C.position);
}
You mean position ins$$anonymous$$d of "location" right? Or would it be localPosition?
Either way, didn't work here :/ perhaps because my t2 is scaled?
I'm sorry to revive this, but could you explain mathematically how you came to this solution? I'm stuck at how i would actually go about taking it into consideration myself, let alone write my own solution.
Your answer
Follow this Question
Related Questions
Moving a GameObject to a certain point in world space via script 1 Answer
Why is rotation offset 1 Answer
Setting a blocks rotation to predetermined values. 1 Answer
changing x multiplies x,y and z position for no reason 2 Answers
How to shift the player to a definite position in the x-axis using key presses? 1 Answer