Item.cs 만들기Item.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Tilemaps;
[CreateAssetMenu(menuName = "Scriptable object/Item")]
// Monobehabiour 대신 SriptableObject를 쓰는 이뉴는 최적화 관련
public class Item : ScriptableObject {
[Header("Only gameplay")]
public TileBase tile; // 그리드 보여주기
public ItemType type;
public ActionType actionType;
public Vector2Int range = new Vector2Int(5, 4);
[Header("Only UI")]
public bool stackable = true; // 여러 개 중첩할 수 있는지 아이템인지
[Header("Both")]
public Sprite image; // 인벤토리 스프라이트 보여주기
}
public enum ItemType {
BuildingBlock,
Tool
}
public enum ActionType {
Dig,
Mine
}
Items 폴더 만들기Create -> Scriptable object -> Item 선택Digging block 이름 붙이기Both Image 적당한 스프라이트 넣기InventoryItem.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
public class InventoryItem : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler {
public Item item;
[Header("UI")]
public Image image;
[HideInInspector] public Transform parentAfterDrag;
// 매개변수로 Item newItem을 받고 받은 newItem의 이미지를 이 객체의 sprite로 초기화
public void InitialiseItem(Item newItem) {
item = newItem;
image.sprite = newItem.image;
}
public void OnBeginDrag(PointerEventData eventData) {
image.raycastTarget = false;
parentAfterDrag = transform.parent;
transform.SetParent(transform.root);
}
public void OnDrag(PointerEventData eventData) {
transform.position = Input.mousePosition;
}
public void OnEndDrag(PointerEventData eventData) {
image.raycastTarget = true;
transform.SetParent(parentAfterDrag);
}
}
InventoryManager 추가 후 하이어러키 Main Camera 밑에 위치InventoryManager.cs 컴포넌트 추가InventoryManger.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class InventoryManager : MonoBehaviour {
// 만들어둔 InventorySlot을 저장할 배열
public InventorySlot[] inventorySlots;
public GameObject inventoryItemPrefab;
// 비어있는 InventoryItemSlot 순서데로 Item 생성
public void AddItem(Item item) {
// Find any empty slot
for (int i = 0; i < inventorySlots.Length; i++) {
InventorySlot slot = inventorySlots[i];
// InventoryItemSlot의 자식인 InventoryItem 가져오기
InventoryItem itemInSlot = slot.GetComponentInChildren<InventoryItem>();
// 만약 InventorySlot에 InventoryItem이 없는 경우 아이템 생성
if (itemInSlot == null) {
SpawnNewItem(item, slot);
return;
}
}
}
// 아이템을 이동할 InventorySlot이 비어있다면 해당 Slot에 아이템 스폰
void SpawnNewItem(Item item, InventorySlot slot) {
GameObject newItemGo = Istantiate(inventoryItemPrefab, slot.transform);
InventoryItem inventoryItem = newItemGo.GetComponent<InventoryItem>();
inventoryItem.InitialiseItem(item);
}
InventoryManager Inventory Slots에 여태까지 만들어둔 InventorySlot 모두 넣기IventoryManager Inventory Item Prefab에 InventoryItem 프리펩 추가Canvas 안에 Create Emtpy TestGroup 만들기TestGroup 안에 UI ->Button 3개 Spawn Item 1, Spawn Item 2, Spawn Item 3 만들기 TestGroup 에 DemoScript.cs 추가DemoScript.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DemoScript : MonoBehaviour {
public InventoryManager inventoryManager;
// 아이템을 id와 아이템 매칭을 위한 배열
public Item[] itemsToPickup;
// 아이템 id를 매개변수로 받아서 itemsToPickup에서 Item을 얻고, InventoryManager.AddItem()을 통해 인벤토리에 추가
public void PickupItem(int id) {
inventoryManager.AddItem(itemsToPickup[id]);
}
}
TestGroup Inventory Manager에 Inventory Manager 할당TestGroup Items To Pickup에 Items 할당Spawn item 1, Spawn item 2, Spawn item 3 모두에 On Click() TestGroup -> DemoScript -> PickupItem(int) 추가Spawn item에 서로 다른 id 부여InventoryManager.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class InventoryManager : MonoBehaviour {
public InventorySlot[] inventorySlots;
public GameObject inventoryItemPrefab;
public bool AddItem(Item item) {
for (int i = 0; i < inventorySlots.Length; i++) {
InventorySlot slot = inventorySlots[i];
InventoryItem itemInSlot = slot.GetComponentInChildren<InventoryItem>();
if(itemInSlot == null) {
SpawnNewItem(item, slot);
// 인벤토리에 빈공간이 있다면 true 반환
return true;
}
// 인벤토리에 빈공간이 없다면 false 반환
return false;
}
void SpawnNewItem(Item item, InventorySlot slot) {
GameObject newItemGo = Instantiate(inventoryItemPrefab, slot.transform);
InventoryItem inventoryItem = newItemGo.GetComponent<InventoryItem>();
inventoryItem.InitialiseItem(item);
}
}
DemoScript.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DemoScript : MonoBehaviour {
public InventoryManager inventoryManager;
public Item[] itemsToPickup;
public void PickupItem(int id) {
bool result = inventoryManager.AddItem(itemsToPickup[id]);
if (result == true) {
Debug.Log("Item added");
}
else {
Debug.Log("INVENTORY FULL!");
}
}
}
InventoryItem.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
public class InventoryItem : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler {
[Header("UI")]
public Image image;
public Text countText;
[HideInInspector] public Item item;
// 쌓을 수 있는 아이템을 표시하기 위해 사용
[HideInInspector] public int count = 1;
[HideInInspector] public Transform parentAfterDrag;
public void InitialiseItem(Item newItem) {
item = new Item;
image.sprite = newItem.image;
RefreshCount();
}
// 아이템 수량 리프레쉬
public void RefreshCount() {
countText.text = count.ToString();
}
public void OnBeginDrag(PointerEventData eventData) {
image.raycastTarget = false;
parentAfterDrag = transform.parent;
transform.SetParent(transform.root);
}
public OnDrag(PointerEventData eventData) {
transform.position = Input.mousePosition;
}
public OnEndDrag(PointerEventData eventData) {
image.raycastTarget = true;
transform.SetParent(parentAfterDrag);
}
}
InventoryItem 프리펩에 UI -> Text Count 추가Count 아래쪽에 위치Text = 1로 설정 Font Style Bold로 설정Color 하얀색으로 설정InventoryItem에 Text 추가InventoryItem.cs
. . .
public RefreshCount() {
countText.text = count.ToString();
// 1 보다 클 때만 숫자 표시
bool textActive = count > 1;
countText.gameObject.SetActive(textActive);
}
. . .
InventoryManager.cs
using Systems.Collections;
using System.Collections.Generic;
using UnityEngine;
public class InventoryManager : MonoBehaviour {
// 최대 중첩 횟수
public int maxStackedItems = 4;
public InventorySlot[] inventorySlots;
public GameObject inventoryItemPrefab;
public bool AddItem(Item item) {
// 모든 아이템 슬롯을 대상으로 진행
for(int i = 0; i < inventorySlots.Length; i++) {
// i 번째 InventorySlot을 가져와서
InventorySlot slot = inventorySlots[i];
// 해당 Slot에 있는 InventoryItem을 가져옴
InventoryItem itemInSlot = slot.GetComponenetInChildren<InventoryItem>();
// 가져온 아이템이 null이 아니고, 같은 아이템 이고, 갯수가 4보다 작다면
// 아이템 갯수 증가
if(itemInSlot != null &&
itemInSlot.item == item &&
itemInSlot.count < maxStackedItems ) {
itemInSlot.count++;
itemInSlot.RefreshCont();
return true;
}
}
// Find any empty slot
for(int i = 0; i < inventorySlots.Length; i++) {
InventorySlot slot = inventorySlots[i];
InventoryItem itemInSlot = slot.GetComponenetInChildren<InventoryItem>();
if (itemInSlot == null) {
SpawnNewItem(item, slot);
return true;
}
}
return false;
}
void SpawnNewItem(Item item, InventorySlot slot) {
GameObject newItemGo = Instantiate(inventoryItemPrefab, slot.transform);
InventoryItem inventoryItem = newItemGo.GetComponent<InventoryItem>();
inventoryItem.InitialiseItem(item);
}
}
InventorySlot.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
public class InventorySlot : MonoBehaviour, IDropHandler {
public Image image;
// 선택됐으면 다른 색으로 표시
public Color selectedColor, notSelectedColor;
private void Awake() {
Deselect();
}
public void Select() {
image.color = selectedColor;
}
public void Deselect() {
image.color = notSelectedColor;
}
// Drag and Drop
public void OnDrop(PointerEventData eventData) {
if (transform.childCount == 0) {
InventoryItem inventoryItem = eventData.pointerDrag.GetComponenet<InventoryItem>();
inventoryItem.parentAfterDrag = transform;
}
}
}
InventoryManager.cs
using Systems.Collections;
using System.Collections.Generic;
using UnityEngine;
public class InventoryManager : MonoBehaviour {
// 최대 중첩 횟수
public int maxStackedItems = 4;
public InventorySlot[] inventorySlots;
public GameObject inventoryItemPrefab;
/*********************************************
추 가 된 부 분
**********************************************/
// Default selectedSlot 번호
int selectedSlot = -1;
private void Start() {
ChangeSelectedSlot(0);
}
void ChangeSelectedSlot(int newValue) {
// 선택된 인덱스가 0 이상인지 검사
if (selectedSlot >= 0) {
inventorySlots[selectedSlot].Deselect();
}
inventorySlots[newValue].Select();
selectedSlot = newValue;
}
/*********************************************
추 가 된 부 분
**********************************************/
public bool AddItem(Item item) {
// 모든 아이템 슬롯을 대상으로 진행
for(int i = 0; i < inventorySlots.Length; i++) {
// i 번째 InventorySlot을 가져와서
InventorySlot slot = inventorySlots[i];
// 해당 Slot에 있는 InventoryItem을 가져옴
InventoryItem itemInSlot = slot.GetComponenetInChildren<InventoryItem>();
// 가져온 아이템이 null이 아니고, 같은 아이템 이고, 갯수가 4보다 작다면
// 아이템 갯수 증가
if(itemInSlot != null &&
itemInSlot.item == item &&
itemInSlot.count < maxStackedItems ) {
itemInSlot.count++;
itemInSlot.RefreshCont();
return true;
}
}
// Find any empty slot
for(int i = 0; i < inventorySlots.Length; i++) {
InventorySlot slot = inventorySlots[i];
InventoryItem itemInSlot = slot.GetComponenetInChildren<InventoryItem>();
if (itemInSlot == null) {
SpawnNewItem(item, slot);
return true;
}
}
return false;
}
void SpawnNewItem(Item item, InventorySlot slot) {
GameObject newItemGo = Instantiate(inventoryItemPrefab, slot.transform);
InventoryItem inventoryItem = newItemGo.GetComponent<InventoryItem>();
inventoryItem.InitialiseItem(item);
}
}
inventorySlot 프래팹 Image에 이미지 추가InventoryManager.cs
using Systems.Collections;
using System.Collections.Generic;
using UnityEngine;
public class InventoryManager : MonoBehaviour {
// 최대 중첩 횟수
public int maxStackedItems = 4;
public InventorySlot[] inventorySlots;
public GameObject inventoryItemPrefab;
// Default selectedSlot 번호
int selectedSlot = -1;
private void Start() {
ChangeSelectedSlot(0);
}
/*********************************************
추 가 된 부 분
**********************************************/
private void Update() {
if (Input.inputString != null) {
bool isNumber = int.TryParse(Input.inputString, out int number);
if(isNumber && number > 0 && number < 8) {
ChangeSelectedSlot(number - 1);
}
}
}
/*********************************************
추 가 된 부 분
**********************************************/
void ChangeSelectedSlot(int newValue) {
// 선택된 인덱스가 0 이상인지 검사
if (selectedSlot >= 0) {
inventorySlots[selectedSlot].Deselect();
}
inventorySlots[newValue].Select();
selectedSlot = newValue;
}
public bool AddItem(Item item) {
// 모든 아이템 슬롯을 대상으로 진행
for(int i = 0; i < inventorySlots.Length; i++) {
// i 번째 InventorySlot을 가져와서
InventorySlot slot = inventorySlots[i];
// 해당 Slot에 있는 InventoryItem을 가져옴
InventoryItem itemInSlot = slot.GetComponenetInChildren<InventoryItem>();
// 가져온 아이템이 null이 아니고, 같은 아이템 이고, 갯수가 4보다 작다면
// 아이템 갯수 증가
if(itemInSlot != null &&
itemInSlot.item == item &&
itemInSlot.count < maxStackedItems ) {
itemInSlot.count++;
itemInSlot.RefreshCont();
return true;
}
}
// Find any empty slot
for(int i = 0; i < inventorySlots.Length; i++) {
InventorySlot slot = inventorySlots[i];
InventoryItem itemInSlot = slot.GetComponenetInChildren<InventoryItem>();
if (itemInSlot == null) {
SpawnNewItem(item, slot);
return true;
}
}
return false;
}
void SpawnNewItem(Item item, InventorySlot slot) {
GameObject newItemGo = Instantiate(inventoryItemPrefab, slot.transform);
InventoryItem inventoryItem = newItemGo.GetComponent<InventoryItem>();
inventoryItem.InitialiseItem(item);
}
}