One_KWS

게임 개발 일지 #1 - 프로젝트 시작, 조이스틱 개발 본문

게임 개발

게임 개발 일지 #1 - 프로젝트 시작, 조이스틱 개발

One-Kim 2022. 12. 29. 00:40

개임을 만드는 이유와 일지를 쓰는 이유

현재 회사에서 Unity를 사용하지만, 교육 서비스다 보니 Unity의 많은 기술 중 일부만을 사용하는 느낌을 많이 받았다. 또한 일찍이 팀장을 맡으면서 개발 외의 업무들도 하다 보니 개발하는 시간도 줄기도 했기 때문에 내 실력 향상을 위해서는 사이드 프로젝트가 꼭 필요하다고 생각했다. 그렇게 올해 6월부터 퇴근 후 조금씩 만들었는데 진행한 내용들을 정리해 놓지 않아서 바쁠 때 신경 못쓰다가 다시 돌아오면 어디까지 했는지 기억이 잘 안 나는 문제가 생겨서 .. 지금이라도 조금씩 개발한 내용들을 정리해 놓으려고 한다. (이것도 자주 쓸 수 있을지 모르겠다..)

 

어떤 게임을 만들 것인가 

게임을 만들자는 생각을 할 때 쯤 하데스라는 게임을 하고 있었다. 그래서 자연스럽게 핵 앤 슬래시 로그라이트 게임을 만들어야겠다고 생각했던 것 같다. 혼자 만들기 때문에 게임 볼륨이 너무 크면 중간에 포기할 것 같아서 하데스 보다 더 단순하게 만들어야 겠다고 생각했다. (플랫폼은 일단 Android로 하기로 했다. 25달러면 되니깐 ..)

  • 매 층마다 몬스터들이 존재하고 특정 층마다 보스 몬스터가 나온다.
  • 몬스터를 전부 잡으면 랜덤으로 능력을 얻을 수 있으며 다음 층으로 넘어갈 수 있다.
  • 죽으면 1층으로 돌아간다.

이미 6개월간 개발을 했기 때문에 현재까지 개발된 상태를 정리해서 올리면서 게임 개발도 병행하려고 한다. (시간이 될 지 모르겠다.. 나를 갈아 넣는다면 ..) 개발을 할때마다 일지로 정리해서 쓰지는 못하겠지만 1~2주에 한번씩은 정리해서 올리는게 목표이다.


조이스틱

모바일로 개발하고 있기 때문에 조이스틱과 공격 등 버튼 UI를 만들었다. 마침 전에 에셋 스토어에서 산 UI 에셋에 원신과 비슷한 조이스틱 이미지가 있어서 원신의 조이스틱 움직임을 참고하며 개발했다. 

참고한 원신의 조이스틱

조이스틱 핸들이 테두리를 따라 회전을 하는 형태이기 때문에 현재 터치 위치와 핸들의 위치를 이용하여 각도를 계산하고 핸들의 회전 값으로 넣어주었다. 손가락을 조이스틱에 대고 있는 동안에만 핸들이 보이도록 OnPointerUp과 OnPointerDown에서 설정해주었다.

// Unity EventSystem
public void OnDrag(PointerEventData eventData) {
    SetHandleAngle(eventData);
}

public void OnPointerUp(PointerEventData eventData) {
    handle.SetActive(false);
}

public void OnPointerDown(PointerEventData eventData) {
    handle.SetActive(true);

    SetHandleAngle(eventData);
}

// 터치 위치와 핸들 위치 사이 각도 계산
private float GetAngle(Vector2 startPosition, Vector2 endPosition) {
    var targetVector = endPosition - startPosition;
    return Mathf.Atan2(targetVector.y, targetVector.x) * Mathf.Rad2Deg;
}

// 핸들 각도 설정
private void SetHandleAngle(PointerEventData eventData) {
    var angle = GetAngle(handle.transform.position, eventData.position);
    handle.transform.rotation = Quaternion.Euler(Vector3.forward * (angle - ANGLE_OFFSET));
}

 

조이스틱을 움직일 때 핸들의 방향에 따라 플레이어의 방향을 바꿔줄 수 있도록  현재 조이스틱 값을 전달할 수 있도록 구현했다. 핸들의 Z Rotation이 0일 때 45도 방향을 향하고 있기 때문에 Value 값 리턴시 45도를 빼주도록 했다. Value 값을 0 ~360 값으로 줄 수 있도록 % 연산을 하였다. 

...

private readonly int ANGLE_OFFSET = 45;

...

private Vector2 joystickValue = Vector2.zero;
public Vector2 Value {
    get {
        var angle = (handle.transform.localRotation.eulerAngles.z - ANGLE_OFFSET) % 360;
        joystickValue.x = Mathf.Sin(-angle * Mathf.Deg2Rad);
        joystickValue.y = Mathf.Cos(-angle * Mathf.Deg2Rad);

        return joystickValue;
    }
}

조이스틱 핸들의 각도가 0일 때 45도 방향을 향하고 있다.
완성된 조이스틱

싱글톤

조이스틱 값은 싱글톤을 통해 값을 가져올 수 있도록 했다. 싱글톤은 제네릭으로 만들어서 쉽게 만들어서 쓸 수 있게 구현했다. 

public class Singleton<T> : MonoBehaviour where T : MonoBehaviour {
    private static T instance;
    public static T Instance {
        get {
            if (instance == null) {
                instance = FindObjectOfType(typeof(T)) as T;

                if (instance == null) {
                    var singletonObject = new GameObject();
                    instance = singletonObject.AddComponent<T>();

                    singletonObject.name = typeof(T).Name;
                    DontDestroyOnLoad(singletonObject);
                }
            }

            return instance;
        }
    }
}

 

위의 싱글톤 클래스를 상속받아 InputManager 클래스를 만들었다. 

public class InputManager : Singleton<InputManager> {
    public bool IsJoystickActive => joystick.IsActive;
    public Vector2 MoveValue => joystick.Value;

    private Joystick joystick;

    private void Awake() {
        joystick = GameObject.Find("Joystick").GetComponent<Joystick>();
    }
}