본문 바로가기

유니티/프로젝트 최적화

[Unity] 스크립팅 최적화 (3) - 두 지점 사이 거리 비교

반응형

Vector3.Distance와 Vector3.SqrMagnitude

두 지점 사이의 거리를 측정하는 방법은 여러 방법이 있지만 그중 주의 깊게 살펴봐야 하는 Vector3.Distance와 Vector3.SqrMagnitude에 대해 비교하고자 한다.

 

우선 Vector3.Distance(a, b)는 두 지점 a와 b 사이의 거리를 반환한다.

반면 Vector3.SqrMagnitude(a, b)는 두 지점 a와 b사이의 거리의 제곱을 반환한다.

 

우리는 정확한 거리를 알려주는 Vector3.Distance를 사용하면 될까?


높은 비용의 제곱근 연산

문제는 Vector3.Distance가 제곱근 연산을 포함하고 있다는데에 있다.

두 지점 사이의 거리는 곱셈과 루트 연산이 들어가는데, CPU는 곱셈에는 강하지만 제곱근에는 약하다.

따라서 경우에 따라서 CPU오버헤드를 일으킬 수도 있게된다.

 

더군다나 유니티에서는 정확한 거리를 계산해야 하는 경우가 드물다.

대부분 두 지점 사이의 거리를 비교하는 연산이 필요할 뿐이다.

 

따라서 다음과 같은 연산은

float threshold = 10f;
if (threshold < Vector3.Distance(transform.position, target.transform.position))
{
    //Do something
}

 

아래와 거의 같다.

float sqrThreshold = threshold * threshold;

if (sqrThreshold < Vector3.SqrMagnitude(transform.position - target.transform.position))
{
    //Do something
}

 

여기서 거의 같다고 한 이유는 둘 사이의 소수점 정확도가 서로 다르기 때문이다. (Distance가 더 높은 소수점 정확도를 보인다.)

 

따라서 시뮬레이션과 같은 정확한 거리 계산이 필요한 경우가 아니라면 SqrMagnitude를 사용하는 것이 CPU입장에서 비용이 적게 든다.


프로파일링을 통한 비교

실제로는 얼마나 차이가 나는지 비교해 보면 다음과 같다.

 

아래는 각 케이스에 따라 1000만 번 실행하고 걸리는 시간을 측정하는 소스코드이다.

void Update()
{
    if (Input.GetKeyDown(KeyCode.Alpha1))
    {
        for (int i = 0; i < 10000000; i++)
            Vector3.Distance(transform.position, target.transform.position);
    }

    if (Input.GetKeyDown(KeyCode.Alpha2))
    {
        for (int i = 0; i < 10000000; i++)
            Vector3.SqrMagnitude(transform.position - target.transform.position);
    }
}

 

먼저 1번을 눌러 Distance를 측정하면 2189ms가 걸린다.

2189ms

반면 2번을 눌러 SqrMagnitude를 측정하면 2114ms가 걸린다.

2114ms

SqrMagnitude를 사용한 비교가 Distance 대비 4% 정도의 비용절감 효과가 측정되었다.

(여러 번 측정한 결과 3.5%~6%까지 나타났다.)

 

따라서 높은 정밀도를 요구하는 상황이 아니라면 SqrMagnitude를 통한 거리 비교를 하도록 하자.

반응형