내일배움캠프 54일차 TIL, 최종프로젝트 개발일지2

황오영·2024년 7월 5일
0

TIL

목록 보기
54/56
post-thumbnail
  • 오늘은 최종프로젝트 개발일지를 작성!

인벤토리 시스템

  • 기본 정렬만 하는 인벤토리 시스템은 구현은 몇번했는데 이번에 만드는 게임이 스타듀밸리, 마인크래프트류의 드래그 드롭 이벤트를 통해 인벤을 정리하고 정렬하는 기능이 있어서 이번에 구현했다.

  • 지난번에 비슷하게 슬릇을 드래그하는 기능을 했었을땐 뭔가 어설프게 구현했는데 이번엔 그때의 경험도있고 많은것을 배워서 좀더 원활하게 구현한것 같다.

  • 코드

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class UI_Inventory : MonoBehaviour
{
    public GameObject inventoryPanel;
    public List<UI_ItemSlot> slots = new List<UI_ItemSlot>();
    public GameObject[] playerInventory;
    private void Awake()
    {
        playerInventory = new GameObject[10];
    }
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.E))
        {
            ToggleInventory();
        }
    }


    public void AddItem(GameObject go)
    {
        for (int i = 0; i < playerInventory.Length; i++)
        {
            if (playerInventory[i] == null)
            {
                playerInventory[i] = go;
                return;
            }
        }
        return;
    }
    public void SwapInventory(int from, int to)
    {
        playerInventory.ArraySwap(from, to);
    }

    public void ToggleInventory()
    {
        if (!inventoryPanel.activeSelf)
        {
            inventoryPanel.SetActive(true);
            Refresh();
        }
        else
        {
            inventoryPanel.SetActive(false);
        }
    }

    void Refresh()
    {
        for (int i = 0; i < slots.Count; i++)
        {
            if (playerInventory[i] != null)
                slots[i].SetItem(playerInventory[i]);
        }
    }
}
  • 우선 임시가안이라 이미지로만 인벤토리 배열을 추가해놨었다. 추후 데이터 저장을 할때 인벤토리 상태를 저장해놔야 할 수 도있기 때문에 배열로 선언 List로 하지 않은것은 인벤토리의 크기가 정해져 있기 때문에 우선은 배열로 선언했다. 인벤토리에선 그냥 슬릇을가지고 관리하는 역할 대부분은 slot에서 기능을 구현
  • 특히 배열을 저장하는 과정에서 swap을 해줘야할 필요가 있을것 같아 확장메서드를 이용해서 등록, 확실히 써보니 좀 더 잘이해가되서 좋았다.
using System;
using System.Linq;
using UnityEngine;
using UnityEngine.EventSystems;

public static class Extension
{
    public static void ArraySwap<T>(this T[] array, int from, int to)
    {
        T tmp = array[from];
        array[from] = array[to];
        array[to] = tmp;
    }
}

Slot코드

using UnityEngine.UI;

public class UI_DragSlot : UI_Base
{
    static public UI_DragSlot instance;
    public UI_ItemSlot itemSlot;
    public Image dragImage;
    enum Images
    {
        testImage,
    }
    public override void Init()
    {
        Bind<Image>(typeof(Images));

        instance = this;
        dragImage = GetImage((int)Images.testImage);
        ResetDragSlot();
    }
    public void ResetDragSlot()
    {
        dragImage.color = Util.SetColorAlpha(dragImage, 0);
        dragImage.sprite = null;
    }

    public void SetDragSlot(Image _image, float alpha)
    {
        dragImage.sprite = _image.sprite;
        dragImage.color = Util.SetColorAlpha(dragImage, alpha);
    }

}
using System;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class UI_ItemSlot : UI_Base, IBeginDragHandler, IDragHandler, IEndDragHandler, IDropHandler
{
    public UI_Inventory inventory;
    public int index;
    public Image myImage;
    enum Images
    {
        testImage,
    }
    public override void Init()
    {
        Bind<Image>(typeof(Images));

        myImage = GetImage((int)Images.testImage);
    }
    public void OnBeginDrag(PointerEventData eventData)
    {
        if (myImage.sprite != null)
        {
            UI_DragSlot.instance.itemSlot = this;
            UI_DragSlot.instance.SetDragSlot(myImage, 1);
            UI_DragSlot.instance.transform.position = eventData.position;
        }
    }

    public void OnDrag(PointerEventData eventData)
    {
        if (myImage.sprite != null)
        {
            UI_DragSlot.instance.transform.position = eventData.position;
        }
    }

    public void OnDrop(PointerEventData eventData)
    {
        if (UI_DragSlot.instance.itemSlot != null)
        {
            ChangeSlot();
        }

    }

    public void OnEndDrag(PointerEventData eventData)
    {
        UI_DragSlot.instance.ResetDragSlot();
        UI_DragSlot.instance.itemSlot = null;
    }


    private void ChangeSlot()
    {
        //data is null
        if (myImage.sprite == null)
        {
            Image image = UI_DragSlot.instance.dragImage;
            myImage.sprite = image.sprite;
            myImage.color = Util.SetColorAlpha(image, 1);
            UI_DragSlot.instance.itemSlot.myImage.color = Util.SetColorAlpha(image, 0);
            UI_DragSlot.instance.itemSlot.myImage.sprite = null;
        }
        // data is not null
        else
        {
            Image image = UI_DragSlot.instance.dragImage;
            UI_DragSlot.instance.itemSlot.myImage.sprite = myImage.sprite;
            myImage.sprite = image.sprite;
        }
        inventory.SwapInventory(index, UI_DragSlot.instance.itemSlot.index);

    }

    public void SetItem(GameObject go)
    {
        if (myImage.sprite == null)
        {
            myImage.sprite = go.GetComponentInChildren<SpriteRenderer>().sprite;
            myImage.color = Util.SetColorAlpha(myImage, 1);
        }
    }

    public void SetEmpty()
    {
        myImage.sprite = null;
        myImage.color = Util.SetColorAlpha(myImage, 0);
    }
}
  • 우선 유니티 입력 인터페이스 IBeginDragHandler, IDragHandler, IEndDragHandler, IDropHandler를 상속받고 구현했었다. 여기서 하나 배운것이
    drop 이 실행되고 enddrag가 실행된다는거 이번에 이런 순서도 배웠다.
  • ChangeSlot 메소드를 통해 스왑을 해주게 되는데 비어있는 슬릇인지를 체크하는 로직을 추후 개선해서 넣으면 좋을듯 지금은 Image 스프라이트로만 구분을 하는데 아마 데이터가 들어오게되면 좀더 다르게 구현해야하지 싶긴하다. 일단 간단하게 작동이 되게 구현
  • 하나 좀 놓쳤던것이 단순하게 해당 슬릇을 움직이게 했는데 이렇게 구현하면 문제가 ui의 레이어 순서상 뒤로 밀리기 때문에 이미지가 뒤로 묻히는 현상이 있었다.
  • 그래서 아에 dragslot을 만들어서 새롭게 선언해주고 전역으로 사용 이부분도 조금의 개선은 가능해보이긴한다. static으로 안쓰고 가지고 있어도 되긴할듯?

오늘의 회고

  • 생각보다 인벤토리 구현이 재미있었다. 아직 데이터넣고 쓰는 부분은 미흡한데 이부분도 좀 바꿔놔야될듯
  • 퀵슬릇도 만들고 있는데 뭔가 input함수이용해서 9개쓰는 방식말고 찾아보고 싶은데 딱히 방법이 없어보여서 좀아쉽다.ㅠ 내일 팀원분들과 만든 프로토탙입 합치고 한번 느낌을 다시 봐야겠다.
  • 예전 프로젝트 했을때 비슷한 기능을 했었는데 더 성장한것이 느껴서 괜히 뿌듯했었다. 인터페이스, 상속등 잘 이용할수 있게 된것같아서 기분이 너무 좋았다.
profile
게임개발을 꿈꾸는 개발자

0개의 댓글