정면에서 30도 왼쪽과 30도 오른쪽은 내적 값이 같습니다. 내적으로는 얼마나 정면에 가까운지 알 수 있지만, 어느 쪽으로 돌아야 하는지는 알 수 없습니다. 좌우 부호가 필요할 때 외적을 함께 씁니다.
이번 글은 시야각이 아니라 회전 방향과 면의 방향을 다룹니다. Unity에서 월드 +Y를 위, +Z를 앞, +X를 오른쪽으로 정한 상황부터 시작합니다.
인자 순서를 숫자로 고정하기
Vector3 forward = Vector3.forward;
Vector3 toRight = Vector3.right;
float side = Vector3.Dot(Vector3.up, Vector3.Cross(forward, toRight));
Debug.Log(side);
이 입력의 기대값은 +1입니다. 목표를 왼쪽인 (-1,0,0)으로 바꾸면 -1, 정면이나 후면으로 바꾸면 0입니다. “양수면 오른쪽”이라는 규칙은 이 축 배치와 인자 순서에 대한 규칙입니다. 외적의 두 인자를 뒤집으면 부호도 뒤집힙니다.
3D 캐릭터가 벽을 타거나 기울어진 지면 위에 있다면 월드 up을 그대로 쓰는 것이 맞는지 다시 봐야 합니다. 캐릭터가 사용하는 기준 up에 수직인 평면으로 방향을 투영한 뒤 판정할 수 있습니다.
Vector3 planarForward = Vector3.ProjectOnPlane(actor.forward, actor.up);
Vector3 planarTarget = Vector3.ProjectOnPlane(target.position - actor.position, actor.up);
float side = Vector3.Dot(actor.up, Vector3.Cross(planarForward, planarTarget));
actor와 target은 Transform 참조입니다. 이 값은 각도가 아닙니다. 벡터 길이에 영향을 받기 때문에 부호만 사용하거나, 정규화 후 별도 임계값을 설계해야 합니다.
정반대 방향에서는 어느 쪽으로 돌까
외적이 0이라는 것은 왼쪽도 오른쪽도 아니라는 뜻만은 아닙니다. 정면, 정반대, 길이 0인 입력이 모두 가능합니다. 내적을 함께 보면 앞과 뒤를 나눌 수 있지만 정확히 180도 뒤의 목표로 어느 쪽을 택할지는 여전히 게임 규칙입니다.
직전 회전 방향을 유지하거나 항상 오른쪽으로 도는 방식처럼 정책을 정하세요. 작은 부호 변화만 따라가면 뒤에 있는 대상을 향해 좌우로 떨 수 있습니다. 일정 각속도로 돌아야 한다면 방향 부호를 직접 누적하는 대신 Quaternion.RotateTowards를 쓰는 방법도 있습니다.
세 점으로 면적과 법선 계산하기
삼각형 꼭짓점이 A=(0,0,0), B=(2,0,0), C=(0,0,3)이라고 합시다.
Vector3 edgeAB = vertexB - vertexA;
Vector3 edgeAC = vertexC - vertexA;
Vector3 areaVector = Vector3.Cross(edgeAB, edgeAC);
float area = areaVector.magnitude * 0.5f;
Vector3 normal = areaVector.sqrMagnitude > 0.000001f
? areaVector.normalized
: Vector3.zero;
이 입력의 외적은 (0,-6,0), 삼각형 면적은 3, 법선은 아래 방향입니다. B와 C의 순서를 바꾸면 면적은 같고 법선만 반대가 됩니다. 메시의 정점 순서가 바뀌었을 때 면이 뒤집혀 보이는 문제와 연결되는 부분입니다.
세 점이 일직선이면 면적이 0이고 고유한 법선도 없습니다. 이때 임의의 법선을 반환하면 잘못된 메시 데이터를 숨기게 됩니다. 예제처럼 0을 반환하고 호출부에서 해당 삼각형을 건너뛰거나 오류로 기록하는 편이 원인을 찾기 쉽습니다.
시야 판정 글의 내적과 이 글의 외적을 합치면 방향의 크기와 부호를 나눠 생각할 수 있습니다.