말감로그

[Unity] Valley - Item Shop 구현 본문

TIL

[Unity] Valley - Item Shop 구현

habbn 2024. 11. 21. 17:12
728x90

 

아이템을 파는 ItemBox는 있지만, 아이템을 사는 ItemShop은 없어서 따로 만들어주었다.

UI는 이런식으로 만들어줬다.

 

 

ItemShop 스크립트는 간단하게 sellItems 리스트를 만들어 각 리스트에 아이템을 추가해주고, 해당 버튼을 누르면 돈이 차감되고, 해당 아이템을 toolbar에 추가해주는 형식으로 만들었다.

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

public class Shop : MonoBehaviour
{
    public GameObject shopPanel;
    public Button riceBuyBtn;
    public Button tomatoBuyBtn;
    public List<Item> sellItems;

    private bool isPlayerInRange = false;
    private Player player;

    private void Start()
    {
        player = FindObjectOfType<Player>();

        riceBuyBtn.onClick.AddListener(() => BuyItem(sellItems[0]));
        tomatoBuyBtn.onClick.AddListener(() => BuyItem(sellItems[1]));
    }

    private void Update()
    {
        if (isPlayerInRange && Input.GetMouseButtonDown(1))
        {
            shopPanel.SetActive(true);
        }
    }

    public void BuyItem(Item item)
    {
        if (sellItems.Contains(item))
        {
            if (player.money >= item.itemData.price)
            {
                player.inventoryManager.Add("Toolbar", item);
                StartCoroutine(InGameUI.instance.UpdateMoneyEffect(player.money, player.money - item.itemData.price));
            }
            else
            {
                InGameUI.instance.ShakingText();
            }
        }
    }

    private void OnTriggerEnter2D(Collider2D other)
    {
        if (other.gameObject.name == "Player")
        {
            isPlayerInRange = true;
        }
    }

    private void OnTriggerExit2D(Collider2D other)
    {
        if (other.gameObject.name == "Player")
        {
            isPlayerInRange = false;
            shopPanel.SetActive(false);
        }
    }
}

 

 

만약 플레이어가 보유한 금액보다 아이템의 가격이 더 높을 때 ( 플레이어가 돈이 없을 때) moneyText를 색상 변경과 함께 좌우로 흔들리는 효과를 주고 싶어 코루틴과 Mathf.Sin() 메서드를 활용하여 구현했다.

 

Mathf.Sin() 메서드는 1과 -1을 반복하기 때문에 진자 운동같은 반복적인 움직임에 사용된다.

 public void ShakingText()
    {
        StartCoroutine(ShakeCoroutine());
    }

    private IEnumerator ShakeCoroutine()
    {
        float amplitude = 3f;   // 진폭
        float frequency = 20f;  // 빈도
        float duration = 1f;    // 주기
        Color originalColor = moneyText.color;
        Vector3 orignalPosition = moneyText.rectTransform.anchoredPosition;

        moneyText.color = Color.red;

        float elapsedTime = 0f;

        while (elapsedTime < duration)
        {
            float offset = Mathf.Sin(elapsedTime * frequency) * amplitude;
            moneyText.rectTransform.anchoredPosition = orignalPosition + new Vector3(offset, 0, 0);

            elapsedTime += Time.deltaTime;
            yield return null;
        }

        moneyText.rectTransform.anchoredPosition = orignalPosition;
        moneyText.color = originalColor;
    }

 

 

추가적으로 각 스크립트에서 필요없는 코드 삭제나 코드 최적화 작업을 진행하였고,

문이 열리고 닫힐 때 레이케스트로 인식하다보니 부자연스러운 부분이 있는 것 같아서 OnTriggerEnter/Exit로 변경해주었더니 훨씬 자연스럽게 되었다. 그리고 너무 레이캐스트를 남발하는 것 같아서 PostBox도 마찬가지로 OnTriggerEnter/Exit로 변경해주었다.

 

또한 Unity Project에서 타일 명을 바꾸고, 스크립트에 바뀐 타일명으로 다시변경해주지 않아서 안되었던 것들도 제대로 맞게 변경해주었다.

728x90