Carrot
본문 바로가기
Unity/멋쟁이사자처럼 부트캠프

[멋쟁이사자처럼부트캠프] 유니티 게임 개발 5기(73일차) - 모바일 틱택톡 게임 구현 (1), DOTween 맛보기

by 독기품은토끼 2025. 9. 2.
✅ 오늘의 학습 목표
1. 테스트 이론
2. 틱택토 모바일 게임 구현

1. Test

  • 만든 게임이 정상적으로 동작하는지 확인하는 과정
  • 개발 과정에서 이루어지는 단위 테스트, 통합 테스트
    • 단위 테스트: 함수 단위로 이루어지는 테스트
    • 통합 테스트: 여러 기능이 통합된 상태에서 이루어지는 테스트
  • 개발이 완료되면 진행하는 클로즈 베타 테스트, 오픈 베타 테스트
    • 알파 테스트: 외부에 공개하지 않고 내부적으로 테스트
    • 베타 테스트: 특정 또는 불특정 다수를 기반으로 한 테스트

단위 테스트 → 통합 테스트 → 알파 테스트 → 클로즈 베타 테스트 → 오픈 베타 테스트 → 출시

 

2. Tic Tac Toe (1)

🥕 예행 작업
1. Asset 다운로드
 

DOTween (HOTween v2) | 애니메이션 도구 | Unity Asset Store

Use the DOTween (HOTween v2) tool from Demigiant on your next project. Find this & more animation tools on the Unity Asset Store.

assetstore.unity.com


2. 가로 회전 막기

 

1. 게임 모드 정의

public class Constants
{
    public enum GameType { SinglePlay, DualPlay, MultiPlay }    
}

 

싱글, 듀얼, 멀티 플레이를 추후에 지원하기 위해서 enum 타입으로 게임 모드를 정의해 주었다.

 

2. 전역 게임 매니저

using UnityEngine;
using UnityEngine.SceneManagement;

public abstract class Singleton<T> : MonoBehaviour where T : Component
{
    private static T _instance;

    public static T Instance
    {
        get
        {
            if (_instance == null)
            {
                _instance = FindFirstObjectByType<T>();
                if (_instance == null)
                {
                    GameObject obj = new GameObject();
                    obj.name = typeof(T).Name;
                    _instance = obj.AddComponent<T>();
                }
            }
            return _instance;
        }
    }

    public void Awake()
    {
        if (_instance == null)
        {
            _instance = this as T;
            DontDestroyOnLoad(gameObject);

            // 씬 전환시 호출되는 액션 메서드 할당
            SceneManager.sceneLoaded += OnSceneLoad;
        }
        else
        {
            Destroy(gameObject);
        }
    }

    protected abstract void OnSceneLoad(Scene scene, LoadSceneMode mode);
}
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

public class GameManager : Singleton<GameManager>
{
    [SerializeField] private GameObject confirmPanel;

    private Constants.GameType _gameType; // Main 씬에서 선택한 게임 타입

    private Canvas _canvas;

    public void ChangeToGameScene(Constants.GameType gameType)
    {
        _gameType = gameType;
        SceneManager.LoadScene("Game");
    }

    public void ChangeToMainScene()
    {
        SceneManager.LoadScene("Main");
    }

    public void OpenConfirmPanel(string message)
    {
        if (_canvas != null)
        {
            var confirmPanelObject = Instantiate(confirmPanel, _canvas.transform);
            confirmPanelObject.GetComponent<ConfirmPanelController>().Show(message);
        }
    }

    protected override void OnSceneLoad(Scene scene, LoadSceneMode mode)
    {
        _canvas = FindFirstObjectByType<Canvas>();
    }
}

 

 

씬 전환과 팝업 호출을 총괄하는 GameManager를 만들어 주었다.

  • 메인 ↔ 게임 씬 전환
  • 선택된 GameType 저장
  • 팝업 패널 띄우기

이때 싱글톤 패턴을 적용해야 하므로 별도의 베이스 클래스를 만들어 주었다.

  • 씬이 바뀌어도 파괴되지 않고 하나만 존재

 

3. 메인 패널 버튼 연결

using UnityEngine;
using UnityEngine.UI;

public class MainPanelController : MonoBehaviour
{
    public void OnClickSinglePlayButton()
    {
        GameManager.Instance.ChangeToGameScene(Constants.GameType.SinglePlay);
    }

    public void OnClickMultiPlayButton()
    {
        GameManager.Instance.ChangeToGameScene(Constants.GameType.MultiPlay);
    }

    public void OnClickDualPlayButton()
    {
        GameManager.Instance.ChangeToGameScene(Constants.GameType.DualPlay);
    }

    public void OnClickSettingsButton()
    {

    }
}

 

메인 씬에 배치된 싱글/듀얼/멀티/환경설정 버튼을 각각 해당 스크립트에서 처리해 주었다.

  • 버튼 클릭 시 → GameManager.Instance.ChangeToGameScene() 호출
  • 인자로 Constants.GameType 전달

즉, 플레이어가 어떤 버튼을 눌렀는지에 따라 게임 모드가 결정된다.

 

4. 게임 씬 구성

using UnityEngine;

public class GameUIController : MonoBehaviour
{
    public void OnClickBackButton()
    {
        // GameManager.Instance.ChangeToMainScene();

        GameManager.Instance.OpenConfirmPanel("게임을 종료하시겠습니까?");
    }
}

 

게임 씬으로 넘어왔을 때 뒤로가기 버튼을 누르면 곧바로 메인 씬으로 돌아가는 게 아니라 확인 팝업을 띄우도록 한다.

  • 뒤로가기 버튼 클릭 시 → GameManager.Instance.OpenConfirmPanel("게임을 종료하시겠습니까?"); 호출

 

5. 팝업 패널 구현

using TMPro;
using UnityEngine;

public class ConfirmPanelController : PanelController
{
    [SerializeField] private TMP_Text messageText;

    public void Show(string message)
    {
        messageText.text = message;
        base.Show();
    }

    public void OnClickConfirmButton()
    {
        Hide();
    }

    public void OnClickCloseButton()
    {
        Hide();
    }
}

 

팝업은 메시지를 표시하고, 확인 및 닫기 버튼을 갖는다.

 

  • Show(message) → 팝업 메시지 출력
  • OnClickConfirmButton() / OnClickCloseButton() → 패널 닫기

 

6. 팝업 애니메이션

using DG.Tweening;
using UnityEngine;

[RequireComponent(typeof(CanvasGroup))] // 이 스크립트와 연결된 오브젝트는 Canvas Gropu 컴포넌트가 반드시 존재해야함.
public class PanelController : MonoBehaviour
{
    [SerializeField] private RectTransform panelRectTransform;

    private CanvasGroup _backgroundCanvasGroup;

    private void Awake()
    {
        _backgroundCanvasGroup = GetComponent<CanvasGroup>();
    }

    public void Show()
    {
        _backgroundCanvasGroup.alpha = 0;
        panelRectTransform.localScale = Vector3.zero;

        _backgroundCanvasGroup.DOFade(1, 0.3f).SetEase(Ease.Linear);
        panelRectTransform.DOScale(1, 0.3f).SetEase(Ease.OutBack);
    }

    public void Hide()
    {
        _backgroundCanvasGroup.alpha = 1;
        panelRectTransform.localScale = Vector3.one;

        _backgroundCanvasGroup.DOFade(0, 0.3f).SetEase(Ease.Linear);
        panelRectTransform.DOScale(0, 0.3f).SetEase(Ease.InBack);
    }
}

 

 

그냥 SetActive로 딱 뜨는 게 아니라, 부드럽게 등장/퇴장하는 연출을 만든다.

  • Show() → 투명도 0 → 1 (Fade in), 크기 0 → 1 (Scale up)
  • Hide() → 투명도 1 → 0 (Fade out), 크기 1 → 0 (Scale down)

이렇게 하면 팝업이 툭! 하고 뜨는 느낌이 아니라 애니메이션처럼 자연스럽게 나온다.