Back Ground

Unity - Mathf.Cos(), Mathf.Sin() 시야함수 만들기 본문

Unity/3D

Unity - Mathf.Cos(), Mathf.Sin() 시야함수 만들기

Back 2021. 7. 25. 16:56

 

위 큐브가 적이라고 치고 시선을 보고있는 방향을 구현하였다.

이렇게만 보면 뭔지 이해를 못할 것 같아서 현재 서비스운영중인 게임을 보자면,

 

[가디언 테일즈]게임에서 인베이더(적)들이 보는 탐색거리를 표현한것이다.

 

만들기 전에 삼각함수 공식에 대해서 먼저 설명하도록 하겠다.

(삼각함수 공식을 이용하여 코드로 작성해야하기 때문)

 

[삼각함수] ▼

더보기

삼각함수


각의 크기를 삼각비로 나타내는 함수이다.

삼각함수에는 3개의 기본적인 함수가 있으며,
사인(sin), 코사인(cos), 탄젠트(tan)가 있다.


Sin 사인, Cos 코사인,Tan 탄젠트

[쉽게 외우는 방법]






호도법 



60분법은 
우리가 평소 각도(Degree)를 말할때 쓰는 방식으로 
1도 ~ 360도를 말한다.
원의 벌어진 정도의 단위를 말하지 길이는 아니다.


호도법(radian measure)이란 
 각도를 길이로 표현 하는 방법이다 즉,
 라디안을 단위로 하여 중심각을 재는 방법


[라디안]


호의 길이가 반지름과 같게 되는 만큼의 각을 1 라디안이라고 정의한다.
라디안은 절대적인 각도이며 실제 1 라이안은 57.3도에 해당하는 값이다.
라디안의 표기는 rad라고 한다.

반지름과 호의 길이가 동일한 상태를 1 라디안이라고 부른다.
[여기서 r은 반지름을 뜻한다.]








그런 식으로 늘어나게 되면 1 ~ 2 ~ 3 ~... 라디안이 된다.
그런데 반원이 되기에
3 라디안에서 약 0.147592.. 정도가 모자라게 되는데


원지름에 대한 길이의 비율 값을 3.14159265358979.. 가 되는데
이걸 파이(π, pi)라고 한다.














즉, 반원의 라디안은 파이 라디안이 된다 (원지름이 파이이기 때문)


 Gif설명




 정리된 그림


[이미지 출처 : https://giverboy.tistory.com/42]




π = 3.14159265358979...
: 180º

반원 = πr (π: 파이 *  r 반지름 )  [즉 180도 * 반지름으로 반원을 그린다고 생각하면 쉽다)
원주율 =  2πr








세타(theta)

Θ 각도를 나타내는말 (x,y축 기준으로 양수음수로 나타낸다)

 

 

코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Vector3[] CalualteSightPoint(float radius, float angle)
{
    Vector3[] results = new Vector3[2];
 
    // 우측 끝 점의 좌표를 구한다.
    float theta = 90 - angle - transform.eulerAngles.y;
    float posX = Mathf.Cos(theta * Mathf.Deg2Rad) * radius;
    float posY = transform.position.y;
    float posZ = Mathf.Sin(theta * Mathf.Deg2Rad) * radius;
    results[0= new Vector3(posX, posY, posZ);
 
    // 좌측 끝 점의 좌표를 구한다.
    theta = 90 + angle - transform.eulerAngles.y;
    posX = Mathf.Cos(theta * Mathf.Deg2Rad) * radius;
    posY = transform.position.y;
    posZ = Mathf.Sin(theta * Mathf.Deg2Rad) * radius;
    results[1= new Vector3(posX, posY, posZ);
 
     return results;
}
cs

 

코드를 설명하기전 만들고자 하는 부분이 어디인지 설명 하자면

오른쪽 각도선를 먼저 설명할 것이다.

 

적당히 CalualteSightPoint라는 이름의 시선점 계산해주는 함수 정의 한 후

 

 

Mathf.Cos() 코사인 함수를 이용하여 길이를 구해준다.

 

1
2
float theta = 90 - angle;
float posX = Mathf.Cos(theta * Mathf.Deg2Rad) * radius;
cs

 

 

theta각도를 구해준다.  90에서 뺀 이유는 

적이 기준에서 x측이 0이기 때문에  /(오른쪽 대각선)을 구하기위해서 90기준에서

우리가 지정할 각도(매개변수 angle)를 빼준 것이다.

 

Mathf.Deg2RadDegree(60분법 각도)에서 Radian(호의 길이)로 변경해준다.

 

 

밑변의 길이를 구해주기 위한 처리

 Mathf.Cos(theta * Mathf.Deg2Rad) * radius;
밑변 = cos(angle) * 빗면

그럼 이제 Z의 값도 구해준다. 

 

 

(Y가 아니라 왜 Z??)



유니티에서 보면 쉽게 알 수 있는데 
forward방향 Z가 되므로, X와 Z를 구해야 한다.

 Z축 

1
float posZ = Mathf.Sin(theta * Mathf.Deg2Rad) * radius;
cs
 Mathf.Sin(theta * Mathf.Deg2Rad) * radius;
높이 = sin(angle) * 빗면

 

 

1
results[0= new Vector3(posX, posY, posZ);
cs

Vector3를 통해서 (x위치 , y위치(본인 값), z위치)에 맞춰서 넣어주게 되면

위 그림의 현재 각도에 맞춰서 나타나게 된다.

(흰 선은 기즈모를 활용하여 시각화 했을뿐 이 코드만으로 저렇게 나오지 않는다.)

 

 

이와 같은 방식으로 좌측도 만들면 된다.

1
2
3
4
5
6
    // 좌측 끝 점의 좌표를 구한다.
    theta = 90 + angle - transform.eulerAngles.y; // 90도를 넘을 것이기 때문에 + 처리
    posX = Mathf.Cos(theta * Mathf.Deg2Rad) * radius; //x 위치
    posY = transform.position.y; //현재 큐브에 script를 추가했기 때문에 자기 자신의 y값 
    posZ = Mathf.Sin(theta * Mathf.Deg2Rad) * radius; //z 위치 
    results[1= new Vector3(posX, posY, posZ);
cs

 

 

다음으로는 기즈모를 그려보겠다.

 

[ 기즈모 그리는 함수 ] 

https://backback.tistory.com/manage/posts/

 

TISTORY

나를 표현하는 블로그를 만들어보세요.

www.tistory.com

 

 

기즈모 선그리기

1
2
3
4
5
6
7
8
9
10
11
12
void OnDrawGizmos()
{
    Gizmos.color = Color.white;
    
    // 시야 범위의 양쪽 끝 지점을 구한다.
    Vector3[] sightPos = CalculateSightPoint(sightDistance, sightDegree);
 
    for(int i=0; i < sightPos.Length; i++)
    {
        Gizmos.DrawLine(transform.position, transform.position + sightPos[i]);
    }
}
cs

 

 

코드 설명

기즈모를 하얀색으로 지정해주었다.

Gizmos.color = Color.white; 

 

 

기즈모의 그려질 각 끝점을 구한다.

1
Vector3[] sightPos = CalculateSightPoint(sightDistance, sightDegree);
cs

각도계산하는 함수로 원하는 각도를 통해서 거리와 각도를 구한다.

현재는 전역변수

float sightDistance = 10;

float sightDegree = 30;

로 지정하였다. 

 

기즈모의 선을 그린다.

1
Gizmos.DrawLine(transform.position, transform.position + sightPos[i]);
cs

DrawLine의 시작지점 (transform.position) ~ 끝지점 transform.position + sightPos[0]; 을 지정해줬는데

- 시작지점이 현재 script가 있는 큐브에서 부터 시작하므로 transform.position으로 지정

- 끝지점은 위에서 구한 sightPos의 각도를 구한 지점인데

   현재 큐브에서 부터 각도가 나와야 하기때문에 transform.position + sightPos로 지정해줬다.

 

 

'Unity > 3D' 카테고리의 다른 글

Unity - OnDrawGizmos 기즈모 그리기  (0) 2021.07.27
Comments