18.툴팁(아이템 설명창)
using UnityEngine;
using UnityEngine.UIElements;
using static UnityEditor.Progress;
[System.Serializable]
public class ItemEffect
{
public string itemName;//아이템 이름(키값)
[Tooltip("HP, SP, DP, HUNGRY, THIRSTY, SATISFY만 가능합니다")]
public string[] part;//부위
public int[] num;//수치
}
public class ItemEffectDatabase : MonoBehaviour
{
[SerializeField]
private ItemEffect[] itemEffects;
//필요한 컴포넌트
[SerializeField]
private StatusController thePlayerStatus;
[SerializeField]
private WeaponManager theWeaponManager;
[SerializeField]
private SlotToolTip theSlotToolTip;
private const string HP = "HP", SP = "SP", DP = "DP", HUNGRY = "HUNGRY", THIRSTY = "THIRSTY", SATISFY = "SATISFY";
public void ShowToolTop(Item _item,Vector3 _pos)
{
theSlotToolTip.ShowToolTip(_item, _pos);
}
public void HideToolTip()
{
theSlotToolTip.HideToolTip();
}
public void UseItem(Item _item)
{
if (_item.itemType == Item.ItemType.Equipment)
{
StartCoroutine(theWeaponManager.ChangeWeaponCoroutine(_item.weaponType, _item.itemName));
}
else if (_item.itemType == Item.ItemType.Used)
{
for (int x = 0; x < itemEffects.Length; x++)
{
if (itemEffects[x].itemName == _item.itemName)
{
for (int y = 0; y < itemEffects[x].part.Length; y++)
{
switch (itemEffects[x].part[y])
{
case "HP":
thePlayerStatus.IncreaseHP(itemEffects[x].num[y]);
break;
case "SP":
thePlayerStatus.IncreaseSP(itemEffects[x].num[y]);
break;
case "DP":
thePlayerStatus.IncreaseDP(itemEffects[x].num[y]);
break;
case "HUNGRY":
thePlayerStatus.IncreaseHungry(itemEffects[x].num[y]);
break;
case "THIRSTY":
thePlayerStatus.IncreaseThirsty(itemEffects[x].num[y]);
break;
case "SATISFY":
break;
default:
Debug.Log("잘못된 Status 부위. HP, SP, DP, HUNGRY, THIRSTY, SATISFY만 가능합니다");
break;
}
Debug.Log(_item.itemName + "을 사용했습니다");
}
return;
}
}
Debug.Log("ItemEffectDatabase에 일치하는 itmeName가 없습니다");
}
}
}
using UnityEngine;
[CreateAssetMenu(fileName ="New Item", menuName = "New Item/item")]
public class Item : ScriptableObject
{
public string itemName; //아이템 이름
[TextArea]//인스팩터 창에서 택스트 창을 키움
public string itemDesc;//아이템 설명
public ItemType itemType; //아이템의 유형
public Sprite itemImage; //아이템의 이미지
public GameObject itemPrefab; //아이템의 프리팹
public string weaponType; //무기 유형
public enum ItemType
{
Equipment, Used, Ingredient, ETC
}
}
using UnityEngine;
using UnityEngine.UI;
public class SlotToolTip : MonoBehaviour
{
[SerializeField]
private GameObject go_Base;
[SerializeField]
private Text text_ItemName;
[SerializeField]
private Text text_ItemDesc;
[SerializeField]
private Text text_ItemHowtoUsed;
public void ShowToolTip(Item _item, Vector3 _pos)
{
go_Base.SetActive(true);
_pos += new Vector3(go_Base.GetComponent<RectTransform>().rect.width * 0.5f, -go_Base.GetComponent<RectTransform>().rect.height, 0f);
go_Base.transform.position = _pos;
text_ItemName.text = _item.itemName;
text_ItemDesc.text = _item.itemDesc;
if(_item.itemType == Item.ItemType.Equipment)
{
text_ItemHowtoUsed.text = "우클릭 - 장착";
}
else if (_item.itemType == Item.ItemType.Used)
{
text_ItemHowtoUsed.text = "우클릭 - 먹기";
}
else
{
text_ItemHowtoUsed.text = "";
}
}
public void HideToolTip()
{
go_Base.SetActive(false);
}
}
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
public class Slot : MonoBehaviour, IPointerExitHandler, IPointerEnterHandler, IPointerClickHandler, IBeginDragHandler, IDragHandler, IEndDragHandler, IDropHandler
{
private Vector3 originPos;
public Item item;//획득한 아이템
public int itemCount;//획득한 아이템 개수
public Image itemImage;//아이템 이미지
//필요 컴포넌트
[SerializeField]
private Text text_Count;
[SerializeField]
private GameObject go_CountImage;
private ItemEffectDatabase theItemEffectDatabase;
void Start()
{
theItemEffectDatabase = FindAnyObjectByType<ItemEffectDatabase>();
}
private void SetColor(float _alpha)//이미지 투명도 조절
{
Color color = itemImage.color;
color.a = _alpha;
itemImage.color = color;
}
public void AddItem(Item _item, int _count = 1)//아이템 획득
{
item = _item;
itemCount = _count;
itemImage.sprite = item.itemImage;
if (item.itemType != Item.ItemType.Equipment)
{
go_CountImage.SetActive(true);
text_Count.text = itemCount.ToString();
}
else
{
text_Count.text = "0";
go_CountImage.SetActive(false);
}
SetColor(1);
}
public void SetSlotCount(int _count)//아이템 개수 조정
{
itemCount += _count;
text_Count.text = itemCount.ToString();
if (itemCount <= 0)
ClearSlot();
}
private void ClearSlot()//슬롯 초기화
{
item = null;
itemCount = 0;
itemImage.sprite = null;
SetColor(0);
text_Count.text = "0";
go_CountImage.SetActive(false);
}
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 OnBeginDrag(PointerEventData eventData)
{
if (item != null)
{
DragSlot.instance.dragSlot = this;
DragSlot.instance.DragSetImage(itemImage);
DragSlot.instance.transform.position = eventData.position;
}
}
public void OnDrag(PointerEventData eventData)
{
if (item != null)
{
DragSlot.instance.transform.position = eventData.position;
}
}
public void OnEndDrag(PointerEventData eventData)
{
DragSlot.instance.SetColor(0);
DragSlot.instance.dragSlot = null;
}
public void OnDrop(PointerEventData eventData)
{
if (DragSlot.instance.dragSlot != null)
{
ChangeSlot();
}
}
private void ChangeSlot()
{
Item _tempItem = item;
int _tempItemCount = itemCount;
AddItem(DragSlot.instance.dragSlot.item, DragSlot.instance.dragSlot.itemCount);
if (_tempItem != null)
{
DragSlot.instance.dragSlot.AddItem(_tempItem, _tempItemCount);
}
else
{
DragSlot.instance.dragSlot.ClearSlot();
}
}
//마우스가 슬롯에 들어갈 때 발동
public void OnPointerEnter(PointerEventData eventData)
{
if (item != null)
theItemEffectDatabase.ShowToolTop(item, transform.position);
}
//슬롯에서 빠져나갈 때 발동
public void OnPointerExit(PointerEventData eventData)
{
theItemEffectDatabase.HideToolTip();
}
}
이번시간에는 게임에서 마우스를 아이템 위로 두면 해당 아이템의 설명이 나오는 것을 만들어 볼 것 입니다
Canvas의 하위 Inventory에 빈 객체를 만들고 이름을 SlotToolTip로 명명합니다
그리고 그 하위에 Panel을 만들어 줍니다
그리고 오른쪽 그림을 참고해서 초록색 4각형을 만들어 줍니다
그런데 여기서 Panel과 Image의 차이를 생각해보신 적 있나요?
Ai에게 물어봤습니다
넵 쉽게 말해서 Panel은 어떤 객체들을 모아두는 것이고 Image는 그냥 단순한 이미지네요
이제 하위에 Panel을 또 만들어주고 이번에는 위의 4각형 안에 작은 4각형이 넣은 것 처럼 아래같이 보이게 만들어 줍니다
그 다음은 하위에 Text를 만들어주고 설정을 잡아줍니다
이번에는 그림처럼 Rock의 부분에 아이템의 이름이 나오기 위한 텍스트 였습니다
다음은 아래처럼 아이템 설명이 나오는 4각형을 텍스트로 만들어 줍니다
여기서 오른쪽 그림의 BestFit를 활성화하면 MinSize와 MaXSize를 설정가능합니다
보면 아시겠지만 이 텍스트는 최소크기 최대크기가 정해져 있습니다
툴팁을 제대로 표현하기 위함입니다
이제 마지막으로 Panel의 오른족에서 아래에 우클릭 - 장착이나, 우클릭 사용을 표시해주는 Text를 만들어 줍니다
전부다 만들은다면
우리는 이러한 툴팁 이미지를 만들게 됩니다
그리고 이렇게 명명해줍니다
첫번째로 만들은 빈 객체는 SlotToolTip로 명명하고 첫번째 Panel은 Base_Outer, 두번째 Panel은 Base_Inner,
text로 만들어진 객체 3개는 위처럼 만들은 순서대로 명명해주고 Base_Inner에 다 넣어줍니다
그리고 각 객체들의 하위를 위처럼 만들어 줍니다
이제 스크립트를 손봐줍시다
Item 스크립트를 열어줍시다
그리고 위에 표시한 7,8줄을 작성해서 넣어줍시다
여기서 7번줄의 TextArea는 유니티엔진 인스펙터에서 텍스트 상자를 만들어서 값을 넣을 수 있게 수정해줍니다
이렇게 말입니다
유용한 것이니 기억해줍시다
테스트를 위해 Itme 객체들 중에서 Gun1을 위 처럼 값을 넣어줍니다
이제 또 C#스크립트를 작성해줍시다
이름은 SlotToolTip로 명명합니다
우리는 Text를 다루기 때문에 using UnityEngine.UI;를 입력해줘야 합니다
7번줄은 인스펙터에서 기본 베이스가 되는 게임 오브젝트입니다 on/off 용이라고 생각하면 됩니다
9번줄은 아이템의 이름을 나타낼 텍스트고
11번줄은 아이템 설명문을 나타낼 내용입니다
13번줄은 아이템 내용 중 오른쪽 클릭 - 장비, 오른쪽 클릭 - 사용 같은 텍스트용 입니다
void ShowToolTip함수를 봅시다 인수로 Item _item, Vector3 _pos를 받아옵니다
17번 줄은 아이템 설명 판넬을 활성화해줍니다
18번 줄은 _pos를 조절합니다 이건 아이템 설명이 뜨면 아이템 설명박스의 위치를 아래에서 살짝 오른족으로 오게하는 것 입니다
go.Base.GetComponent<RectTransform>().rect.width * 0.5f로 이건 가로조절
go.Base.GetComponent().rect.height는 세로 조절
마지막 0f는 z축 입니다
19번은 18번 줄에서 세팅된 것을 _pos에 적용해주는 것 입니다
21과 22번은 각 아이템 이름과 아이템 설명을 적용해주는 것 입니다
24~35번줄은 if문으로 아이템 타입별로 "우클릭 - 장착", "우클릭 - 먹기" 같은 것을 설정해주는 것 입니다
만약 아무 타입도 없다면 else로 공백이 출력됩니다
이제 Slot 스크립트를 열어줍시다
Slot 스크립트에서 상속 중 IPointerExitHandler, IPointerEnterHandler를 불러와줍시다
위 두개가 있어야지 마우스를 갔다가 대면 툴팁이 생기는 옵션을 조종할 수 있습니다
ItemEffectDatabase를 장착합시다
135번줄의 함수를 봅시다
if문으로 item이 null이 아닐때
ShowToolTop(item, transform.position)이 호출 됩니다
즉 이 함수는 마우스를 아이템 아이콘 위에 올렸을때고
141번줄은 HideToolTip를 호출하며 마우스를 아이템 아이콘에서 때면 설명이 사라지는 효과입니다
이제 ItemEffectDatabase 스크립트를 열어봅시다
SlotToolTip스크립트를 장착합시다
현재 작성 중인 ItemEffectDatabase 는 중간다리 역활을 합니다
우리가 위에서본 함수들 입니다
여기에서 징검다리 처럼 실행할 수 있게 작성해줍니다
이제 테스하기 전에 인스펙터를 연결해줍니다
SlotToolTip 오브젝트에 SlotToolTip 스크립트를 넣고 위 스크린샷 처럼 객체를 연결해줍시다
이렇게 하고 테스트를 하면...
이렇게 구현되었습니다