Rotating a parent object so that child is at the closest possible position to another object

Hi there,

I have spent the last 4 hours trying to resolve this however I cannot seem to be able to get this to work, so I thought that I would raise this on the forum.

Basically I am working on a random dungeon generator. in this generator we have prefab rooms blocks. each prefab room block have an empty gameobject which is a child of the room prefab, this empty node is used to denominate the fact that a door will be there. (see screen shot a)

Now I am generating rooms positions from -200 to 200 in the x and z axis and am trying to force the rooms prefabs to assign themselves a rotation so that the child object will be at the shortest possible distance to the nominated centre (in this case (0,0,0).
(i.e the child points towards the centre)

(note that the objects are prefabs and have not been initializes at this point)

Now I was experimenting with the concept that since I know the absolute positions of the three vectors then I can derive the relative angle between the parent → child and the parent → centre. (See screenshot B green label)

However it seems to produce 3 rotation outcome.

  1. it produces the correct angle and orientation
  2. it produces the 180 - angle to what I need.
  3. or it produces a negative angle to what I need.

So this shows that the formula is working. However I am starting to think that there might be an alot easier method for this that I have missed.

If anyone’s got any advice or suggestion to resolve this then that would be most appreciated!

alt text

alt text

alt text

****************Code***************

note:
position = the parent's real world position
selectedExit.transform.position = is the local position of the exit point that needs to be orientated.
new vector3(0,0,0) is the world centre that I want all pieces to orientate towards.


var rotate = AngleSigned(position + selectedExit.transform.position, new Vector3(0, 0, 0), position);

           
var rotation = new Vector3(0,rotate,0);


var room = new InstantiatedRoom(RandomRoomPrefab, position, rotation);
            //go and create a new object we will use it to decide if we are really going to create it as a gameobject later on.

public static float AngleSigned(Vector3 v1, Vector3 v2, Vector3 n)
    {
        double a;
        double b;
        double c;
        c= (v1 - v2).magnitude;
        b = (v2 - n).magnitude;
        a = (v1 - n).magnitude;
        double temp1;
    
        double top = (((a*a)+ (b*b))-(c*c));

        double bottom = (2 * a*b );      
     
        double temp = (Math.Acos(top/bottom))*Mathf.Rad2Deg;

        return (float)temp;
            
    }

Let me start by saying, that IMHO, the best solution would be to put the door in the front (positive ‘z’ side) of every prefab. Then you can just do:

transform.LookAt(Vector3.zero);

And then everything is done. But that may not work for your situation, so my next suggestion is to do the rotation this way:

Vector3 direction = selectedExit.transform.position - position;
rotation = Quaternion.FromToRotation(direction, -position);

Note the use of ‘-position’ in the FromToRotation() works because you are using Vector3.zero as the target position. Also I’m assuming the prefab has (0,0,0) rotation. If the prefab has a rotation, then you will need to do:

rotation = Quaternion.FromToRotation(direction, -position) * prefabRotation;