공부중

[project_PQ]-[Unity3D] 임의의 원 범위 안에서 스폰하기. 본문

Project/project_PQ

[project_PQ]-[Unity3D] 임의의 원 범위 안에서 스폰하기.

곤란 2018. 9. 3. 16:25
반응형

일단 위의 스크린샷은 내가 멍청하게도 Collision충돌로 알아서 밀어내겠지 하고 안일한 생각을 가지다가 

is Trigger를 체크한것을 잊어버려서 결국엔 겹치는 현상을 보여주고 있다. -_-

 

실제 게임에서도 스폰 특정구역에서 범위안에서 다음 웨이브가 시작시 랜덤하게 스폰을 해주고 있는데 

아래의 그림처럼 하나의 점을 기준으로 일정 거리 안에서만 스폰이 되고 있다.

 

 

위의 그림처럼 원 안에서만 스폰되는거라고 생각하면 된다.

그런데 그림을 보고 말로하는것은 그까짓꺼 간단하게 랜덤 좌표를 구해오면 되지 이런생각이 들지만

 

막상 구현하려고 하면 음... 막 코드밖에 떠오르지 않는다.

1. 임의의 좌표를 랜덤으로 받아온다.

2. 두 점사이의 거리를 통해서 거리가 반지름(r)보다 긴지 짧은지 비교를 한다.

3. 거리가 길다면 다시 짧은거리가 될때까지 받아온다..

 

이 방법은 운이 좋으면 한번에 운이 나쁘면 언제까지 루프를 계속 돌릴지도 의문이고....

(그 놈의 요즘 CPU들은 성능 좋아져서 막 짜도 된다는 개같은 소리는 집어치웠으면 좋겠다 

이렇게 뻔히 루프 횟수가 차이나는데...

ㅅㅂ 코드 짜야하는 시간이 1분 뭐 이렇게 존나 급한것도 아니고)

 

일단 머리속을 정리하고 내가 구현한 방법은..

 

위는 원의 방정식에서 임의의 x,y에 해당하는 점이 반지름 r인 원 안에 존재한다는 범위인데...

 

반지름 길이는 일단 1로 두고

일단 여기서 하나의 값을 랜덤한 값으로 가져오자.

랜덤으로 가져올 값의 범위는 원점에서 음수의 반지름 길이만큼부터 양수의 반지름 길이 까지가 되겠다.

 

여기서는 반지름 길이를 1로 두었으니 -1 부터 1까지가 되겠다.

 

임의의 값으로 0.3이 나왔다고 치고 값을 대입해 보았다.

 

이제 y에 대한 식으로 정리를 해보면..

이렇게 정리가 된다

이제 정확한 값은 아니지만 근사값으로 y의 값을 0.95로 하고 

 

반지름 길이가 1인 원위의 값으로 (0.3 , 0.95)가 나왔다.

 

대략 저 위치에 존재하게 된다.

 

이제 여기서 중요한것은 반지름의 길이를 조절해서 사용자가 원하는 범위대로 조절해 주면 된다.

여기서 반지름의 길이가 20이라고 한다면 그래프는 이렇게 그려질 것이다.

 

이렇게 반지름의 길이만큼 곱해주면 위와같은 그림이 되면서 위치가 변하게 된다.

 

여기서 중요한점은 이 반지름 길이를 최대값보다 작거나 같음으로 랜덤값을 뽑아서 곱해버리면 된다는것.

 

이제 코드로 옮겨보자

 

    public Vector3 RandomSphereInPoint( float radius )     {         // xz 바닥 평면이니까         float x = Random.Range(-1.0f, 1.0f);         float temp = Mathf.Pow(1.0f, 2) - Mathf.Pow(x, 2);         float z = Mathf.Sqrt(temp);          return (new Vector3(x, 0.0f, z) * Random.Range(0.0f, radius))             + new Vector3(transform.position.x, 0.0f, transform.position.z);     } 

(처음 작성한 코드에 실수가 있어서 버그가 있었다 -_-;; 지금은 수정 완료...)

코드를 보면 일단 유니티는 y축이 위쪽이고 xz가 평면인 축이다.

x의 좌표를 랜덤으로 구하고 원의 방정식에 대입해서 z를 구하였다.

 

그리고 리턴으로 넘겨주는것을 보면 transform.position의 값들을 더해주고 있는데 이거는 현재 xz위치 만큼 평행이동이라고 생각하면 된다.

 

 

그리고 이렇게 일일히 구하는 방법이 있는가 하면은 유니티에서 친절하게도 만들어 둔것이 있다.

아래의 코드를 보자.

 

    public Vector3 RandomSphereInPoint( float radius )     {         //Random.onUnitSphere : 반경 1을 갖는 구의 표면상에서 임의의 지점을 반환합니다. (읽기 전용)         Vector3 getPoint = Random.onUnitSphere;         getPoint.y = 0.0f;          // 0.0f 부터 지정한 반지름의 길이 사이의 랜덤한 값 추출.         float r = Random.Range(0.0f, radius);          // 현재 이 위치만큼 평행이동이 필요하므로. position을 더해준다.         return (getPoint * r) + transform.position;     } 

 

먼저 Random.onUnitSphere는 주석에 적힌대로 반경이 1인 구의 표면에서 임의의 지점을 반환한다

여기서 우리는 xz평면에 대한것만 사용할거싱라서 y는 0.0으로 했고 ( 이렇게 하면은... 반지름의 길이가 정확한 1은 아니겠지만... )

 

여기서 랜덤한 반지름의 길이를 구해서 곱해주었다.

그 후에 평행이동할 만큼 더하고 return 해주는것으로 완료..

 

다음은 이 구한 좌표를 통해서 스폰한 결과이다.

 

 

 

https://youtu.be/kH0jtiA4g00

야호

 

 

반응형

'Project > project_PQ' 카테고리의 다른 글

[project_PQ]-[Unity3D] Runtime navmesh bake  (4) 2018.07.28
[project_PQ] 포켓몬 퀘스트 모작.  (0) 2018.07.28