Search Unity

Resolved Position and Rotation relative to another set of objects

Discussion in 'Scripting' started by vraka000, Jul 14, 2020.

  1. vraka000


    Nov 7, 2019
    So, I'm trying to position an object's clone relative to a plane according to the original's position to another plane. However, I want the position and rotation of the cloned object to be behind the second plane:

    Where A is the original and B is the clone. The arrows represent the objects' transform.forward directions.

    I've been looking into unity's Matrix4x4 methods, and so far I've come up with:
    Code (CSharp):
    1. var m = plane2.transform.localToWorldMatrix * plane1.transform.worldToLocalMatrix * objectA.transform.localToWorldMatrix;
    3. Vector3 newPos = m.getColumn(3);
    5. Quaternion newRot = m.rotation;
    This places objectB exactly at objectA's location (in front and facing the second plane). However, I'm not sure how to get from here to what I want.

    Thanks for any help!
  2. WarmedxMints


    Feb 6, 2017
    It's late here so sorry if I misunderstood but I think you are trying to set object b to a position where it would be if plane 1 was a mirror so it is like a reflected position and rotation, is that correct? If so, Vector3 has a reflect method that will do the work for you.

    Code (CSharp):
    1. //Get relative position for Obj1 to Plane1
    2. var offset = plane1.transform.position - objA.transform.position;
    3. //Relect Position
    4. var newPos = plane1.transform.InverseTransformPoint(Vector3.Reflect(offset, plane1.transform.forward));
    5. //Calc rotation difference
    6. var rotation = objA.transform.rotation * Quaternion.Inverse(plane1.transform.rotation);
    7. //Move object 2 to relative relfeclted position
    8. objB.transform.position = plane2.transform.TransformPoint(newPos);
    9. //Add the rotation difference
    10. objB.transform.rotation = plane2.transform.rotation * rotation;
    This is untested but I think it will do what you want, maybe? :D
  3. vraka000


    Nov 7, 2019
    I was having trouble getting the position right with the reflect method, however I looked up the TransformPoint and InverseTransformPoint functions you used and got a solution!

    Code (CSharp):
    1. //First, get objectA's position relative to plane1 and find the same location and rotation relative to plane2
    2. var m = plane2.transform.localToWorldMatrix * plane1.transform.worldToLocalMatrix * objectA.transform.localToWorldMatrix;
    3. //If you want to keep the objects on the same side of their respective planes, you can just set objectB's position and rotation to m.getColumn(3) and m.rotation
    5. //To take the new position, I took first found the relative position in plane2's local space
    6. Vector3 localPos = plane2.transform.InverseTransformPoint(m.getColumn(3));
    7. //Flipped it across the center of the plane
    8. localPos = Vector3.Scale(localPos, new Vector3(-1f, -1f, -1f));
    9. //And brought it back into world space
    10. Vector3 newPos = linkedPortal.transform.TransformPoint(localPos);
    12. //Then I had to adjust the y position because the two planes may not be at the same y position
    13. float yoffset = plane1.transform.position.y - objectA.transform.position.y;
    14. newPos.y = plane2.transform.position.y - yoffset;
    16. //Finally, objectB is still facing the same direction as objectA, so rotation by 180 around the y axis
    17. Quaternion newRot = Quaternion.Euler(m.rotation.eulerAngles.x, m.rotation.eylerAngles.y + 180f, m.rotation.eulerAngles.z);
    19. objectB.transform.SetPositionAndRotation(newPos, newRot);
    Works great now, so thanks for the help!