Search code examples
c#unity-game-enginevectorpositionangle

Unity3d: Position a gameobject such that its forms a right angled triangle with other two gameobjects


enter image description here

How do I position C gameObject such that it forms a right angled triangle with A and B. I tried to use (B.transform.position.x,A.transform.position.z) but it still gives me something which is close to A (it takes it globally). I want the C to be along the local red axis of A and local green axis of B as seen in the picture. What do I do?


Solution

  • There's a few ways of expressing this problem.


    One is finding such a point along B's up axis such that it makes a right angle with A. This would ignore any rotations of A.

    To do this, project A's position along B's up. In other words, find the dot product of (A-B) and B's up, multiply that by B's up, and add that to B.

    Vector3 cPos = B.transform.position + Vector3.Dot(A.transform.position - B.transform.position, B.transform.up) * B.transform.up;
    C.transform.position = cPos;
    

    Another way would be finding the intersection point of B's up and A's right. This would possibly make non right angles or maybe no point at all depending on the rotations of A and B.

    This is a bit more complicated, and the link in the comments has a good implementation:

    public static bool LineLineIntersection(out Vector3 intersection, Vector3 linePoint1, Vector3 lineVec1, Vector3 linePoint2, Vector3 lineVec2){
    
          Vector3 lineVec3 = linePoint2 - linePoint1;
          Vector3 crossVec1and2 = Vector3.Cross(lineVec1, lineVec2);
          Vector3 crossVec3and2 = Vector3.Cross(lineVec3, lineVec2);
    
          float planarFactor = Vector3.Dot(lineVec3, crossVec1and2);
    
          //is coplanar, and not parrallel
          if(Mathf.Abs(planarFactor) < 0.0001f && crossVec1and2.sqrMagnitude > 0.0001f)
          {
              float s = Vector3.Dot(crossVec3and2, crossVec1and2) / crossVec1and2.sqrMagnitude;
              intersection = linePoint1 + (lineVec1 * s);
              return true;
          }
          else
          {
              intersection = Vector3.zero;
              return false;
          }
      }
    

    Then to find your position:

    Vector3 cPos;
    bool doIntersect = LineLineIntersection(out cPos, A.transform.position, A.transform.right, B.transform.position, B.transform.up);
    if (doIntersect) {
        C.transform.position = cPos;
    } else {
        // do something reasonable, like using projection, or not changing the position
        Vector3 cPos = B.transform.position + Vector3.Dot(A.transform.position - B.transform.position, B.transform.up) * B.transform.up;
        C.transform.position = cPos;
    }