Tab의 작동원리는 간단합니다. Tab A와 Tab B에 Button을 달아 해당 Tab을 클릭 시
Content A나 B가 활성화되는 역할과 아이템을 Drag로 이동할 Tab위에 올려두면 역시
해당 Tab의 Content가 활성화되는 기능을 가지고 있습니다.
빈 오브젝트를 만들어 이름을 Tab Group 지정합니다.
그 아래 Tab A와 다시 그 아래 Tab의 이름을 지정할 TextMeshPro를 달아 주세요
아래 이미지는 Tab A에 들어갈 Components이며 해당 값은 만드시는 인벤토리에 맞게
조정해 주시고 Tab 모양을 만들 Image 역시 알맞은 이미지를 만들어 넣어 주시면 됩니다.
Button의 색상은 모두 하얀색으로 통일해서 클릭되는 효과가 나오지 않게 해 줍니다.
OnClick 이벤트에는 2부에서 만든 InventoryManager에 추가로 TabChange 메서드를 만들어서
넣어 주겠습니다. 해당 버튼의 int 값은 Tab의 번호를 의미합니다.
자 여기서 InventoryTab.cs를 만들기 전에 DataManager.cs를 먼저 만들어 두겠습니다.
말 그대로 인벤토리에 저장된 아이템을 Json으로 저장과 불러오기를 하게 될 것이면 싱글톤으로 지정하여
Inevntory에서 같이 사용하게 될 변수 역시 DataManager에 선언해서 사용할 것입니다.
using UnityEngine;
public class DataManager : MonoBehaviour
{
public static DataManager Instance { get; private set; }
[Header("인벤토리 매니저")]
public InventoryManager inventory;
private void Awake()
{
if (Instance == null)
{
Instance = this;
DontDestroyOnLoad(this);
}
else
{
Destroy(gameObject);
}
}
/// <summary>
/// Hex Color Code를 변환 시켜 준다.
/// </summary>
public Color ColorHEX(string _color)
{
ColorUtility.TryParseHtmlString($"#{_color}", out Color color);
return color;
}
}
DataManager를 싱글톤으로 만들어 어디서나 불러오기 쉽게 만들었습니다.
인벤토리 매니저를 연결해 주세요.
이건 색상을 헥스코드를 넣어 색을 지정하기 위해 사용됩니다.
데이터를 저장하고 불러오는 기능은 나중에 구현하도록 하겠습니다.
자 그리고 InventoyManager.cs에 추가 코드를 작성해 줍니다.
Tab A와 Tab B를 여기에 넣어 주시면 됩니다.
아래 그림 참조
tabIndex는 활성화되어 있는 Tab의 번호를 나타냅니다.
tabOnColor는 활성화된 Tab의 배경색이며 tabOffColor는 비활성화된 Tab의 배경색입니다.
InventoyManager.cs 코드 추가는 계속됩니다.
집중해 주세요
/// <summary>
/// Tab을 변경해 준다
/// </summary>
/// <param name="tabIndex">Select Tab Index</param>
public void TabChange(int tabIndex)
{
OnTabAnimation(tabIndex);
OffTabAnimation(tabIndex);
}
/// <summary>
/// Tab을 활성화 시켜준다
/// </summary>
/// <param name="_tabIndex">Select Tab</param>
private void OnTabAnimation(int _tabIndex)
{
slotParent[_tabIndex].gameObject.SetActive(true);
tabObject[_tabIndex].color = DataManager.Instance.ColorHEX(tabOnColor);
tabObject[_tabIndex].transform.DOScaleY(0.5f, 0.2f).OnComplete(() => {
tabObject[_tabIndex].transform.DOScaleY(1f, 0.4f).SetEase(Ease.OutBounce);
});
}
/// <summary>
/// Tab을 비활성화 시킨다
/// </summary>
/// <param name="_tabIndex">Select Tab</param>
private void OffTabAnimation(int _tabIndex)
{
var index = DataManager.Instance.inventory.tabIndex;
tabObject[index].color = DataManager.Instance.ColorHEX(tabOffColor);
slotParent[index].gameObject.SetActive(false);
tabObject[index].transform.DOScaleY(1.2f, 0.2f).OnComplete(() => {
tabObject[index].transform.DOScaleY(1f, 0.4f).SetEase(Ease.OutBounce);
DataManager.Instance.inventory.tabIndex = _tabIndex;
});
}
TabChange() 메서드는 위 Tab A와 Tab B의 버튼 이벤트에 연결해 주시고 해당 버튼
이벤트의 int 값은 순서에 맞게 Tab A = 0번 Tab B = 1번 만약 Tab 이 추가된다면 추가되는 순서대로
번호를 부여해 주시면 됩니다.
나머지 OnTanAnimation()과 OffTabAnimation() 메서드의 역할은 각 Tab의 활성 / 비활성을 담당하게 됩니다.
여기까지 무사히 오셨다면 Tab 버튼이 잘 작동하나 테스트해 보겠습니다.
게임을 플레이시킨 후 Tab A와 Tab B를 클릭해서 Contant 전환이 잘 되나 확인해 봐 주세요.
Tab B 클릭
Tab A 다시 클릭 잘 작동하고 있습니다.
이제 Tab A에 있는 아이템을 Darg 해서 Tab B위에 올려 Tab을 전환 후 아이템을 Tab B의 Content에
넣어 보겠습니다.
using Cysharp.Threading.Tasks;
using UnityEngine;
using UnityEngine.EventSystems;
public class InventoryTab : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler
{
[Header("Tab 순서")]
[SerializeField] private int tabIndex;
private bool isTabOnCheck;
/// <summary>
/// 아이템이 Tab 위에 올라온다면 처리
/// </summary>
/// <param name="eventData"></param>
public void OnPointerEnter(PointerEventData eventData)
{
if (eventData.pointerDrag != null)
{
// 아이템이 비활성화 된 Tab 위에서만 작동한다.
if (DataManager.Instance.inventory.tabIndex != tabIndex)
{
isTabOnCheck = true;
TabDelayOpen().Forget();
}
}
}
/// <summary>
/// 아이템이 Tab 에서 벗어 난다면 처리
/// </summary>
/// <param name="eventData"></param>
public void OnPointerExit(PointerEventData eventData)
{
if (eventData.pointerDrag != null)
{
isTabOnCheck = false;
}
}
/// <summary>
/// Tab을 0.5초 후에 활성화 시켜준다.
/// </summary>
private async UniTask TabDelayOpen()
{
await UniTask.Delay(System.TimeSpan.FromSeconds(0.5f));
if (isTabOnCheck)
{
isTabOnCheck = false;
DataManager.Instance.inventory.TabChange(tabIndex);
}
}
}
위 코드를 Tab A와 Tab B에 각각 넣어 주세요.
IPointerEnterHandler, IPointerExitHandler의 역할은 마우스 커서 또는 Drag가 해당 이벤트가 있는
UI 위에 올가 가거나 빠져나갈 때 이벤트가 발생하게 됩니다.
각 Tab에 맞는 번호를 넣어 주시면 됩니다. Tab A는 0번, Tab B는 1번
아이템이 Tab위에 있는지 확인하기 위해 사용됩니다.
이 부분은 아이템이 Tab 위에 올라가면 발생하는 이벤트입니다.
InventoryManager에 선언한 tabIndex는 현재 활성화된 Tab 번호를 의미하고 있습니다.
다시 말해 아이템이 올라간 Tab이 InventoryManager의 tabIndex와 Tab 안에 지정한 tabIndex가 다르다면
Tab 이동을 시켜 줍니다.
활성화된 Tab위에 있을 땐 아무 일도 일어나지 않습니다.
isTabOnCheck를 true를 주어 Tab 이동이 작동했다를 알려 줍니다.
위 코드엔 UniTask를 사용했지만 UniTask를 모르시는 분들은 코루틴을 사용하시면 됩니다.
아무튼 여기서 0.5초를 대기합니다.
if (isTabOnCheck) -> 아직 아이템이 Tab위에 있다면 Tab을 변경합니다.
isTabOnCheck를 false를 주어 Tab 변경이 끝났음을 알려 줍니다.
그리고 위에서 만든 TabChange 메서드를 이용해 실제 Tab을 변경해 줍니다.
Tab 위에 있던 Item이 다른 곳으로 이동했다면 발생하는 이벤트입니다.
isTabOnCheck를 false로 주어 위에 0.5초 이전에 아이템이 Tab에서 빠져나간다면
변경을 못하게 막아 줍니다.
이것으로 Tab 기능은 마무리되었습니다.
아이템을 Drag 하여 다른 Tab으로 이동시켜 보시고 다시 원래 Tab으로 가져오는 테스트를 해보시기 바랍니다.
3부는 여기까지 하겠습니다.
4부에선 인벤토리에 들어 있는 아이템을 DataManager를 이용해서 Json Data로 저장과 불러오기
기능을 넣어보도록 하겠습니다.
'Unity' 카테고리의 다른 글
유니티 (Unity) - 실전 인벤토리 제작 (5부) (6) | 2025.07.28 |
---|---|
유니티 (Unity) - 실전 인벤토리 제작 (4부) (4) | 2025.07.26 |
유니티 (Unity) - 실전 인벤토리 제작 (2편) (0) | 2025.07.24 |
유니티 (Unity) - 실전 인벤토리 제작 (1편) (0) | 2025.07.24 |
유니티 C# - Interface 게임에 적용해 보기 (10) | 2024.07.09 |