Search Unity

Resolved Position and Rotation relative to another set of objects

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

  1. vraka000

    vraka000

    Joined:
    Nov 7, 2019
    Posts:
    2
    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;
    2.  
    3. Vector3 newPos = m.getColumn(3);
    4.  
    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

    WarmedxMints

    Joined:
    Feb 6, 2017
    Posts:
    1,035
    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

    vraka000

    Joined:
    Nov 7, 2019
    Posts:
    2
    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
    4.  
    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);
    11.  
    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;
    15.  
    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);
    18.  
    19. objectB.transform.SetPositionAndRotation(newPos, newRot);
    Works great now, so thanks for the help!