Chapter 6-2. 퀵슬롯 : 퀵슬롯 심화
카테고리: Unity Lesson 3
태그: Unity Game Engine
인프런에 있는 케이디님의 [유니티 3D] 실전! 생존게임 만들기 - Advanced 강의를 듣고 정리한 필기입니다. 😀
🌜 강의 들으러 가기 Click
Chapter 6. 퀵슬롯
무기 뿐만 아니라 활성화 퀵슬롯에 있는 다른 아이템들도 사용 가능 하도록 구현 할 것.
🚖 맨 손에 아이템 들기
- 활성화 된 퀵슬롯의 포션 같은 소모품 아이템을 맨손 오른손 끝에 들고 있을 수 있게 (무기 제외)
아이템 들 위치
맨손 Hand
의 자식들 중 오른손 끝에 해당하는 오브젝트인 DownArmR_End
오브젝트 자식으로, 아이템을 들고 있는 위치로서 기능할 빈 오브젝트 ItemPos
를 추가해주었다.
ItemPos
이 오브젝트가 아이템을 들고 있는 위치가 될 것이다. 이 위치에 아이템 프리팹을 생성할 것.- 로컬 회전축이 월드 기준 회전축과 일치할 수 있도록 z 축으로 90 도 회전하였다.
📜QuickSlotController.cs
[SerializeField] private Transform tf_ItemPos; // 손 끝 오브젝트. 손 끝에 아이템이 위치도록 Transform 정보 받아올 것
public static GameObject go_HandItem; // 손에 든 아이템. static인 이유는 이거 하나 받아오려고 📜QuickSlotController 로딩하는건 낭비라서
private void Execute()
{
if (quickSlots[selectedSlot].item != null)
{
if (quickSlots[selectedSlot].item.itemType == Item.ItemType.Equipment)
StartCoroutine(theWeaponManager.ChangeWeaponCoroutine(quickSlots[selectedSlot].item.weaponType, quickSlots[selectedSlot].item.itemName));
else if (quickSlots[selectedSlot].item.itemType == Item.ItemType.Used)
ChangeHand(quickSlots[selectedSlot].item);
else
ChangeHand();
}
else
{
ChangeHand();
}
}
private void ChangeHand(Item _item = null)
{
StartCoroutine(theWeaponManager.ChangeWeaponCoroutine("HAND", "맨손"));
if (_item != null)
StartCoroutine(HandItemCoroutine());
}
IEnumerator HandItemCoroutine()
{
HandController.isActivate = false;
yield return new WaitUntil(() => HandController.isActivate); // 맨손 교체의 마지막 과정
go_HandItem = Instantiate(quickSlots[selectedSlot].item.itemPrefab, tf_ItemPos.position, tf_ItemPos.rotation);
go_HandItem.GetComponent<Rigidbody>().isKinematic = true; // 중력 영향 X
go_HandItem.GetComponent<Collider>().enabled = false; // 콜라이더 끔 (플레이어와 충돌하지 않게)
go_HandItem.tag = "Untagged"; // 획득 안되도록 레이어 태그 바꿈
go_HandItem.layer = 8; // "Weapon" 레이어는 int
go_HandItem.transform.SetParent(tf_ItemPos);
}
tf_ItemPos
: 손 끝 오브젝트. 오른손의ItemPos
할당할 것.go_HandItem
: 현재 손에 들고 있는 아이템.- 파괴하거나 생성하거나 할 수 있도록 GameObject로 선언하였고
static
으로 선언하여 다른 스크립트에서도 접근할 수 있도록 한다.- 이거 하나로 📜QuickSlotController.cs 전체를 로딩하기엔 낭비라 statc 으로 선언
- Execute()
- 활성화된 퀵슬롯에 무기가 있다면 해당 무기로 교체
- 활성화된 퀵슬롯에 포션같은 소비 아이템이 있다면 맨손으로 교체하고 해당 아이템을 손에 들도록
- ChangeHand(quickSlots[selectedSlot].item); 호출
- 활성화된 퀵슬롯에 기타 아이템이 있다면 그냥 맨손으로 교체까지만
- ChangeHand(); 호출
- ChangeHand(Item _item = null)
- 맨손으로 교체한 후
- 해당 아이템 손에 들기
- HandItemCoroutine() 호출
- HandItemCoroutine()
- 👉 손에 아이템 들기!
- 우선 맨손 교체가 완료될 때까지 기다린다. (이래서 코루틴) 맨손이 된 후 아이템을 들어야 하니까
isActivate
false 한번 해주고 StartCoroutine(theWeaponManager.ChangeWeaponCoroutine(“HAND”, “맨손”)); 실행이 전부 끝나면isActivate
가 True가 되는데,isActivate
가 True가 될 때까지 기다린다.- ⭐ 코루틴
WaitUntil
-
- Bool 타입을 리턴하는 함수의 포인터 혹은 람다 함수를 인수로 넘기고 True 값을 리턴할 때까지 대기한다.
-
- 해당 아이템을
go_HandItem
에 생성- 아이템 프리팹을 손 위치에 생성
- 생성한 아이템의 Rigidbody 의 물리를 꺼준다.
isKinematic
을 True로.- 물리 현상이 활성화 되면 손에 붙지 않고 중력을 받아 떨어지게 된다.
- 생성한 아이템의 Collider 를 꺼준다.
- 플레이어의 손과 충돌하여 튕겨나가지 않고 손에 얌전히 붙어있도록
- 손에 들고 있을 아이템은 획득이 안되도록
Item
으로 되어 있던 태그, 레이어를 바꾼다.- 생성한 아이템의 태그를 “Untagged” 로 바꾼다.
- 생성한 아이템의 레이어를 “Weapon”으로 바꾼다. 레이어는 int 이므로 “Weapon”에 해당하는 정수로 할당
Weapon Camera
에 렌더링 될 수 있도록 한다. 메인 카메라보다 깊이가 우선되어 렌더링 되는 카메라이므로 손 위에 아이템이 그려질 것이다.
- 생성한 아이템의 부모를 오른손 끝 위치 오브젝트로.
- 우선 맨손 교체가 완료될 때까지 기다린다. (이래서 코루틴) 맨손이 된 후 아이템을 들어야 하니까
- 👉 손에 아이템 들기!
tf_ItemPos
에 오른 손 끝 오브젝트였던 ItemPos
할당
🚖 활성화 퀵슬롯 아이템 소비하기
먹는 애니메이션
Any State
👉Hand_Item
Item
트리거 파라미터가 발동될 때- Has Exit Time 해제
Hand_Item
👉Hand_Idle
- Has Exit Time 체크
- Exit Time 1
- 끝까지 다 재생되면 정지 애니메이션으로
📜QuickSlotController.cs
[SerializeField]
private ItemEffectDatabase theItemEffectDatabase;
public void EatItem()
{
theItemEffectDatabase.UseItem(quickSlots[selectedSlot].item);
quickSlots[selectedSlot].SetSlotCount(-1);
if (quickSlots[selectedSlot].itemCount <= 0)
Destroy(go_HandItem);
}
- EatItem() 👉 아이템 소비. 📜HandController.cs 에서 인벤토리 안켜져 있고 그냥 우클할 때 호출된다. 활성화 퀵슬롯에 있는 아이템이 바로 소비될 수 있도록.
- 실제로 소비하는 처리 (스태미나, 배고픔 증가 등등 이런 처리)
- 📜ItemEffectDatabase.cs 의 UseItem 함수에 퀵슬롯 아이템 넘겨 줌
- 강의에선 다루지 않았던 부분인데 추가해보았다.
- 실제로 아이템을 먹는 처리가 이루어 져야 하므로
- 📜ItemEffectDatabase.cs 의 UseItem 함수에 퀵슬롯 아이템 넘겨 줌
- 슬롯에서 갯수 1 차감
- 슬롯 아이템 갯수가 0 이하면
- 손에 들고 있는 아이템 파괴
- 실제로 소비하는 처리 (스태미나, 배고픔 증가 등등 이런 처리)
📜Slot.cs
public void OnPointerClick(PointerEventData eventData)
{
if(eventData.button == PointerEventData.InputButton.Right)
{
if (item != null)
{
theItemEffectDatabase.UseItem(item);
if(item.itemType == Item.ItemType.Used)
SetSlotCount(-1);
}
}
}
public void SetSlotCount(int _count)
{
itemCount += _count;
text_Count.text = itemCount.ToString();
if (itemCount <= 0)
{
ClearSlot();
if (isQuickSlot)
if (QuickSlotController.go_HandItem != null)
if (QuickSlotController.go_HandItem.GetComponent<ItemPickUp>().item.itemType == Item.ItemType.Used)
Destroy(QuickSlotController.go_HandItem);
}
}
아이템 ‘슬롯’에다가 우클릭 하여 소비할 때 (활성화 퀵슬롯 말고 그냥 인벤토리에서든 어디서든)
- 아이템 갯수가 0 이하에 도달했을 때
- 만약 우클릭 한 슬롯이 퀵슬롯이었다면!! 게다가 아이템도 들고 있는 상태이며 심지어 포션 같은 아이템이라면!
- 손에 든 아이템도 파괴해 주어야 한다.
- 만약 우클릭 한 슬롯이 퀵슬롯이었다면!! 게다가 아이템도 들고 있는 상태이며 심지어 포션 같은 아이템이라면!
강의에선 다루지 않았던 부분인데 추가해보았다. 활성화 퀵슬롯을 직접 슬롯에다가 우클릭으로 다 소비할 땐 손에 든 아이템이 파괴되지 않길래
📜HandController.cs
[SerializeField]
private QuickSlotController theQuickSlotController;
void Update()
{
if (isActivate && !Inventory.invectoryActivated)
{
if (QuickSlotController.go_HandItem == null)
TryAttack();
else
TryEating();
}
}
private void TryEating()
{
if (Input.GetButtonDown("Fire2"))
{
currentCloseWeapon.anim.SetTrigger("Eat");
theQuickSlotController.EatItem();
}
}
인벤토리 안켜진 상태 + 그냥 아이템 들고 있는 상태에서 아이템을 소비하려면
- 맨손 상태에서 좌클릭 - 공격
- 아이템 들고 있는 맨손 산태에서 우클릭 - 아이템 먹기
- 아무것도 안들고 있다면 맨손 공격
- 맨손인 상태고 인벤토리가 활성화 되어 있지 않을 때
- 손에 들고 있는 아이템이 없다면 공격을 할 수 있는 상태다. (좌클릭 감지)
- 손에 들고 있는 아이템이 있다면 아이템 소비를 할 수 있는 상태다.(우클릭 감지)
- TryEating()
- 마우스 우클릭이 들어온다면
- 아이템 먹는 애니메이션 재생 후
- EatItem() 아이템 갯수 1 차감 후 0 에 도달했다면 아이템 파괴
- 마우스 우클릭이 들어온다면
- TryEating()
📜WeaponManager.cs
private void CancelPreWeaponAction()
{
switch(currentWeaponType)
{
case "GUN":
theGunController.CancelFineSight();
theGunController.CancelReload();
GunController.isActivate = false;
break;
case "HAND":
HandController.isActivate = false;
if (QuickSlotController.go_HandItem != null)
Destroy(QuickSlotController.go_HandItem);
break;
case "AXE":
AxeController.isActivate = false;
break;
case "PICKAXE":
PickaxeController.isActivate = false;
break;
}
}
맨손인 상태에서 다른 무기로 바꾼다면 (맨손 👉 맨손 도 포함)
- 아이템을 들고 있는 맨손인 상태에서 그냥 맨손이든 총이든 다른 무기로 교체하려면 현재 손에 들고 있는 아이템만 파괴한다.
📜InputNumber.cs
IEnumerator DropItemCorountine(int _num)
{
for (int i = 0; i < _num; i++)
{
if(DragSlot.instance.dragSlot.item.itemPrefab != null)
{
Instantiate(DragSlot.instance.dragSlot.item.itemPrefab,
thePlayer.transform.position + thePlayer.transform.forward,
Quaternion.identity);
}
DragSlot.instance.dragSlot.SetSlotCount(-1);
yield return new WaitForSeconds(0.05f);
}
if (int.Parse(text_Preview.text) == _num) // 모두 버리는거면
if (QuickSlotController.go_HandItem != null) // 손에 아이템 들고 있다면
Destroy(QuickSlotController.go_HandItem);
DragSlot.instance.dragSlot = null;
go_Base.SetActive(false);
activated = false;
}
if (int.Parse(text_Preview.text) == _num) // 모두 버리는거면
if (QuickSlotController.go_HandItem != null) // 손에 아이템 들고 있다면
Destroy(QuickSlotController.go_HandItem);
아이템을 드래그 하여 버릴 때 인풋 필드
- 만약 모두 버리는거면 손에 들고 있는 아이템도 파괴되도록
- Placeholder 에는 자동으로 해당 아이템을 갖고 잇는 최대 개수가 들어가도록 하였으므로 입력한 수와 Placeholder 텍스트가 같다면 모두 버리겠다는 뜻
🚖 퀵슬롯의 쿨타임
쿨타임이 지나야만 아이템 사용이 가능하도록.
- 쿨타임을 가질 때
- 퀵슬롯에 방금 가져다 놓은 아이템일 때
- 해당 아이템을 사용했을 때
쿨타임 UI 만들기
퀵슬롯의 슬롯들에게 자식으로 쿨타임 이미지 CoolTime_Image
오브젝트를 추가해주었다. 이미지 컴포넌트를 추가한 빈 오브젝트다.
- 8 개의
CoolTime_Image
를 PosX 를 0 으로 해준다.- 자신의 부모인 슬롯과 동일한 위치에 있을 수 있도록
- 쿨타임은 360도 Filled 로 표현할 것이기 때문에 100 % 의 상태, 즉 Fill Amount 값이 1 일 때의 상태를 좀 더 까만 슬롯 이미지로 해주기 위하여
CoolTime_Image
들의 소스 이미지는 기본 슬롯 이미지에 검정 컬러에 투명함을 올려준 이미지로 사용하였다. - 이미지 타입은 Filled
- 360도
- Fill Origin 은 Top 부터 시작하도록.
- Fill Amount 기본 값은 0 으로 일단 해두기.
📜QuickSlotController.cs
[SerializeField] private Image[] img_CoolTime; // 퀵슬롯 쿨타임 이미지들
// 쿨타임 내용
[SerializeField]
private float coolTime; // 정해짐 쿨타임 [SerializeField]로 유니티 인스펙터에서 결정
private float currentCoolTime; // coolTime 을 시작점으로 0 이 될 때까지 감소 업뎃
private bool isCoolTime; // 현재 쿨타임 중인지
void Update()
{
TryInputNumber();
CoolTimeCalc();
}
private void CoolTimeReset()
{
currentCoolTime = coolTime;
isCoolTime = true;
}
private void CoolTimeCalc()
{
if (isCoolTime)
{
currentCoolTime -= Time.deltaTime; // 1 초에 1 씩 감소
for (int i = 0; i < img_CoolTime.Length; i++)
img_CoolTime[i].fillAmount = currentCoolTime / coolTime;
if (currentCoolTime <= 0)
isCoolTime = false;
}
}
private void TryInputNumber()
{
if(!isCoolTime)
{
if (Input.GetKeyDown(KeyCode.Alpha1))
ChangeSlot(0);
else if (Input.GetKeyDown(KeyCode.Alpha2))
ChangeSlot(1);
else if (Input.GetKeyDown(KeyCode.Alpha3))
ChangeSlot(2);
else if (Input.GetKeyDown(KeyCode.Alpha4))
ChangeSlot(3);
else if (Input.GetKeyDown(KeyCode.Alpha5))
ChangeSlot(4);
else if (Input.GetKeyDown(KeyCode.Alpha6))
ChangeSlot(5);
else if (Input.GetKeyDown(KeyCode.Alpha7))
ChangeSlot(6);
else if (Input.GetKeyDown(KeyCode.Alpha8))
ChangeSlot(7);
}
}
private void Execute()
{
CoolTimeReset();
if (quickSlots[selectedSlot].item != null)
{
if (quickSlots[selectedSlot].item.itemType == Item.ItemType.Equipment)
StartCoroutine(theWeaponManager.ChangeWeaponCoroutine(quickSlots[selectedSlot].item.weaponType, quickSlots[selectedSlot].item.itemName));
else if (quickSlots[selectedSlot].item.itemType == Item.ItemType.Used)
ChangeHand(quickSlots[selectedSlot].item);
else
ChangeHand();
}
else
{
ChangeHand();
}
}
public void EatItem()
{
CoolTimeReset();
theItemEffectDatabase.UseItem(quickSlots[selectedSlot].item);
quickSlots[selectedSlot].SetSlotCount(-1);
if (quickSlots[selectedSlot].itemCount <= 0)
Destroy(go_HandItem);
}
public bool GetIsCoolTime()
{
return isCoolTime;
}
- CoolTimeCalc() 👉 현재 쿨타임 상태라면 매 프레임마다
currentCoolTime
쿨타임 시간 업데이트- 쿨타임 중일 때만
isCoolTime
, 매프레임마다 실행 된다. currentCoolTime
은 1 프레임당Time.deltaTime
씩 차감 (= 1 초에 1 씩 차감)- 정해진
coolTime
에서 시작하여 0 이 될 때까지 감소coolTime
값이 3 이라면currentCoolTime
은 3 초 동안 0 을 향해 감소한다.
- 정해진
- 퀵슬롯 슬롯들의 쿨타임 이미지의 Fill Amount 값을 업데이트 한다.
currentCoolTime
가 0 에 도달하면isCoolTime
을 False로 만들어, 다음 프레임부터는 CoolTimeCalc() 함수가 더 이상 실행 되지 않음.
- 쿨타임 중일 때만
- CoolTimeReset() 👉 쿨타임을 돌리기 시작한다!
currentCoolTime
을 다시coolTime
으로 초기화isCoolTime
을 True 로 만듬. 다음 프레임 부터 CoolTimeCalc() 함수가 실행될 것
- GetIsCoolTime()
- 📜Slot.cs 에서 마우스 우클로 슬롯에 있는 아이템 소비시 쿨타임 중인 아이템을 사용하지 못하게 하기 위하여
isCoolTime
을 리턴받기 위한 함수
- 📜Slot.cs 에서 마우스 우클로 슬롯에 있는 아이템 소비시 쿨타임 중인 아이템을 사용하지 못하게 하기 위하여
- 쿨타임 돌릴 때
- TryInputNumber()
- 쿨타임 중이 아닐 때만 키보드 넘버 입력할 수 잇음 (활성화 퀵슬롯 바꾸기)
- Execute()
- 활성화 슬롯 (무기 교체 혹은 아이템) 사용하고나면 쿨타임 有
- CoolTimeReset() 쿨타임 돌리기
- EatItem()
- 활성화 슬롯 아이템 소비할 때 쿨타임 有
- CoolTimeReset() 쿨타임 돌리기
- TryInputNumber()
- 쿨타임 이미지 배열 할당
coolTime
쿨타임 3 초로 설정
📜HandController.cs
private void TryEating()
{
if (Input.GetButtonDown("Fire2") && theQuickSlotController.GetIsCoolTime())
{
currentCloseWeapon.anim.SetTrigger("Eat");
theQuickSlotController.EatItem();
}
}
인벤토리 활성화 되있을 때말고 그냥 게임 중에 우클릭 입력이 들어오면 손에 들고 있는 아이템을 소비한다. 이때 쿨타임 중이면 못 먹게 하도록 조건을 추가해주었다.
📜ItemEffectDatabase.cs
// 📜QuickSlotController 👉 📜Slot 징검다리
public bool GetIsCoolTime()
{
return theQuickSlotController.GetIsCoolTime();
}
강의에선 다루지 않았던 부분인데 추가해보았다. 📜Slot.cs 에서 마우스 우클로 슬롯에 있는 아이템 소비시 쿨타임 중인 아이템을 사용하지 못하게 하기 위하여 추가. 📜Slot.cs 은 프리팹이므로 로딩을 줄이기 위하여 📜Slot.cs 에서 필요한 컴포넌트들은 📜ItemEffectDatabase.cs에서 징검 다리 역할로 로딩하여 가져오고 있음
📜Slot.cs
// 마우스 클릭 이벤트
public void OnPointerClick(PointerEventData eventData)
{
if(eventData.button == PointerEventData.InputButton.Right)
{
if (item != null)
{
if (!isQuickSlot) // 인벤토리 우클
{
theItemEffectDatabase.UseItem(item);
if (item.itemType == Item.ItemType.Used)
SetSlotCount(-1);
}
else if (!theItemEffectDatabase.GetIsCoolTime()) // 퀵슬롯 우클 + ✨쿨타임 중이 아닐 때✨
{
theItemEffectDatabase.UseItem(item);
if (item.itemType == Item.ItemType.Used)
SetSlotCount(-1);
}
}
}
}
강의에선 다루지 않았던 부분인데 추가해보았다. 퀵슬롯에 있는 슬롯에다가 우클을 했을 땐 쿨타임이 아닐 때만 사용할 수 있어야 한다.
🚖 퀵슬롯 ON OFF
필요할 때만 퀵슬롯이 등장하도록
- 인벤토리 활성화 될 때 퀵슬롯도 같이 ON
- 인벤토리 비활성화 될 때 퀵슬롯도 같이 OFF
- 퀵슬롯을 바꿀 때 퀵슬롯 ON
- 활성화 퀵슬롯에 있는 아이템 소비할 때도 ON
퀵슬롯에 애니메이션 추가
크로스 헤어 애니메이션 만들던 과정과 비슷. 참고하기.
애니메이션 클립
QuickSlot
오브젝트에 Animator 컴포넌트를 추가한 후, “QuickSlotAnimController” 애니메이션 컨트롤러를 할당했다. 그런 후 QuickSlot
오브젝트를 클릭한 상태에서 Animation 윈도우를 켜서 QuickSlot
오브젝트의 애니메이션 생성
- 1️⃣ QuickSlot_Anim_Appear
- 퀵슬롯 나타나기
- PosX 를 대충 0 으로 녹화하기 (원래 위치로 녹화)
- 퀵슬롯 나타나기
- 2️⃣ QuickSlot_Anim_Disappear
- 퀵슬롯 사라지게 하기
- PosY 를 -100 정도로 녹화하여 사라지게 하기
- 퀵슬롯 사라지게 하기
- 두 애니메이션 파일의 Loop Time를 해제해준다.
애니메이션 컨트롤러
- Bool
Appear
파라미터 추가 - 퀵슬롯 사라지기(디폴트) 👉 퀵슬롯 나타나기
Appear
가 True 일 때- Has Exit Time 해제
- 퀵슬롯 나타나기 👉 퀵슬롯 사라지기
Appear
가 False 일 때- Has Exit Time 해제
📜QuickSlotController.cs
// 퀵슬롯 등장 내용
[SerializeField] private float appearTime; // 퀵슬롯이 나타나는 동안의 시간
private float currentAppearTime;
private bool isAppear;
private Animator anim;
void Start()
{
quickSlots = tf_parent.GetComponentsInChildren<Slot>();
selectedSlot = 0;
anim = GetComponent<Animator>();
}
void Update()
{
TryInputNumber();
CoolTimeCalc();
AppearCalc();
}
private void AppearReset()
{
currentAppearTime = appearTime;
isAppear = true;
anim.SetBool("Appear", isAppear);
}
private void AppearCalc()
{
if (Inventory.invectoryActivated) // 인벤토리 켜져있을 땐 퀵슬롯도 늘 활성화
AppearReset();
else // 인벤토리가 켜져 있지 않을때만 쿨타임 깎아야 함
{
if (isAppear)
{
currentAppearTime -= Time.deltaTime; // 1초에 1감소
if (currentAppearTime <= 0)
{
isAppear = false;
anim.SetBool("Appear", isAppear);
}
}
}
}
- AppearCalc() 👉 현재 퀵슬롯 활성화 상태라면 매 프레임마다
currentAppearTime
퀵슬롯 활성화 시간 업데이트- 인벤토리가 활성화 되있을 땐 퀵슬롯도 내내 활성화 하도록 한다.
- 인벤토리가 비활성화 상태일땐 퀵슬롯은
appearTime
시간 동안만 활성화 된 후 그 이후엔 비활성화- 퀵슬롯 활성화 중일 때만
isCoolTime
, 매프레임마다 실행 된다.currentAppearTime
은 1 프레임당Time.deltaTime
씩 차감 (= 1 초에 1 씩 차감)- 정해진
appearTime
에서 시작하여 0 이 될 때까지 감소 appearTime
값이 3 이라면currentAppearTime
은 3 초 동안 0 을 향해 감소한다.
- 퀵슬롯 활성화 중일 때만
currentAppearTime
가 0 에 도달하면isAppearTime
을 False로 만들어, 다음 프레임부터는 AppearCalc() 함수가 더 이상 실행 되지 않음.- 퀵슬롯이 사라지는 애니메이션 재생
- AppearReset() 👉 퀵슬롯을 활성화 한다.
currentAppearTime
을 다시isAppearTime
으로 초기화isAppearTime
을 True 로 만듬. 다음 프레임 부터 AppearCalc() 함수가 실행될 것- 퀵슬롯이 생성되는 애니메이션 재생
appearTime
3 으로 설정 👉 퀵슬롯은 인벤토리 비활성 상태라면 3 초 있다가 사라지게 됨
📜Slot.cs
// 마우스 드래그가 시작 됐을 때 발생하는 이벤트
public void OnBeginDrag(PointerEventData eventData)
{
if(item != null && Inventory.invectoryActivated)
{
DragSlot.instance.dragSlot = this;
DragSlot.instance.DragSetImage(itemImage);
DragSlot.instance.transform.position = eventData.position;
}
}
인벤토리 상태가 아닐 땐 슬롯 드래그가 안되게 한다. (인벤토리 끄면 퀵슬롯도 곧 사라지니 인벤토리 상태가 아닐 때는 퀵슬롯에서 아이템 드래그 못하게 했다.)
🚖 아이템 획득시 퀵슬롯부터 채우기
아이템을 획득하면 기본으로 인벤토리로 가게 되는데, 아이템을 먹으면 퀵슬롯에 우선적으로 채워지도록 하자.
📜Inventory.cs
[SerializeField]
private GameObject go_QuickSlotParent; // 퀵슬롯 영역
private Slot[] slots; // 인벤토리 슬롯들
private Slot[] quickSlots; // 퀵슬롯의 슬롯들
private bool isNotPut;
void Start()
{
slots = go_SlotsParent.GetComponentsInChildren<Slot>();
quickSlots = go_QuickSlotParent.GetComponentsInChildren<Slot>();
}
public void AcquireItem(Item _item, int _count = 1)
{
PutSlot(quickSlots, _item, _count);
if (isNotPut)
PutSlot(slots, _item, _count);
if (isNotPut)
{
Debug.Log("아이템이 꽉 찼습니다.");
}
}
private void PutSlot(Slot[] _slots, Item _item, int _count)
{
if (Item.ItemType.Equipment != _item.itemType)
{
for (int i = 0; i < _slots.Length; i++)
{
if (_slots[i].item != null)
{
if (_slots[i].item.itemName == _item.itemName)
{
_slots[i].SetSlotCount(_count);
isNotPut = false;
return;
}
}
}
}
for (int i = 0; i < _slots.Length; i++)
{
if (_slots[i].item == null)
{
_slots[i].AddItem(_item, _count);
isNotPut = false;
return;
}
}
isNotPut = true;
}
isNotPut
아이템을 슬롯에 넣었다면 True, 못 넣었다면 False.slots
인벤토리 슬롯들,quickSlots
퀵슬롯의 슬롯들.- PutSlot(Slot[] _slots, Item _item, int _count)
- Slot 타입의 배열 (
slots
,quickSlots
받을 수 있음) 중에서 아이템을 넣을 수 있는 슬롯을 찾아 넣는다. - 아이템 넣을 슬롯을 찾을 때마다
isNotPut
을 False로 하고 끝냄. 아이템 넣을 슬롯을 못 찾았다면 최종적으로isNotPut
이 True가 됨.
- Slot 타입의 배열 (
- AcquireItem(Item _item, int _count = 1)
- 우선 퀵슬롯의 슬롯들에게 넣기 시도
quickSlots
을 PutSlot 에 넘김
- 퀵슬롯에 못 넣었다면 인벤토리에 넣기 시도
slots
을 PutSlot 에 넘김
- 둘 다 못 넣었다면, 즉 아직도
isNotPut
가 true라면 인벤토리, 퀵슬롯 둘 다 꽉차서 넣을 수 없는 상태
- 우선 퀵슬롯의 슬롯들에게 넣기 시도
go_QuickSlotParent
에 퀵슬롯 영역인 Contents
할당.
🚖 아이템을 꽉 차서 먹을 수가 없다면
강의에선 다루지 않았던 부분인데 추가해보았다.
인벤토리, 퀵슬롯 둘 다 꽉차서 넣을 수 없다면 아이템을 먹을 수 없다는 텍스트 띄우기.
📜ActionController.cs
먹을 수 있는 아이템 텍스트를 띄우는 곳이 여기였기 때문에 이번에도 여기서 텍스트 처리.
[SerializeField]
private Text itemFullText; // 아이템이 꽉 찼다는 경고 메세지를 보여줄 텍스트
public IEnumerator WhenInventoryIsFull()
{
itemFullText.gameObject.SetActive(true);
itemFullText.text = "아이템이 꽉 찼습니다.";
yield return new WaitForSeconds(3.0f); // 3 초 후 메세지는 사라짐. 메세지는 3 초만 띄움.
itemFullText.gameObject.SetActive(false);
}
아이템이 꽉 찼다는 경고 메세지로 쓸 텍스트 UI 를 추가하고 해당 텍스트를 itemFullText
에 할당. WhenInventoryIsFull() 함수가 활성화 될 때 이 텍스트를 활성화 하고 “아이템이 꽉 찼습니다.” 메세지를 딱 3 초 동안만 띄우 비활한다.
📜Inventory.cs
private bool isFull = false; // 인벤토리 퀵슬롯 모두 꽉 찼는지
[SerializeField]
private ActionController theActionController;
public void AcquireItem(Item _item, int _count = 1)
{
PutSlot(quickSlots, _item, _count);
if (isNotPut)
PutSlot(slots, _item, _count);
if (isNotPut)
{
isFull = true;
StartCoroutine(theActionController.WhenInventoryIsFull());
}
}
public bool GetIsFull()
{
return isFull;
}
public void SetIsFull(bool _flag)
{
isFull = _flag;
}
- 외부 스크립트에서 인벤토리, 퀵슬롯 둘다 꽉찼는지 알 수 있게
isFull
멤버 추가 (접근 함수까지) - 인벤토리, 퀵슬롯 둘 다 꽉차면
isFull
True로 업뎃- 📜ActionController.cs 의 WhenInventoryIsFull() 함수 실행하여 텍스트 띄움
📜ItemEffectDatabase.cs
[SerializeField]
private Inventory theInventory;
// 📜Inventory 👉 📜Slot 징검다리
public bool GetIsFull()
{
return theInventory.GetIsFull();
}
// 📜Inventory 👉 📜Slot 징검다리
public void SetIsFull(bool _flag)
{
theInventory.SetIsFull(_flag);
}
📜Slot.cs 징검 다리
📜Slot.cs
// 해당 슬롯의 아이템 갯수 업데이트
public void SetSlotCount(int _count)
{
itemCount += _count;
text_Count.text = itemCount.ToString();
if (_count < 0)
{
if (theItemEffectDatabase.GetIsFull())
theItemEffectDatabase.SetIsFull(false);
}
if (itemCount <= 0)
{
ClearSlot();
if (isQuickSlot)
if (QuickSlotController.go_HandItem != null)
if (QuickSlotController.go_HandItem.GetComponent<ItemPickUp>().item.itemType == Item.ItemType.Used)
Destroy(QuickSlotController.go_HandItem);
}
}
// 해당 슬롯 하나 삭제
private void ClearSlot()
{
item = null;
itemCount = 0;
itemImage.sprite = null;
SetColor(0);
text_Count.text = "0";
go_CountImage.SetActive(false);
if (theItemEffectDatabase.GetIsFull())
theItemEffectDatabase.SetIsFull(false);
}
if (theItemEffectDatabase.GetIsFull())
theItemEffectDatabase.SetIsFull(false);
슬롯이 하나 비거나 아이템 갯수가 줄어들면 📜Inventory.cs 의 isFull
을 False 로.
🌜 개인 공부 기록용 블로그입니다. 오류나 틀린 부분이 있을 경우
언제든지 댓글 혹은 메일로 지적해주시면 감사하겠습니다! 😄
댓글남기기