방명록
- 유니티 게임 개발 숙련 #22023년 09월 20일 20시 55분 25초에 업로드 된 글입니다.작성자: noun06
개요
개인 프로젝트인 RPG 플레이어 스탯 및 인벤토리 시스템의 기본적인 부분들을 완성하였음. 실제로 스크립터블 오브젝트 개념을 특히 아이템 쪽에 적용하여 활용해보았는데 이 기능의 확정성, 편의성 측면의 장점을 체감하였음. 현재 가장 큰 문제점은 플레이어 스크립터블 오브젝트에 직접적으로 아이템 장착/장착 해제 수치가 반영되기 때문에 고정되어 있는 플레이어 스크립터블 오브젝트를 리셋시키는 기능이 필요함.
플레이어 스탯
- 플레이어 스크립터블 오브젝트 클래스인 PlayerSO는 플레이어의 정보 속성들을 가지고 있음.
using UnityEngine; [CreateAssetMenu(fileName = "Player Info", menuName = "SO/Player")] public class PlayerSO : ScriptableObject { [Header("Basic Info")] public string playerName; public int level; public int gold; [Header("Stats Info")] public int atk; public int def; public int maxHP; public int maxMP; public int maxSP; public int luk; }
- PlayerStatsUI 클래스 내에서 PlayerSO의 데이터를 가져와서 UI 상에서 나타냄.
public PlayerSO playerData; private void Update() { UpdatePlayerStatsUI(); } void UpdatePlayerStatsUI() { playerNameText.text = playerData.playerName; playerLevelText.text = "LV. " + playerData.level.ToString(); playerGoldText.text = playerData.gold.ToString(); playerAttackText.text = "ATK: " + playerData.atk.ToString(); playerDefenseText.text = "DEF: " + playerData.def.ToString(); playerMaxHPText.text = "HP: " + playerData.maxHP.ToString(); playerMaxMPText.text = "MP: " + playerData.maxMP.ToString(); playerMaxSPText.text = "SP: " + playerData.maxSP.ToString(); playerLuckText.text = "LUK: " + playerData.luk.ToString(); }
인벤토리 시스템
- 동일하게 아이템의 경우도 스크립터블 오브젝트를 통해 관리하며 이를 기반으로 여러 종류의 에셋들을 만들어 놓음.
using UnityEngine; [CreateAssetMenu(fileName = "Item Info", menuName = "SO/Item")] public class ItemSO : ScriptableObject { public string itemName; public string itemDescription; public ItemType itemType; public int itemDamage; public int itemArmor; public Sprite itemImage; public enum ItemType { Weapon, Armor, Consumable } }
- Item.cs는 실제 아이템 객체들의 동작을 가지고 있음. ItemSO의 데이터를 가져와 사용하며 플레이어와 충돌 시 인벤토리에 아이템을 추가하는 메서드를 호출함.
using UnityEngine; public class Item : MonoBehaviour { [SerializeField] private ItemSO itemData; private void OnCollisionEnter2D(Collision2D collision) { if (collision.gameObject.CompareTag("Player")) { InventoryManager.instance.AddItemToInventory(itemData); Destroy(gameObject); } } }
- InventoryManager.cs는 메뉴 창 토글, 인벤토리에 아이템 추가의 기능을 수행함. 각 아이템 슬롯들을 배열 변수로 선언하여 반복문을 통해 각 슬롯 배열에 item.cs를 통해 추가된 아이템을 AddItem() 메서드를 통해 실제 아이템 정보들과 함께 인벤토리에 추가함.
using UnityEngine; public class InventoryManager : MonoBehaviour { public GameObject menu; private bool isMenuActive; [SerializeField] private ItemSlot[] itemSlots; public static InventoryManager instance; private void Awake() { if (instance == null) { instance = this; } else { Destroy(gameObject); } } void Update() { if (Input.GetKeyDown(KeyCode.Escape)) { ToggleMenu(!isMenuActive); } } public void AddItemToInventory(ItemSO itemData) { for (int i = 0; i < itemSlots.Length; i++) { if (itemSlots[i].isFull == false) { itemSlots[i].AddItem(itemData); return; } } } private void ToggleMenu(bool showMenu) { menu.SetActive(showMenu); isMenuActive = showMenu; } }
- ItemSlot.cs는 인벤토리의 각 슬롯을 관리하는 역할을 함. InventoryManager을 거쳐 받아온 아이템 정보들을 아이템 정보창을 통해 나타냄과 동시에 각 슬롯 아이템의 장착관리를 함. IPointerEventData 인터페이스를 구현하여 좌클릭시 아이템 정보들을 보여주고 우클릭시 장착 상황을 토글함.
using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; using TMPro; public class ItemSlot : MonoBehaviour, IPointerClickHandler { private ItemSO itemData; public bool isFull; private bool isEquipped = false; [SerializeField] private Image itemImage; [SerializeField] private GameObject selectedSlot; [SerializeField] private GameObject equippedImage; [SerializeField] private bool isSelected; [SerializeField] private Image itemDescriptionImage; [SerializeField] private TMP_Text itemDescriptionNameText; [SerializeField] private TMP_Text itemDescriptionText; public void AddItem(ItemSO itemData) { this.itemData = itemData; isEquipped = false; isFull = true; itemImage.sprite = itemData.itemImage; } public void OnPointerClick(PointerEventData eventData) { if (eventData.button == PointerEventData.InputButton.Left) { if (itemData != null) { selectedSlot.SetActive(true); isSelected = true; itemDescriptionNameText.text = itemData.itemName; itemDescriptionText.text = itemData.itemDescription; itemDescriptionImage.sprite = itemData.itemImage; } } else if (eventData.button == PointerEventData.InputButton.Right) { if (itemData != null) { ToggleItemEquip(); } } } public void ToggleItemEquip() { isEquipped = !isEquipped; if (isEquipped) { PlayerStatsController.instance.EquipItem(itemData); equippedImage.SetActive(true); } else { PlayerStatsController.instance.UnequipItem(itemData); equippedImage.SetActive(false); } } }
- PlayerStatsController.cs는 장착/장착해제 상황에서의 동작을 나타냄. PlayerSO의 데이터를 가져와 아이템의 공격력 수치만큼 더해주거나 빼줌.
using UnityEngine; public class PlayerStatsController : MonoBehaviour { [SerializeField] private PlayerSO playerData; private int originalAtk; public static PlayerStatsController instance; private void Awake() { if (instance == null) { instance = this; } else { Destroy(gameObject); } } private void Start() { originalAtk = playerData.atk; } public void EquipItem(ItemSO item) { if (item.itemType == ItemSO.ItemType.Weapon) { playerData.atk += item.itemDamage; } } public void UnequipItem(ItemSO item) { if (item.itemType == ItemSO.ItemType.Weapon) { playerData.atk -= item.itemDamage; } } }
다음글이 없습니다.이전글이 없습니다.댓글