[TIL] Unity - 세금 시스템

MINO·2024년 7월 29일
post-thumbnail

2024-07-29


구현 목적

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


구상

마을에 세금을 거두는 회관 NPC 가 존재한다.

  • 세금은 5일마다 한 번씩 징수
  • 세금 가격은 추후 골드 밸런스를 통해 맞출 예정
  • NPC 와의 대화 시스템을 통해 세금에 대한 정보를 공유
  • NPC 와의 대화 시스템에 선택지 기능이 필요
  • 5일 자정까지 세금을 내지 못한다면, 처형 이벤트 발생

스크립트 작업

세금에 관련된 메서드를 관리하기 때문에
TaxManager.cs 로 관리하였다.


TaxManager.cs

using System;
using UnityEngine;

public class TaxManager : MonoBehaviour
{
    [SerializeField] private int TaxDue = 5;
    public static Action OnCutSceneEvent;

    private void Awake()
    {
        if (GameManager.Instance.TaxManager != null) 
        	return;

        GameManager.Instance.TaxManager = this;
    }


    private void OnEnable()
    {
        ClockSystem.OnCheckTaxPayment += CheckTaxPayment;
    }

    private void OnDisable()
    {
        ClockSystem.OnCheckTaxPayment -= CheckTaxPayment;
    }

    public int TaxPrice()
    {
        int week = (ClockSystem.Dday - 1) / TaxDue + 1;
        int price = week * 1000;

        return price;
    }
    
    public void PayTax()
    {
        int price = TaxPrice();

        if (DataManager.Instance.currentPlayer.gold >= price) // 돈 있을 때
        {
            DataManager.Instance.currentPlayer.lastPayment = ClockSystem.Dday;
            DataManager.Instance.currentPlayer.gold -= price;

            DialogueManager.skipDialogueNum = 22;
        }
        else // 돈 없을 때
        {
            DialogueManager.skipDialogueNum = 21;
        }
    }

    public void CheckTaxPayment()
    {
        if(ClockSystem.Dday - DataManager.Instance.currentPlayer.lastPayment <= TaxDue)
            return;
        
        else
            OnCutSceneEvent?.Invoke();
    }

}

ClockSystem.cs

현재 마을씬에 존재하고,
생존 일수 % 세금납부일 == 1 일 때 (세금 내는 다음 날), 세금을 냈는지 확인하는
OnCheckTaxPayment 이벤트를 호출한다.

// ClockSystem.cs
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++;
                if (Dday % GameManager.Instance.TaxManager.TaxDue == 1 
                		&& SceneManager.GetActiveScene().buildIndex == 2)
                    OnCheckTaxPayment?.Invoke();

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

TaxOffice.cs

또한, 날짜가 바뀜에 따라 NPC의 대사가 바뀌어야한다.
마을 회관에서의 NPC 대사를 수정하는 스크립트인 TaxOffice 이다.

날짜대사
1~3일차이번 주 세금은 OO G 입니다.
4일차내일이 세금내는 날이니 잊지마세요.
5일차세금은 OO G 입니다. 세금을 납부하시겠습니까? (Y / N 선택지)
5-Y1(충분한 돈이 있을 때, 돈이 빠져나가며) 이번 주 세금은 잘 받았습니다.
5-Y2(충분한 돈이 없을 때) 돈이 부족한거 같으니 다시 방문해주세요.
5-N오늘 안에 다시 한 번 방문해주세요.
5-세금 납부이미 세금을 받았습니다.

플레이어의 보유 골드와 생존 일자, 이미 세금을 납부했는지 등에 따라
마을 회관 NPC 의 대사가 바뀌어야한다.

using UnityEngine;

public class TaxOffice : MonoBehaviour
{
    int[] lineX = new int[] { 0, 17, 18, 19 ,23};
    int[] lineY = new int[] { 0, 17, 18, 19 ,23};
    public InteractionEvent interaction;

    private void Start()
    {
        interaction = GetComponent<InteractionEvent>();
        DialogueChange();
    }
    private void OnEnable()
    {
        ClockSystem.TaxDialogueEvent += DialogueChange;
    }

    private void OnDisable()
    {
        ClockSystem.TaxDialogueEvent -= DialogueChange;
    }

    private int DialogueNum()
    {
        if (ClockSystem.Dday % GameManager.Instance.TaxManager.TaxDue == 0) // 세금 당일
        {
            if (ClockSystem.Dday == DataManager.Instance.currentPlayer.lastPayment)
                return 4;
    
            else
                return 3;
        }
        else if (ClockSystem.Dday % GameManager.Instance.TaxManager.TaxDue < GameManager.Instance.TaxManager.TaxDue - 1) // 평상 시
            return 1;

        else if (ClockSystem.Dday % GameManager.Instance.TaxManager.TaxDue == GameManager.Instance.TaxManager.TaxDue - 1) // 세금 전 날
           return 2;


        return 0;
    }

    public int SetLineX()
    {
        return lineX[DialogueNum()];
    }

    public int SetLineY()
    {
        return lineY[DialogueNum()];
    }

    public  void DialogueChange()
    {
        int x = SetLineX();
        int y = SetLineY();

        interaction.UpdateDialogueLines(x, y);
        GameManager.Instance.DialogueManager.GetDialogues(interaction.GetDialogue());
    }
}

TIL 마무리

대화 시스템의 경우,

팀원이 케이디 - 대화 시스템 구현 유튜브 강의를 보며 구현한 대화 시스템을 활용하였다.

내가 구현한 코드가 아니라
대사 한 줄 추가하기 조차 힘들고 복잡했다.

세금을 못 내서 처형될 때도 컷씬을 연출해보고 싶지만,
기한 안에 만들 수 있을지 걱정이다.

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

0개의 댓글