유니티 스터디 타이머 구현

Roh·2024년 9월 17일
0

토이프로젝트

목록 보기
1/1

하루 공부 시간을 저장하는 윈도우 앱은 구하기 힘들어서 만들어보기로 했다.

프로젝트를 새로 만들어주고

작업에 편하게 Game View 화면 9 : 19 로 설정

캔버스 설정도 해주고 ~

빌드시 너무 커서 크기 조절이 가능하게끔 설정할 것이다.
Player Setting 에서 Screen Width, Height, Resizable Window 설정.

CameraScaler 코드를 짜주고,

using UnityEngine;

[RequireComponent(typeof(Camera))]
public class CameraScaler : MonoBehaviour
{
    [SerializeField] protected int targetWidth = 900;
    [SerializeField] protected int targetHeight = 1900;

    [SerializeField] protected int dynamicMaxWidth = 900;
    [SerializeField] protected int dynamicMaxHeight = 1900;

    [SerializeField] protected bool useDynamicWidth = false;
    [SerializeField] protected bool useDynamicHeight = false;

    private Camera cam;
    private int lastWidth = 0;
    private int lastHeight = 0;

    private float orthoSize;

    protected void Awake()
    {
        cam = GetComponent<Camera>();
        orthoSize = cam.orthographicSize;
    }

    protected void Update()
    {
        if (Screen.width != lastWidth || Screen.height != lastHeight)
        {
            UpdateCamSize();
            lastWidth = Screen.width;
            lastHeight = Screen.height;
        }
    }

    private void UpdateCamSize()
    {
        float targetAspect;
        float screenAspect = (float)Screen.width / (float)Screen.height;
        float ortoScale = 1f;

        if (useDynamicWidth)
        {
            float minTargetAspect = (float)targetWidth / (float)targetHeight;
            float maxTargetAspect = (float)dynamicMaxWidth / (float)targetHeight;
            targetAspect = Mathf.Clamp(screenAspect, minTargetAspect, maxTargetAspect);
        }
        else
        {
            targetAspect = (float)targetWidth / (float)targetHeight;
        }

        float scaleValue = screenAspect / targetAspect;

        Rect rect = new();
        if (scaleValue < 1f)
        {
            if (useDynamicHeight)
            {
                float minTargetAspect = (float)targetWidth / (float)dynamicMaxHeight;
                if (screenAspect < minTargetAspect)
                {
                    scaleValue = screenAspect / minTargetAspect;
                    ortoScale = minTargetAspect / targetAspect;
                }
                else
                {
                    ortoScale = scaleValue;
                    scaleValue = 1f;
                }
            }

            rect.width = 1;
            rect.height = scaleValue;
            rect.x = 0;
            rect.y = (1 - scaleValue) / 2;
        }
        else
        {
            scaleValue = 1 / scaleValue;
            rect.width = scaleValue;
            rect.height = 1;
            rect.x = (1 - scaleValue) / 2;
            rect.y = 0;
        }

        cam.orthographicSize = orthoSize / ortoScale;
        cam.rect = rect;
    }
}

메인 카메라에 스크립트를 달아줬다.

좋다 이제 스크린 크기 설정이 완료됐다.

기본적인 UI 배치는 이렇게 했다.

너무 밋밋하니까 가운데에 게임 캐릭터를 하나 추가할 것이다.

아래 에셋을 다운받았다.
https://assetstore.unity.com/packages/2d/characters/pixel-adventure-1-155360

UI에서 배경을 빼주고 카메라에 추가했다.

귀여운 플레이어를 추가해주고 스크립트를 짜보자.

GameManager에 State를 추가해주고, 이 State에 따라 플레이어를 움직이게 할 것이다.

그리고 또한, Player에서 GameManager에 편하게 접근하기 위해 GameManager를 SingleTon으로 바꿔줬다.

Player 애니메이션을 추가해주고. GameManager의 State 변화에 따라 동작하게 해주었다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Player : MonoBehaviour
{
    public Animator _anim;

    private void Start()
    {
        // 3초마다 랜덤으로 애니메이션 트리거를 실행
        StartCoroutine(PlayRandomAnimation());
    }

    public void Update()
    {
        if (GameManager.instance.state != GameManager.State.Run)
        {
            _anim.SetTrigger("Stop");
        }
    }

    IEnumerator PlayRandomAnimation()
    {
        while (true)
        {
            if (GameManager.instance.state == GameManager.State.Run)
            {
                int randomAnim = Random.Range(0, 3);

                switch (randomAnim)
                {
                    case 0:
                        _anim.SetTrigger("Idle");
                        break;
                    case 1:
                        _anim.SetTrigger("Jump");
                        break;
                    case 2:
                        _anim.SetTrigger("Run");
                        break;
                }
            }

            // 3초 대기
            yield return new WaitForSeconds(3f);
        }
    }
}

StartButton, StopButton Toggle 스크립트도 만들었다.

게임 매니저의 스크립트를 아래와 같이 바꿔주면 완성된다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class GameManager : MonoBehaviour
{
    public enum State
    {
        Run,
        Stop,
    }

    public Text _timerText;
    public State state;

    public static GameManager instance;

    private float elapsedTime = 0f; // Time in seconds
    private bool isTimerRunning = false;

    private void Update()
    {
        if (state == State.Run && isTimerRunning)
        {
            elapsedTime += Time.deltaTime;
            UpdateTimerDisplay(elapsedTime);
        }
    }

    private void Awake()
    {
        instance = this;
        FindObjectOfType<ButtonToggle>().Init();
        FindObjectOfType<Player>().Init();
    }

    public void StartButtonCallback()
    {
        state = State.Run;
        isTimerRunning = true; // Start or resume the timer
    }

    public void StopButonCallback()
    {
        state = State.Stop;
        isTimerRunning = false; // Pause the timer
    }

    private void UpdateTimerDisplay(float time)
    {
        // Convert time to hours, minutes, seconds
        int hours = Mathf.FloorToInt(time / 3600);  // 1 hour = 3600 seconds
        int minutes = Mathf.FloorToInt((time % 3600) / 60);  // 1 minute = 60 seconds
        int seconds = Mathf.FloorToInt(time % 60);

        // Format the string as "4 hours 12 minutes 12 seconds"
        _timerText.text = string.Format("{0:D2}시간 {1:D2}분 {2:D2}초", hours, minutes, seconds);
    }

    public void InitButtonCallback()
    {

    }
}

완성 !

git link
https://github.com/rohyunsang/StudyNote

profile
Better than doing nothing

0개의 댓글