일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 |
- unity게임만들기
- c#기본문법
- 시샵
- c#문제
- unity3dservival
- c#기초문법
- 유니티게임만들기
- 스파르타코딩클럽
- unity3d게임만들기
- 유니티서바이벌게임만들기
- Unity
- c#코딩기초트레이닝
- c# 백준
- unity3d
- C++문법
- unity공부
- 티스토리챌린지
- 시샵문법
- c#프로그래머스기초문법
- c#
- 오블완
- 유니티상호작용
- C#문법
- 유니티
- 스파르타
- unity게임
- c#코테
- 유니티3dui
- c# c#프로그래머스
- 유니티공부
- Today
- Total
나 개발자 진짜 되냐?
[ Unity 3D 서바이벌 게임 만들기 6 ] 인벤토리 & 아이템 사용 본문
지금까지 한 것은
아이템과 상호작용을 통해
아이템이 플레이어에 들어가 있게 만들어주었다.
그것을 인벤토리 UI로 표현해 보자
먼저
인벤토리에
들어갈 슬롯 하나를 만들어주자
캠버스 안에 이미지 하나 만들어주고
이름은 ItemSlot
이 친구는 버튼을 눌러 장착 해제를 해줄 예정이기 때문에
버튼을 하나 만들어주고
외곽에 선을 그어줄
Outline 컴포넌트와
아이템 슬롯이라는 스크립트를 만들어서 붙여 넣어준다.
아이템 슬롯이라는 스크립트는
UI폴더 안에 만들어 주자!
채우기 ( 회색 ) : 80 80 80 255
테두리 ( 흰색 ) : 255 255 255 255
이 테두리를 한 이유는
버튼을 눌렀을 때 깜빡! 하게 해 주기 위해서 이다.
그래서 지금은 안 보이게 꺼두자!
자 다음에 이 이미지 안에다가
사진 하나, 텍스트 하나 넣어준다
사진은 아이콘 사진이 들어갈 것이고
텍스트는 아이템 개수가 들어갈 것이다.
사진은 사이즈 100 100
위치 4 4 0 ( 살짝 띄우는 느낌 )
텍스트는 60 60에 오른쪽 하단으로 가게
shift alt 눌러주고
폰트는 아까 했던
메쉬프로 폰트체와
사이즈 36
색상은 255 128 0 255로 주황으로 해준다.
위치는 사진처럼 설정해 준다.
이제 만들어진 이 오브젝트를
프리펩으로 넣어준다
왜냐면 10개 정도 만들 계획!
그다음에 우리는 인벤토리는 따로 캠버스를 만들어 주려고 한다
캠버스를 고대로 복사해서 이름을 바꾸어주자
UIInventory
아이템 슬롯을 제외하고 싹 지워준다.
그리고 Sort Order을 1로 해준다.
반대로 원래 있던 캠버스에서는
아이템슬롯 프리팹을 지워줘야 한다.
이 두 캠버스를 담을 오브젝트를 만들어보자
이렇게 해주면 굿!
자 이제 UI캠버스에
인벤토리를 더 예쁘게 만들어봅시다.
먼저 배경화면 만들 이미지 생성
색상은 카키색
50 50 50 255
그다음에 빈 오브젝트 생성하고
slots라고 지어준다.
그 안에다가 우리는
Grid Layout 컴포넌트를 추가한다.
저번에 잠깐 이야기가 나왔지만
자동정렬로
왼쪽 위부터 오른쪽으로 자동정렬 해줄 것이다.
밑에 우리는 아이콘을 120 120으로 만들어주었으니
꼭 사이즈를 적어주어야
예쁘게 정렬된다.
이제 이 안에 프리팹을 넣어주고 복사해 보자.
spacing은 칸마다 간격을 조절해 주는 친구이다.
이렇게 해줘서 13개 복사해 주면
총 14개의
인벤토리가 완성된다.
자 이제 인벤토리 아이템자리는 끝났고
이제 아이템 정보들을 적어주는 창을 만들어보자.
배경 뒤에
해주고
사이즈는
해주면
쨘
이제 이 정보창에는
아이템 이름. 아이템 설명, 스탯을 적어줄 것이다.
아이템 이름 - 폰트 굵게
아이템 설명
이 친구의 경우 설명이 길어질 수도 있기 때문에
Auto Size를 통해서
정해놓은 사이즈 내에서
글자가 커졌다가 작아졌다 해줄 수 있게 해 준다.
밑에 숫자를 통해서
최소사이즈와 최대사이즈를 정해줄 수 있다.
아이템 스텟 - 28 굵게, 노랑 255 255 0
아이템 스텟 값 - 28 굵게, 흰색
자 다음에 버튼들을 만들 것이다
총 4개
아이템 장착, 해제, 사용, 버리기
버리기 버튼을 제외하고
3개는
템에 맞게
유동적으로 true false 해줘서
그때그때 활성화되도록 만들어 줄 것이다.
장착 해제 사용
버리기
해주면
짠!
예쁜 UI 완성
자 이제 스크립트를 적어보자!!
UI 폴더 안에
UIInventory.cs 생성!
미리 까먹지 않게
UIInventory 오브젝트에 드래그드롭 해주고! 작성해 보자
그전에,
인벤토리를 일단 띄워야 하니..
tab키를 누르면 일단 우리가 띄우게 하려고 하는 부분부터
작성해 보자
< ItemSlot.cs >
using TMPro;
using UnityEngine;
using UnityEngine.UI;
public class ItemSlot : MonoBehaviour
{
public ItemData item; // 아이템 정보
public UIInventory inventory; //UIInventory 정보
public Button button; // 버튼
public Image icon; // 아이콘
public TextMeshProUGUI quatityText; // 몇개 가지고 있는지
private Outline outline; // 겉에 깜빡 거리게 하는 선
public int index; // 아이템 슬롯이 몇번째 인지 정보를 가지고 있다.
public bool equipped; // 장착 했는지 안했는지
public int quantity; // 갯수
private void Awake()
{
outline = GetComponent<Outline>();
}
private void OnEnable() // 켜주는 함수
{ // 장착 되어있을때 테두리 켜주기
outline.enabled = equipped;
}
public void Set() // 세팅
{
icon.gameObject.SetActive(true); // 흰색 배경을 켜주기
icon.sprite = item.icon; // 그 값에 이미지를 넣어준다.
// 만약에 1보다 갯수가 많으면 갯수를 입력해주고, 아니면 아무것도 안넣는다.
quatityText.text = quantity > 1 ? quantity.ToString() : string.Empty;
if (outline != null) // 방어코드, 반짝거리는 중이라면
{
outline.enabled = equipped; // 장착!
}
}
public void Clear() // 버리기
{
item = null; // 아이템 비워주고
icon.gameObject.SetActive(false); // 아이템은 꺼주자
quatityText.text = string.Empty; // text도 비우자
}
public void OnClickButton() // 버튼이 눌리면
{
inventory.SelectItem(index); // 그 인덱스에 있는 고른아이템을 보여주자.
}
}
먼저 변수를 몇 개 적어주고
UIInventory로 돌아가보자!
변수들 왕창 입력
아까 인벤토리 만들면서 다 썼던 친구들이다.
대신 여기선 버튼을 button으로 안 하고
GameObject로 해주었다.
그 밑에
private로 버튼을 눌러주었을 때 행동해야 하는
controller과
음식을 먹으면 값이 바뀌니
condition을 가져오자
다음에 start에서 초기화를 해주어야 한다.
private로 선언했기에 초기화를 해주어
이거 나야!라고 알려주고
슬롯의 경우
아까 우리가 14개 만들어주었는데
굳이 14라고 치지 않아도
자식의 개수를 가져올 수 있게 해주는 친구가 있다.
. ChildCount를 이용하면 된다.
자 다음에 바로 밭에
for 문으로 slot 배열들을 싹 초기화 시켜준다.
우리는 아까
이름 설명 스탯 값 이름 이 4 친구도 초기화를 해줘야 하는데
일일이 쓰기 힘드니
함수를 하나 만들어줘서 초기화해주자
그 함수가 바로
마지막에 ClearSelectedItemWindow이다.
이렇게 해주면
Start함수로
초기화가 싸악 된다.
유니티로 돌아가서
1차로 친구들을 넣어보자
실행해 주고
아이템 슬롯들을 눌러보면 값은 다 안 들어가 있지만
인덱스는 들어가 있는 모습을 볼 수 있다.
이렇게..ㅎㅎ
자 이제 tab키를 누르면 켜지게 해 보자
먼저 꺼지고 켜지게 하는 함수를
스크립트로 돌아가서 만들어보자
자, 이제
이 친구들은
Player Controller에서 tab키를 눌러줬을 때 작동해야 하니까
Player Controller.cs에 가서 추가해 주자.
추가.. 는 할 수 있는데
이 토글친구를 어떻게 가져올 수 있을까?
바로 델리게이트를 사용하면 된다.
이렇게 두 개 추가해 주고,
UIInventory에 Start로 가서
토글을 등록해 주고
이렇게 해주면
UIInventory에서
꺼지는 UI가 나타나고
PlayController에서는
위에 함수인
토글 커서까지 실행될 것이다.
이렇게 해주고
위에 올라가서
여기까지 했다면 우리는
tab키 이벤트를 등록해 주러 가보자
이렇게 해주면 끝!
잘되는지 확인해 보자
자 이제
우리는 아이템을 인벤토리에 넣어주어야 한다.
Player.cs에서
우리는 addItem친구에게 이벤트 등록을 해줄 건데
UIInventory.cs
토글 밑에
를 써주면 된다.
그러면
이 친구는 지금
ItemObject에
여기에서 이벤트를 시작시키게 된다.
UIInventory로 가서
< UIInventory.cs >
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.InputSystem;
public class UIInventory : MonoBehaviour
{
public ItemSlot[] slots; // 아이템 슬롯들의 정보
public GameObject inventoryWindow; // 인벤토리 창
public Transform slotPanel; // 슬롯 판넬
public Transform dropPosition; // 떨어지는 아이템 위치
[Header("Selected Item")]
private ItemSlot selectedItem; // 고른 아이템
private int selectedItemIndex; // 고른 인덱스
public TextMeshProUGUI selectedItemName; // 아이템 이름
public TextMeshProUGUI selectedItemDescription; // 아이템 설명
public TextMeshProUGUI selectedItemStatName; // 스탯 이름
public TextMeshProUGUI selectedItemStatValue; // 스탯 값
public GameObject useButton; // 사용 버튼
public GameObject equipButton; // 장착 버튼
public GameObject unEquipButton; // 장착해제 버튼
public GameObject dropButton; // 버리기 버튼
private int curEquipIndex;
private PlayerController controller; // 정보를 주고받을 컨트롤러
private PlayerCondition condition; // 정보를 주고받을 컨디션
void Start()
{
controller = CharacterManager.Instance.Player.controller; // 초기화
condition = CharacterManager.Instance.Player.condition; // 초기화
dropPosition = CharacterManager.Instance.Player.dropPosition;
controller.inventory += Toggle;
CharacterManager.Instance.Player.addItem += AddItem;
inventoryWindow.SetActive(false); // 처음에는 인벤토리창 꺼줘야한다.
slots = new ItemSlot[slotPanel.childCount]; //슬롯을 초기화해줘야한다.
for (int i = 0; i < slots.Length; i++)
{ //각각 초기화하기위한 for문
slots[i] = slotPanel.GetChild(i).GetComponent<ItemSlot>(); // 정보기입
slots[i].index = i; // 인덱스번호 지정
slots[i].inventory = this; // 인벤토리는 나야..!
//slots[i].Clear(); // 값 초기화
}
ClearSelectedItemWindow(); // 선택된 친구들도 다 초기화 시켜줘야한다.
}
public void Toggle() // 켜져있다면 false, 꺼져있다면 true
{
if (IsOpen())
{
inventoryWindow.SetActive(false);
}
else
{
inventoryWindow.SetActive(true);
}
}
public bool IsOpen() // 열려있는지 아닌지 판단해주는 bool값
{ // 하이라키창에 켜져있는지 아닌지 알 수 있는 친구
return inventoryWindow.activeInHierarchy;
}
public void AddItem() // 아이템을 추가
{ //여기 itemData는 현재 상호작용된 아이템의 데이터를 넣어놨다.
ItemData data = CharacterManager.Instance.Player.itemData;
if (data.canStack) // 아이템이 중복 가능한지
{
ItemSlot slot = GetItemStack(data); // 슬롯 가져오기
if (slot != null) // 슬롯이 비어있지 않다면
{
slot.quantity++; // 슬롯 갯수 증가
UpdateUI(); //UI 업데이트
CharacterManager.Instance.Player.itemData = null; // 아이템 데이터 없애기
return;
}
}
// 비어있는 슬롯 가져오기
ItemSlot emptySlot = GetEmptySlot();
//비어있는 슬롯이 있다면
if (emptySlot != null)
{
emptySlot.item = data; // 데이터 넣어주고
emptySlot.quantity = 1; //1로 올려주고
UpdateUI(); // 업데이트 해주고
CharacterManager.Instance.Player.itemData = null; // 아이템 데이터 없애기
return;
}
//비어있는 슬롯이 없다면
ThrowItem(data); // 아이템을 버려야한다.
CharacterManager.Instance.Player.itemData = null; // 아이템 데이터 없애기
}
public void ThrowItem(ItemData data) // 아이템 떨어뜨리기
{ //생성, 버릴 위치, 버릴 프리팹, 360도 어디에서 랜덤하게 떨어뜨리기
Instantiate(data.dropPrefab, dropPosition.position, Quaternion.Euler(Vector3.one * Random.value * 360));
}
public void UpdateUI()
{
for (int i = 0; i < slots.Length; i++) // 슬롯 배열 순회
{
if (slots[i].item != null) // 데이터가 들어가있다면
{
slots[i].Set(); // 세팅해주세요
}
else
{
slots[i].Clear(); // 없애주세요
}
}
}
ItemSlot GetItemStack(ItemData data)
{
for (int i = 0; i < slots.Length; i++) // 슬롯 배열 순회
{ // 데이터와 슬롯의 아이템이 같다면 그리고 그 갯수가 최대값이 아니면
if (slots[i].item == data && slots[i].quantity < data.maxStackAmount)
{
return slots[i]; // 슬롯을 반환
}
}
return null; // 아니면 스킵, 여기서 스킵일 경우 새롭게 슬롯을 만드는 방향으로 진행 될 것!
}
ItemSlot GetEmptySlot()
{
for (int i = 0; i < slots.Length; i++) // 슬롯 배열 순회
{
if (slots[i].item == null) // 아이템에 값이 없다면
{
return slots[i]; // 그냥 그대로 반환해주세요.없는거 보여주세요!
}
}
return null; // 꽉찼으면 그냥 꽉찬채로!
}
public void SelectItem(int index) // 우리가 고른 아이템, 슬롯번호만 받아온다.
{
if (slots[index].item == null) return; // 인덱스의 정보에 접근할건데 값이 없으면 넘기기
selectedItem = slots[index]; // 선택된 아이템의 정보를 가지고 있어보자
selectedItemIndex = index; // 선택된 아이템의 인덱스도 가지고 있자
selectedItemName.text = selectedItem.item.displayName; //각각의 요소에다가 값을 넣어준다. 여기는 이름
selectedItemDescription.text = selectedItem.item.description; // 그리고 설명을 적어준다.
//스탯이랑 스탯값도 넣어주어야하는데 모든 아이템에 스탯이 있는건 아니다.
selectedItemStatName.text = string.Empty; // 그래서 일단 값을 없앤다.
selectedItemStatValue.text = string.Empty; // 없애고 포문을 돌려서 넣어준다.
for (int i = 0; i < selectedItem.item.consumables.Length; i++) // 사용아이템이 없다면 for문이 돌지 않을것이다.
{
selectedItemStatName.text += selectedItem.item.consumables[i].type.ToString() + "\n"; // 다음을 위해 엔터
selectedItemStatValue.text += selectedItem.item.consumables[i].value.ToString() + "\n";
}
useButton.SetActive(selectedItem.item.type == ItemType.Consumable); // 버튼 type을 가져와서 넣어준다.
equipButton.SetActive(selectedItem.item.type == ItemType.Equipable && !slots[index].equipped); // 그리고 장착이 되어있지않다면
unEquipButton.SetActive(selectedItem.item.type == ItemType.Equipable && slots[index].equipped); // 장착이 되어있다면
dropButton.SetActive(true); // 없애는건 무조건 켜줘야한다.
}
void ClearSelectedItemWindow()
{
selectedItem = null;
selectedItemName.text = string.Empty; // 비우기
selectedItemDescription.text = string.Empty;
selectedItemStatName.text = string.Empty;
selectedItemStatValue.text = string.Empty;
useButton.SetActive(false); // 비활성화
equipButton.SetActive(false);
unEquipButton.SetActive(false);
dropButton.SetActive(false);
}
public void OnUseButton() // 사용하기
{
if (selectedItem.item.type == ItemType.Consumable) //type이 consumable일때만 가능하다 먹어야하니까..
{
for (int i = 0; i < selectedItem.item.consumables.Length; i++) // 아이템 조회
{
switch (selectedItem.item.consumables[i].type) //i번째 type을 보고
{ //우리는 29번째줄에 condition을 가져왔었으니
case ConsumableType.Health: // 체력 회복
condition.Heal(selectedItem.item.consumables[i].value); break;
case ConsumableType.Hunger: // 배고픔 회복
condition.Eat(selectedItem.item.consumables[i].value); break;
}
}
RemoveSelctedItem(); // 아이템 하나 빼기
}
}
public void OnDropButton() // 버리기
{
ThrowItem(selectedItem.item); // 버리기 기능
RemoveSelctedItem(); // 템을 지워주자.
}
void RemoveSelctedItem() //UI 정보 업데이트용
{
selectedItem.quantity--; // 갯수 하나 빼주기
if (selectedItem.quantity <= 0) // 0보다 작아지면
{
//if (slots[selectedItemIndex].equipped)
//{
// UnEquip(selectedItemIndex);
//}
selectedItem.item = null; //템 없애기
ClearSelectedItemWindow(); //템 없애기
}
UpdateUI();
}
public bool HasItem(ItemData item, int quantity)
{
return false;
}
}
AddItem이라고 함수이름을 짓고 만들어보자
아이템을 추가해 주는 함수로
아이템을 넣어두고
중복이 가능한지, 슬롯이 있는지 등을 본다.
이렇게 조건에 맞게
식을 구분해 준 것이다.
여기서 자주 보이는 것은
UpdateUI이다.
계속 값에 따라
그림이 바뀌어야 하고 정보도 바뀌어야 한다.
우리는 Set과 Clear 를통해
이 함수에서는
값을 빼주고 더해주는 역할만 한다.
Set과 Clear는 ItemSlot.cs에서 만져줘야 한다.
다음에 자주 보였던 함수 ( 아이템 있을 때 )
( 아이템 없을 때 )
다시 간단하게 Add에 대해 정리하면
1.
아이템을 먹는다.
자리가 있다면 넣어준다.
2.
자리가 없다면 빈 슬롯을 찾는다
3.
빈 슬롯이 있다면 넣어주고
4.
빈슬롯마저 없으면 버린다.
아이템을 버리게 될 경우
버려야 할 위치도 받아줘야 하기 때문에
Player 가서
위치받아올 변수 적어주어야 한다.
적어주고 다시 돌아와서
변수 적고,
초기화도 해준다.
초기화까지 해주었으니까
떨어뜨렸을 때 얘는 반대로 생성되어줘야 한다.
이 함수가!
이렇게 해주고
유니티로 와서
플레이어 자식으로 빈 오브젝트 생성하고
DropPosition
X : 1
Y : 0.7
Z : 0
해주고 플레이어스크립트에
드롭 오브젝트를 넣어주면 된다.
이만큼 했으면
이제 아이템을 먹을 때
그 아이템 정보가 슬롯으로 들어온다.
이제 이 슬롯을 눈에 보이게끔 해보자!
< ItemSlot.cs >
밑에 UI에 필요한 변수들을 추가했다.
그리고 테두리 깜 박은 get으로 가져왔다.
깜박거리게 해주는 함수도 만들었다.
이제 중요한
Set과 Clear을 해보자
장착
그리고
버리기
다 되었다면
유니티로 가서
ItemSlot 프리팹에 가서!!!
프리팹에 UI폴더에 넣었었다.
에다가 값을 넣어주면 된다.
Button에 뭘 넣어주냐면
그냥 ItemSlot라는 오브젝트를 넣어주면 된다.
꼭 버튼에 버튼을 넣어주어야 하는 것은 아니다.
눌릴 오브젝트를 넣어주어도 충분하다.
자라라 아이템이 신나게 들어간 모습이다.
이제 이 아이템들이
하나하나 눌렸을 때
아이템 정보가 뜨게끔 만들어주자!
먼저 UI에 있는 요소들을 건드려줘야 하니
UI인벤토리를 가서,
코드를 추가해 보자
골라진 아이템과 인덱스를 받아올 변수를 만들어주고
이렇게 작성해 주면 된다.
주석을 보며 확인해 보자!
자 이제
이 버튼들의 이벤트를 만들어 보자
사용하기
버리기
마지막으로
하나하나 눌렸을 때니까 이름을
OnClickButton으로 해주자!
유니티로 돌아가서
ItemSlot로 가서
버튼 이벤트를 추가해 주자
또
이 버튼들에게도 이벤트를 달아주어야 한다.
UIInventory 오브젝트를 달아주고
함수를 찾아서 넣어준다.
그리고 SO에 당근을 들어가서
체력과 배고픔을 동시에 해결해 주는 친구이니
두 개 추가해 보자
까지 해주면!
완성!
장착과 장착해제의 경우
버튼 추가해 주는 것도 있지만..
장착은 카메라를 따로 만들어서
다른 카메라에서는 무기가 보이고,
다른 카메라에서는 환경이 보이도록 만들어야 해서
따로 적어보기로 하자!!
'유니티를 공부해봐요! > 중급이에요!' 카테고리의 다른 글
[ Unity 3D 서바이벌 게임 만들기 8 ] 자원 캐기 (0) | 2024.10.29 |
---|---|
[ Unity 3D 서바이벌 게임 만들기 7 ] 아이템 장착 그리고 공격 (1) | 2024.10.29 |
[ Unity 3D 서바이벌 게임 만들기 5 ] 아이템 상호작용 (0) | 2024.10.29 |
[ Unity 3D 서바이벌 게임 만들기 4 ] 낮과 밤 구현 (2) | 2024.10.28 |
[ Unity 3D 서바이벌 게임 만들기 3 ] 플레이어 대미지 처리 (1) | 2024.10.28 |