[TIL] Unity - 게임 내 시간 구현

MINO·2024년 7월 17일
post-thumbnail

2024-07-17


구현 목적

게임의 모티브인 게임 속, 바바리안으로 살아남기 라는 웹툰의 설정 중,
일정 주기마다 세금을 내는 시스템이 존재한다.

이 시스템으로 인해, 탐험가들은 세금으로 낼 돈을 벌기 위해 던전으로 들어가야만 하는
명분이 생긴다.

마찬가지로, 유저들이 던전을 탐험하지 않고, 마을에만 있어서는 안되기 때문에
당위성을 부여하기 위해 세금 시스템 을 도입하고자 했다.

그러기 위해서는 게임 내의 시간의 흐름이 필요했고,
이를 활용하여 낮과 밤의 맵 밝기 조절이나, 시간대에 따른 이벤트도 만들어 줄 수 있었다.


참고 레퍼런스 및 구상

현실 시간과 게임 속 시간의 흐름의 밸런스는 추후 조정하기로 하고,
대략 0.5 초에 1분이 지나가게끔 구상하였다.

시간대에 따른 이벤트로는

  • 던전에서 밤에 몬스터가 더 자주 생성
  • 마을에서 시간에 따라 맵의 밝기가 변화
스타듀밸리 시간 시스템스타듀밸리 시간 UI프로젝트 좀보이드 시간 UI

스크립트 작업

실제 시간의 흐름을 관리하는 스크립트와
UI를 관리하는 스크립트로 나눠 관리하였다.

ClockSystem.cs

실제 시간의 흐름을 추적하고 관리하는 ClockSystem 스크립트

using System;
using UnityEngine;

public class ClockSystem : MonoBehaviour
{
    public static Action OnTimeChanged;
    
    public static int Minute { get; private set; }
    public static int Hour { get; private set; }
    public static int Dday { get; private set; }

    [SerializeField] private float minuteToRealTime = 0.1f; 
    [SerializeField] private float timer;

    void Start()
    {
        timer = minuteToRealTime;
    }

    void Update()
    {
        if (Player.Instance.isPlayerInteracting)
            return;
         
        timer -= Time.deltaTime;

        if (timer <= 0)
        {
            Minute++;

            if (Minute >= 60)
            {
                Minute = 0;
                Hour++;
                if (Hour >= 24)
                {
                    Hour = 0;
                    Dday++;
                }
            }

            OnTimeChanged?.Invoke();
            timer = minuteToRealTime;
        }
    }

	public static bool IsDayOrNight()
    {
        if (Hour >= 18 || Hour <= 6)
            return false;
        else
            return true;
    }
}

Update 문에서 Player.Instance.isPlayerInteracting 을 확인한 이유는

  • 플레이어가 인벤토리창을 열었을 때
  • NPC 와 대화를 진행하고 있을 때
  • 씬 로드 작업등이 이루어지고 있을 때

등 시간의 흐름을 멈추게 하기 위해서다.


ClockUI.cs

ClockSystem 에서 Minute 가 바뀔 때마다
OnTimeChanged 이벤트에 구독해둔 메서드를 실행함으로
UI 를 업데이트 해준다.

using TMPro;
using UnityEngine;

public class ClockUI : MonoBehaviour
{
    public TextMeshProUGUI Time, Dday, LifeCnt;

    private void OnEnable()
    {
        ClockSystem.OnTimeChanged += UpdateTime;
    }

    private void OnDisable()
    {
        ClockSystem.OnTimeChanged -= UpdateTime;
    }

    private void UpdateTime()
    {
        Time.text = $"{ClockSystem.Hour:00}:{ClockSystem.Minute:00}";
        LifeCnt.text = $"인생 {DataManager.Instance.currentPlayer.lifeCnt} 회차";
        Dday.text = $"생존 {ClockSystem.Dday} 일차";
    }
}

추가 구현

시간의 흐름을 구현하였으니, 앞으로 구현해야할 몇가지 기능을 정리해보았다.

  • 플레이어가 마을에 있을 때
    • Global Light 의 Intensity 속성에 접근해 시간에 따라 밝기를 조절
  • 플레이어가 던전에 있을 때
    • 몬스터가 재 생성되는 주기를 시간에 따라 조절
  • 세금 시스템
    • 5일마다 세금을 거두기
    • 조금 더 세밀한 구상이 필요
  • 데이터 저장
    • 현재 데이터를 저장하고 불러왔을 때, 시간 정보가 불러와지게 수정이 필요

결과물

TIL 마무리

부트 캠프에서 제공되는 강의를 통해 낮과 밤 을 구현한 적이 있었는데,
배운 내용을 기반으로 새롭게 시간 시스템을 구현할 수 있었다.

더 보완되고 수정해야할 부분이 있어 잘 다듬어 봐야겠다.

profile
안녕하세요 게임 개발하는 MINO 입니다.

0개의 댓글