저번 글에서는 Item과 ItemData를 이용하여 인벤토리 서비스를 구현했었다. 이번 글에서는 인벤토리 서비스를 이용하여 인벤토리 UI를 구현해본다.
인벤토리 시스템에서 인벤토리 UI는 사실 큰 비중을 차지하지 못한다. 단순히 아이템 슬롯들을 보관해주는 컨테이너의 역할 그 이상 그 이하도 아니다.
하지만 돈 관리를 인벤토리 서비스로 책임을 위임했기 때문에 돈 관리는 인벤토리 UI에서 맡는다. 별로 어려운 내용은 아직 아니다. 그러니 계속 이어가보자.
만약 인벤토리 UI 이미지가 없다면 아래의 이미지를 사용하도록 하자.

인벤토리에서 사용할 View를 인터페이스로 먼저 정의한다.
public interface IInventoryView : IPopupView
{
void Inject(InventoryPresenter inventory_presenter);
void OpenUI();
void CloseUI();
void UpdateMoney(int amount);
}
인벤토리 UI는 팝업 UI이기도 하기 때문에 IInventoryView는 IPopupView를 구현한다.
using TMPro;
using UnityEngine;
using UnityEngine.UI;
[RequireComponent(typeof(Animator))]
public class InventoryView : MonoBehaviour, IInventoryView
{
[Header("UI 관련 컴포넌트")]
[Header("팝업 UI 매니저")]
[SerializeField] private PopupUIManager m_ui_manager;
[Header("골드")]
[SerializeField] private TMP_Text m_gold_label;
[Header("닫기 버튼")]
[SerializeField] private Button m_close_button;
private Animator m_animator;
private InventoryPresenter m_presenter;
private void Awake()
{
m_animator = GetComponent<Animator>();
}
// 객체가 파괴되는 시점에 프레젠터에서 연결된 돈 갱신 이벤트를 해제한다.
private void OnDestroy()
{
m_presenter.Dispose();
}
// 인벤토리 프레젠터를 Inject()에서 주입받는다.
public void Inject(InventoryPresenter inventory_presenter)
{
m_presenter = inventory_presenter;
m_close_button.onClick.AddListener(m_presenter.CloseUI);
m_close_button.onClick.AddListener(PopupCloseUI);
}
public void OpenUI()
{
m_animator.SetBool("Open", true);
}
public void CloseUI()
{
m_animator.SetBool("Open", false);
}
// 돈이 갱신되면 돈 텍스트를 amount만큼 변경한다.
public void UpdateMoney(int amount)
{
m_gold_label.text = NumberFormatter.FormatNumber(amount);
}
// 키 바인더 UI와 정확히 동일하기 때문에 설명은 생략한다.
public void SetDepth()
{
(transform as RectTransform).SetAsFirstSibling();
}
// 이 부분도 앞으로는 설명을 생략한다.
public void PopupCloseUI()
{
m_ui_manager.RemovePresenter(m_presenter);
}
}
사실 코드 설명을 할 필요도 없을만큼 간단한게 인벤토리 UI다.
이번 글에서 Presenter를 전부 다 완성할 수는 없다. Presenter는 여기서 설명한 구조에 의해 ItemSlotPresenter를 관리해야 하지만.. 이번 글에서는 다루지 않는다.
따라서 이번 글에서는 ItemSlotPresenter 관리를 제외한 나머지 부분들만 소개하고 다음 글에서 InventoryPresenter를 확장하도록 한다.
using System;
using InventoryService;
public class InventoryPresenter : IDisposable, IPopupPresenter
{
private readonly IInventoryView m_view;
private readonly IInventoryService m_model;
// 생성자를 통해서 view와 인벤토리 서비스를 주입받는다.
public InventoryPresenter(IInventoryView view, IInventoryService model)
{
m_view = view;
m_model = model;
// 인벤토리 서비스의 돈 갱신 델리게이트에 뷰의 돈 갱신 이벤트를 연결한다.
m_model.OnUpdatedGold += m_view.UpdateMoney;
m_view.Inject(this);
}
// 인벤토리를 열 때
public void OpenUI()
{
// 돈을 현재 보유한 돈만큼 초기화한다.
// 없어도 무방하지만, 초기화 과정에서의 오류를 방지하기 위함이다.
Initialize();
m_view.OpenUI();
}
public void CloseUI()
{
m_view.CloseUI();
}
// 인벤토리 UI를 초기화할 때 사용한다.
public void Initialize()
{
m_model.InitializeGold();
}
// 인벤토리 서비스의 델리게이트에 연결된 이벤트를 해제한다.
public void Dispose()
{
m_model.OnUpdatedGold -= m_view.UpdateMoney;
}
public void SortDepth()
{
m_view.SetDepth();
}
}
위에서 IInventoryView와 InventoryView, InventoryPresenter를 모두 구현했다면 에디터로 돌아와서 아래와 같이 인벤토리 UI를 구성한다.

팝업 UI 매니저는 이전에 구현했던 PopupUIManager 컴포넌트를 인스펙터를 통해서 할당한다.
위에서 구성한 인벤토리 UI가 제대로 작동하도록 InventoryUIInstaller를 구현해야 한다.
using InventoryService;
using UnityEngine;
public class InventoryUIInstaller : MonoBehaviour, IInstaller
{
[Header("아이템 데이터베이스")]
[SerializeField] private ItemDataBase m_item_db;
[Header("인벤토리 뷰")]
[SerializeField] private InventoryView m_inventory_view;
public void Install()
{
DIContainer.Register<IItemDataBase>(m_item_db);
DIContainer.Register<IInventoryView>(m_inventory_view);
var m_inventory_presenter = new InventoryPresenter(m_inventory_view,
ServiceLocator.Get<IInventoryService>());
DIContainer.Register<InventoryPresenter>(m_inventory_presenter);
Inject();
}
private void Inject()
{
var item_db = DIContainer.Resolve<IItemDataBase>();
var inventory_service = ServiceLocator.Get<IInventoryService>();
inventory_service.Inject(item_db);
}
}
InventoryUIInstaller도 아이템 슬롯에 관한 부분은 현재로서는 제거한 상태다.
앞으로 아이템 슬롯에 관한 내용을 설명하면서 추후에 확장해가도록 하겠다.
인벤토리 UI가 추가되었으니, 인벤토리 UI를 활성화 및 비활성화할 수 있어야 한다. 따라서 팝업 UI 관리자를 확장하기 전에 팝업 UI 관리자 인스톨러를 먼저 확장한다.
이전에 구현했던 PopupUIManagerInstaller에서 다음과 같이 추가한다.
using System.Collections.Generic;
using UnityEngine;
public class PopupUIManagerInstaller : MonoBehaviour, IInstaller
{
[Header("팝업UI 매니저")]
[SerializeField] private PopupUIManager m_popup_manager;
public void Install()
{
var popup_data_list = new List<PopupData>{
// 이전과 동일
new("Inventory", DIContainer.Resolve<InventoryPresenter>()), // 추가되었다.
};
m_popup_manager.Inject(popup_data_list);
}
}
팝업 UI 관리자 인스톨러에서 InventoryPresenter를 리스트 목록에 추가했으니 이에 맞춰서 PopupUIManager에서도 InventoryPresenter에 키 입력을 전달해주도록 확장한다.
using System.Collections.Generic;
using KeyService;
using UnityEngine;
public class PopupUIManager : MonoBehaviour
{
// 이전과 동일
private void Update()
{
// 이전과 동일
if (GameManager.Instance.Event != GameEventType.SETTING)
{
InputToggleKey("Binder");
InputToggleKey("Inventory"); // 추가되었다.
}
}
// 이전과 동일
}
잘 따라 왔다면.. 아래와 같이 정상적으로 인벤토리 UI가 활성화 및 비활성화 되는 모습을 볼 수 있다. 아까도 언급했지만 슬롯과 관련된 부분은 아직 설명하지 않아서 당연히 없는 것이 맞다.

다음 글에서는 본격적으로 아이템 슬롯에 관한 내용들을 이어갈 것이다. 쉽진 않다.