C# Unity, npc 아이템 구매여부 및 대사

삐얅·2024년 8월 12일
0

1. 개요

저번에 npc가 상점을 들고 있지 않아 여러 npc들의 상점 상태를 ui로 불러오는데 쓸데없이 코드가 복잡해지는 문제가 있었다.
이를 해결하기 위해서 각각 npc가 상점 스크립트를 가지고 있게 수정했다.

2. 코드

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

public class NPCInteraction : MonoBehaviour
{
    public GameObject dialogueUI;
    public GameObject selectMenu;
    public GameObject shopObj;
    public TextMeshProUGUI speakerText;
    public TextMeshProUGUI dialogueText;
    public Button upgrade;
    public Button exit;
    public DialogueData dialogueData;
    public LayerMask playerLayer;
    public Shop shop;
    public List<ItemData> shopDataList = new List<ItemData>();
    public GameObject continueKey;

    public bool isPlayerRange = false;
    public bool isDialogue = false;

    public int currentLineIndex = 0;

    private Dictionary<string, bool> itemPurcased;

    private void Awake()
    {
        itemPurcased = new Dictionary<string, bool>();

        foreach(var itemData in shopDataList)
        {
            itemPurcased[itemData.name] = false;
        }

        dialogueUI.SetActive(false);
        selectMenu.SetActive(false);
        shopObj.SetActive(false);
    }

    private void OnTriggerEnter2D(Collider2D collision)
    {
        if(((1 << collision.gameObject.layer) & playerLayer) != 0)
        {
            isPlayerRange = true;
            shop.SetShopGoods();
        }
    }

    private void OnTriggerExit2D(Collider2D collision)
    {
        if (((1 << collision.gameObject.layer) & playerLayer) != 0)
        {
            isPlayerRange = false;
        }
    }

    public void StartDialogue(DialogueData dialogue)
    {
        continueKey.SetActive(false);
        isDialogue = true;
        UIManager.Instance.OpenUI(dialogueUI);
        UIManager.Instance.pause.DisablePlayerInput();
        dialogueData = dialogue;
        currentLineIndex = 0;
        OpenSelectMenu();
        CurrnetLine();
    }

    public void OpenSelectMenu()
    {
        selectMenu.SetActive(true);
        StartCoroutine(CheckSelectMenu());
    }

    public void NextDialogue()
    {
        if(dialogueData == null || dialogueData.dialogueLines == null)
        {
            return;
        }

        if(currentLineIndex < dialogueData.dialogueLines.Count - 1)
        {
            currentLineIndex++;
            if(continueKey != null)
            {
                continueKey.SetActive(true);

            }
            CurrnetLine();
        }
        
        else
        {
            EndDialogue();
        }
    }

    private void CurrnetLine()
    {
        DialogueData.DialogueLine line = dialogueData.dialogueLines[currentLineIndex];
        speakerText.text = line.name;
        dialogueText.text = line.dialogueText;
    }

    public void EndDialogue()
    {
        UIManager.Instance.CloseCurrentUI();
        UIManager.Instance.pause.EnablePlayerInput();
    }

    public void PurchasedItem(ItemData itemData)
    {
        if(!HasPurchasedItem(itemData.name))
        {
            CharacterManager.Instance.Player.GetComponent<Player>().stats.ApplyItemEffect(itemData);
            itemPurcased[itemData.name] = true;
            UIManager.Instance.uiBar.UpdateMaxHP(itemData.healthIncrease);
        }

        else
        {
            Debug.Log("already purchased" + itemData.name);
        }
    }

    public bool HasPurchasedItem(string itemName)
    {
        return itemPurcased.ContainsKey(itemName) && itemPurcased[itemName];
    }

    public void OpenShop()
    {
        UIManager.Instance.OpenUI(shopObj);
    }

    private IEnumerator CheckSelectMenu()
    {
        while(isDialogue)
        {
            if(!selectMenu.activeInHierarchy)
            {
                NextDialogue();
                yield break;
            }

            yield return null;
        }
    }
}

HasPurchassedItem에서 해당 아이템의 재고가 있는지 여부를 반환한 다음 해당 조건문을 통해 플레이어에게 아이템을 추가하는 메서드를 실행하게 했다.
대사는 Scriptable Object를 사용했고 리스트로 대사를 관리하고 있다. index를 통해 다음 대사를 출력할지 대화를 종료할지를 작성했다.
대화를 끝내는 부분은 상점을 선택하는 메뉴가 떠있을 때와 아닐때를 코루틴으로 체크해 다음 대사를 출력하게 만들었다.

0개의 댓글

관련 채용 정보