Game Develop

[C++] -nan(ind)값에 관하여(NaN 오류) 본문

C++/C++

[C++] -nan(ind)값에 관하여(NaN 오류)

MaxLevel 2020. 9. 20. 03:54

 

-nan(ind)값을 발견하게 된 계기

                                                                                                                                                      

 

포트폴리오 작업도중 발견한 값이다.

몬스터의 범위 안에 플레이어가 있을 경우, 몬스터는 플레이어의 위치값(x,y)으로 계속 이동하기 때문에 결국 몬스터와 플레이어는 겹치게 되는데 몬스터와 플레이어가 겹쳐질경우 증발해버리는 현상이 발생했다.

원인을 찾기위해 해당 몬스터의 상태값들을 출력을 해봤더니 활성화는 멀쩡히 잘 되어있지만 객체의 Position값에서

-nan(ind) 라는 값이 출력되는걸 확인할 수 있었다. 

즉 몬스터 인스턴스는 멀쩡히 살아있지만 위치값이 이상하게 바뀌어버려서 어딘가로 날라가버린것이다.

 

 

 

 

-nan(ind)란?

                                                                                                                                                      

 

nan은 Not a Number의 약자로, 말 그대로 숫자가 아님을 의미한다.

좀 더 정확히 말하자면 자료형이 float이나 double형 등, 부동소수점값이 컴퓨터가 허용하는 값이 아닐 때 출력된다.

허용되지 않는 값으로는 분모에 0을 넣어서 계산을 한다던가, 루트 안에 음수값을 넣었을 때가 있다.

 

#include<cmath> 혹은 #include<math.h>를 하면 isnan이라는 함수를 사용할 수 있는데,

이 함수를 이용하여 매개변수의 값이 nan값인지 아닌지 체크할 수 있다.

 

아래는 실제 몬스터의 포지션값이 바뀌는 코드이다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
if (isDetectedPlayer)
    {
        SetAction(Walk);
 
        //if (GM->GetGunner()->pos == pos)
        //{
        //    pos.x -= 0.5f;
        //}
 
        Vector2 dir = (GM->GetGunner()->pos - pos).Normal();
        pos += dir * speed * DELTA;
 
 
        if (isnan(pos.x))
        {
            char buff[100];
            sprintf_s(buff, " isnan 함수 호출.\n");
            OutputDebugStringA(buff);
 
            isActive = false;
        }        
    }
cs

   - pos.x가 몬스터의 x좌표값인데, 이 값이 nan값일 경우 출력창에 "isnan 함수 호출"이란 스트링을 출력하게 해놨다.

 

 

 

 

 

 

 

실제로 몬스터가 사라진 후 출력값을 보면 x,y 값이 -nan(ind)값이 들어가있다.

 

 

Why?

                                                                                                                                                      

 

그렇다면 어째서 -nan(ind)값이 들어가게 됐을까?

위에 적어놨다시피 -nan(ind)값이 출력되는 경우는 분모에 0이 들어가거나 루트안에 음수값이 들어갈 경우이다.

내 케이스같은 경우는 분모값에 0이 들어가서 생긴 문제였다.

 

위의 스크립트에 있는 Normal이라는 함수를 봐보자.

       

     Vector2 dir = (GM->GetGunner()->pos - pos).Normal();

     

여기서 Normal함수는 몬스터의 위치를 기준으로 플레이어의 위치까지의 방향을 구하기위한 함수인데

자세한내용은 벡터의 개념까지 설명해야하기때문에 넘어가겠다.

 

결론적으로, Normal함수를 실행하게 될 경우 x/sqrt(x^2 + y^2) 라는 식을 계산하게 된다. 

   *sqrt 함수는 제곱근을 구하기위한 함수다.

분자의 x값은 어떤값이든 상관없기때문에 분모의 값을 살펴봐야 한다.

분모의 sqrt함수안의 x,y의 값은 각각 (몬스터의 x좌표 - 플레이어x좌표) , (몬스터의 y좌표 - 플레이어y좌표) 이다.

몬스터가 플레이어와의 좌표가 같아질경우 sqrt함수 안의 x,y 값은 각각 0,0이기 때문에 0^2 + 0^2 = 0이 되버린다.

즉, 분모에 0이 들어가게된다.

실제로 몬스터가 증발할때의 각 상태값들을 출력하면 플레이어와 몬스터의 위치가 소수점까지 같아질 경우 분모값은 0이되어 nan값을 출력한다.