본문 바로가기
개발 (Game)/(2021) Unity RTS 포트폴리오

[Day3] 카메라 쿼터 뷰 시점 구현 및 유닛 이동 수정 완료

by 진현개발일기 2021. 7. 14.

[2021. 7. 14]

[카메라 쿼터뷰 구현]

문명과 같이 쿼터 뷰 시점을 구현하고싶었다.

처음 먼저 생각 난 것은 EmptyParent를 하나 만들어서 방향키를 누르면 카메라가 아닌 Empty부모를 움직이는

것이였다. 

카메라 각도는 대각선 아래로 고정이 되어있기 때문에 카메라 자체를 움직이게 하고 transform.forward 값을 이용해 움직인다면  대각선 아래로 내려가기 때문이다.

 

Hierarchy 카메라 구조

이제 유니티 상에서 구조를 잡아놨으니 스크립트를 짜야한다.

움직임을 FixedUpdate안에 Translate으로 움직여야할지 아니면 Update안에 transform.position += 이런 식으로 

해야할지 고민을 해봤고 그 둘의 FPS를 비교 해봤다.

 

 

FixedUpdate(Translate)
Update(position 지정)

 

 

Translate이다. (FPS 290대~380대)
포지션 지정이다. (FPS 290대~380대)

CPU ms차이도 없고 FPS도 다를 것이 없기 때문에 보기에 더 깔끔한 포지션 지정으로 하기로했다.

 

▼ 카메라 움직임(최종) 스크립트다

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
using UnityEngine;
 
 
namespace YJH.World.CameraFunc
{
    public class WorldCamera : MonoBehaviour
    {
        float MoveSpeed = 50f;
        float WheelSpeed = 40f;
        float WheelInput;
        float MinHeight=50f;
        float MaxHeight=100f;
 
        void Update()
        {
            CameraMove();
            CameraZoom();
        }
 
        #region Camera Methods
        void CameraMove()
        {
            if (Input.anyKey)
            {
                transform.position += transform.forward * Input.GetAxis("Vertical"* MoveSpeed * Time.deltaTime;
                transform.position += transform.right * Input.GetAxis("Horizontal"* MoveSpeed * Time.deltaTime;
            }
        }
 
        void CameraZoom()
        {
            Vector3 CamLoc = transform.position;
            float CamY = CamLoc.y;
 
            WheelInput = Input.GetAxis("Mouse ScrollWheel");
 
            if(WheelInput !=0)
            {
                transform.position += Vector3.up * WheelInput * WheelSpeed * CamY * Time.deltaTime;
 
                if(CamY<MinHeight)
                {
                    transform.position = new Vector3(CamLoc.x, MinHeight, CamLoc.z);
                }
                else if(CamY>MaxHeight)
                {
                    transform.position = new Vector3(CamLoc.x, MaxHeight, CamLoc.z);
                }
            }
        }
        #endregion
 
    }
 
}
 
cs

게임 플레이시 Stats(FPS, CPU ms 등등) 변화는 없었다.

 

[유닛 움직임 수정]

이전 글에서 언급했던 문제를 수정하기 위해서 어떤 방법들이 있을지 먼저 고민을 해봤다.

 

x 표시된 타일이 나오면 안된다 (movestat==2)

오랫동안 생각하고 정리해본 방법들은

1. 자주 사용했던 내적, 외적을 이용하여 현재 내가 선택한 유닛과 적들의 위치에 따라서 내가 원하는 위치의 Coord와

   일치하는 타일들을 걸러내서 InActive시키는 방법

 

2. Ray로 원하는 위치의 타일에 쏴서 InActive 시키는 방법

 

첫 번째 방법은 오래걸리면서 변수가 많고 만들었다해도 잔버그가 생길것 같다는 판단하에 두 번째 방법을 택하기로 했다.

 

그러면 Ray를 어떻게 쏴야할까?

 

타일 위에 올라가있는 유닛의 데이터가있기 때문에 그 유닛들이 내가 선택한 유닛을 바라보게 한 뒤

-transform.forward * 원하는 거리 + Vector3.down*길이  만큼 해서  내려 꽂는 식으로 하기로했다.

 

성공한건가 싶었으나 문제가 생겼다.

 

성공 사례들
실패 사례들

빨간색 타일 위 코를 가지고있는 오브젝트가 적이다.

될때가 있고 안될 때가 있다.. 유닛들의 위치를 옮겨도 랜덤으로 될때가 있고 안될때가 있었다. 혹시 몰라서

Debug.Log를 찍어보면서 레이의 위치를 확인해보았고 OnDrawGizmos를 해봐도 레이는 정상적으로 원하는 타일을

찍고있었다.

 

Ray가 타일을 찍고있음

오전에 해결을 못해서 밥을 먹고와서 조금 휴식을 취한 뒤에 생각을 해보았다.

 

잘 되는 타일과 안되는 타일을 유니티에서 비교해봤는데 차이점이 없고. 타일들의 좌표와 Ray의 Direction, Origin을 디버깅을 통해 비교를 해봤는데도 발견되는 규칙이 없는 것을 보아 아마 코드 내의 순서 문제가 아닌 가싶었다.

 

고치기 전 코드

고치고나서 틀렸던 예시를 보여주기 위해 다시 제자리로 복붙한거라서 selectableTiles[j]를 [i]로 생각하면 된다.

생각을 해봤는데 흰색 타일을 true 시켜주는 조건문안에 else if(적)일 경우 빨간색 타일을 Active True를 시켜준다.

 

내 생각이지만 위에서  흰색 타일을 true 시켜주는 if 조건문이 실행되는 동시에

밑에 흰색 타일을 InActive 시켜주는 함수도 동시에 실행되면서 같은 [i]로 체크해서 매우 미세한 속도 차이로

순서가 뒤바뀐것같다. 그래서 for문 하나를 추가로 만들어서 돌렸더니

 

moveStat이 2일때

 

moveStat이 3 일때

성공하였다 ㅎㅎ 

 

고친 후 코딩(리팩토링 전)

                                                                   ▼

                                                                   ▼

리팩토링 후 
InActiveFile 함수

tempMoveStat은 0.001초 그 짧은 순간에 버그가 날 수 있어서 변수로 두고 고치다보니

수정하고 남은 잔해이다. 순서 자체가 이제 고정적으로 정해졌으니 tempMoveStat은 필요없을 것 같다.

 

해결은 했지만 단점이라면 근처 모든 유닛들(아군+적군)이 내가 선택한 유닛을 쳐다보게된다.

일단은 기능 자체는 구현이 되었으니 불만족스러운 것들은 중요한 것들을 다 구현하고나서 수정하면 될것같다.

 

 

728x90