- Home /
How can I obtain the overall rotation of multiple selected gameobjects in the unity editor?
I am trying to align a torus to the rotation of a hexagon created by 6 separate tubes. Is there a way to do this in the editor? Any help would be greatly appreciated!
Answer by MarioSantoso · Apr 16, 2018 at 03:33 AM
Group the tubes (place the tubes as children under another gameobject). Then you can have the rotation of the hexagon.
@$$anonymous$$ilsnus Thank you, but when I try to do that, though the hexagon has a rotation of zero, if I set the torus rotation to zero, they are still not aligned. I am trying to get the torus to encompass the hexagon, while at the same time sharing its rotation. Is there a way to go about doing that within the unity editor? Thanks!
When you are building the hexagon with tubes, build them parallel to an axis. From your image, I think you already rotated the tubes before grouping them, thus why the rotation is already off.
Don't rotate the tubes before grouping them.
@$$anonymous$$ilsnus Thank you, but I am unable to do that because the tubes are part of a larger tubular structure, where each tube has precalculated rotation. Is there another way to accomplish this?
Answer by Bunny83 · Apr 19, 2018 at 02:37 AM
I'm not that familiar with that molecule ^^ however are you actually sure that this ring is actually "flat" (all bonds lie in the same plane)? If that's the case just take two bonds which are not parallel and calculate the cross product between the two direction vectors. This gives you the normal of your ring. If the bonds are not in the same plane but just close to a certain plane you can calculate the cross product between each neighboring bond pair which gives you 6 normals. Just take the arithmetic mean (add them up and renormalize) to get the average normal.
Once you have the normal you can use Quaternion.LookRotation(normal)
as rotation for your torus.
If you need more help you should provide more information on how you actually place those bonds and maybe show how each bond object is rotated (which axis of the bond object points along the bond?).
Thanks! How exactly would I do a cross product? The bonds and bond angles are calculated by putting the molecule in its lowest energy conformer. It is then imported into unity as an FBX, so the bonds are rotated automatically.
That means your ring is one single mesh? In your description you said there are 6 seperate tubes...
Well in the case you only have a single model you either have to use the same math used to calculate those angles or access the vertices of the mesh manually. However analysing the vertices can be tricly because if it's a single mesh you can not simply seperate the vertices for the 6 tubes.
Just to be more exact now, the following assumes your mesh only contains those 6 tubes. No other geometry must be part of the same mesh:
Since you imported the mesh as FBX you have to make sure you mark it as "readable" in the importer.
Depending on how the mesh got imported there will be either a $$anonymous$$eshFilter or a Skinned$$anonymous$$eshRenderer which has the mesh reference. So use GetComponent to get access to the right component and access the $$anonymous$$esh through it's shared$$anonymous$$esh property
Get the vertices array into a local array.
Find the local space center point of the mesh by calulating the arithmetic mean of all vertices. If your ring is actually centered around local 0,0,0 you can of course skip this step.
Create relative vectors from the center to each vertex. To be on the safe side we just calculate all possible combinations but ignore vertices which are too close together.
Once we have all normals we have to make sure they point in the same principal direction. A simple dot product helps to decide if we should flip the normal or not.
Finally just combine all the normals to get the average.
Something like this:
var mf = GetComponent<$$anonymous$$eshFilter>();
var mesh = mf.shared$$anonymous$$esh;
var verts = mesh.vertices;
// calculate center
Vector3 center = verts[0];
for(int i = 1; i < verts.Length; i++)
center += verts[i];
center /= verts.Length;
//get all normals
List<Vector3> normals = new List<Vector3>();
for(int i = 0; i < verts.Length-1; i++)
{
var dir = (verts[i] - center).normalized;
for(int n = i+1; n < verts.Length; n++)
{
var dir2 = (verts[n] - center).normalized;
if ($$anonymous$$athf.Abs(Vector3.Dot(dir, dir2)) < 0.88f)
{
normals .Add(Vector3.Cross(dir, dir2));
}
}
}
// unify and add up the normals
Vector3 refNormal = normals[i];
for(int i = 1; i < normals.Count; i++)
{
if (Vector3.Dot(refNormal, normals[i]) < 0)
refNormal -= normal[i];
else
refNormal += normal[i];
}
refNormal.Normalize();
var rotation = Quaternion.LookRotation(refNormal);
Note i've written this from scratch here on UnityAnswer without any syntax checks. So it may compile but it's meant as sort of pseudo code as example.