Game Development, 게임개발/개발

아이템 인벤토리 확장 기능 구현하기

게임이 더 좋아 2022. 3. 20. 14:36
반응형
728x170

우리가 유니티에서 Inspector창으로 더 자세히 보듯이

아이템도 더 자세히 보고싶으면 어떻게 해야할까?

 

자세한 설명은 생략되어있음을 알고 읽자.

 


 

 

우선 필요한 것이 있다.

 

1. 내가 보고싶은 아이템

2. 해당 아이템에 대한 정보(스프라이트 등)

 

어떠한 로직으로 수행할 것이냐하면??

 

1. 아이템 선택

2. 선택한 아이템에 대한 정보를 가져옴

3. Inspector창에 선택한 아이템을 띄움 ****

4. 해당 아이템을 회전시켜서 다른 각도에서 바라볼 수 있음 ****

 

 

시작해보자

 


 

우선 어떻게 아이템의 정보를 가지고 있을 것이냐..?에 대해서다.

 

나는 이번엔 Scriptable Object를 이용해서 아이템의 정보를 가지고 있을 것이다.

public class ItemSO : ScriptableObject {

    public Sprite sprite; //아이템의 스프라이트
    public Transform prefab; // 아이템의 Transform

}

 

이렇게 함으로써 ItemSO에서 바로 읽어올 수 있다.

prefab으로 따로 만들지 않고 가져오는데 특화된 구조이다.

 

 


 

그렇다면 아이템을 어떻게 Inspector 창에 보여줄 것이냐??이다.

 

선택한 아이템이 무엇인지는 어떻게 알며.. 어떻게 Drag를 감지할 것이고..?

물론 아이템 정보는 위에서 가져온다치고.. Image로 보여주는 것이 아닌데..?

어떻게 회전을 시키고 어떻게 움직이게 할까..?

 

우선 사용자에게 보여주기 위해 멀쩡한 판을 만든다.

 

 

이 판에 대해서 특별한 작업을 해줘야 한다는 것이 감이 온다.

 

 

이 Viewer에는 스크립트를 하나 붙여준다.

 

역할은 3가지 정도 있다.

1. 기존의 inventory의 아이템이 선택되면 선택된 아이템을 보여줘야 한다.

2. Drag하면 해당 아이템을 회전시켜 다른 부분을 보여줘야 한다.

3. 아이템을 보여줄 때 이미지가 아닌 오브젝트로 보여줘야 한다.

 

public class Item3DViewer : MonoBehaviour, IDragHandler {

    //인벤토리에 대한 정보를 가지고 있고
    [SerializeField] private DummyInventory dummyInventory;

    //선택한 아이템에 대한 transform을 가짐
    private Transform itemPrefab;


    private void Start() {
        //EventHandler에 아이템이 선택되었을 때(OnItemSelected가 일어났을 때) 실행할 함수를 등록한다.
        dummyInventory.OnItemSelected += DummyInventory_OnItemSelected;
    }


    //그 함수는 ItemPrefab을 만드는 것으로 -> itemSO를 받아서 해당 정보를 이용하여 프리팹을 만들어 내는 것이다.
    private void DummyInventory_OnItemSelected(object sender, ItemSO itemSO) {
        //이전의 선택된 것은 없애버리고
        if (itemPrefab != null) {
            Destroy(itemPrefab.gameObject);
        }
        //새로 선택한 것을 만듬.
        itemPrefab = Instantiate(itemSO.prefab, new Vector3(1000, 1000, 1000), Quaternion.identity);
    }


    //해당 Viewer에서 Drag가 일어났을 때 실행되는 콜백함수
    // -> 회전을 시키는데 마우스가 오른쪽으로 갔을 때, 위로 갔을 때 어떻게 회전이 되어야하는지 생각해보자.
    public void OnDrag(PointerEventData eventData) {
        itemPrefab.eulerAngles += new Vector3(-eventData.delta.y, -eventData.delta.x);
    }

}

 

 


 

아니.. 근데 ..Object를 직접 캔버스 위에 한다고...?

 

Canvas는 항상 Object 위에 있지 않아..?

 

그리고 Layer가 달라서..머리아프네..?

 

그렇다.

UI임에도 Object를 보여줘야해서 조금 힘들다. 

그래서 우리는 Camera를 이용하려고 한다.

 

우리가 Play에서 보고있는 것은 카메라다.

MainCamera를 기준으로 오브젝트가 보이며 UI도 Overlay 또는 다른 카메라로 보이게 된다.

**Overlay하면 카메라가 필요없이 항상 플레이어가 볼 수 있다.

 

즉, 우리는 ItemInspector 전용 카메라를 만들어서 UI에 출력하면 되겠구나.

Canvas의 다른 요소에도 출력할 수 있구나? 를 생각했다.

 

 

카메라를 만들었다.

카메라는 당연히 우리가 위에서 만들어낸 (Instantiate 된) 아이템을 바라봐야할 것이다.

 


 

??? 아니 그 카메라가 아이템을 바라보긴 하는데... 우리한테 보이진 않는데..?

 

당연하다.

우리는 카메라가 해당 아이템을 찍고있게는 해놓았지만

해당 카메라가 찍는 피사체를 우리가 보고있지 않고 있기 때문이다.

 


 

그렇다면 어떻게 우리가 해당 카메라가 찍는 것을 볼 수 있을까???

 

Rendering Texture를 만들어야 한다.

 

 

다시 말하자면 Rendering Texture가 장착된 카메라의 내용을 얘가 가지고 있다는 것이다.

예를 들면 우리가 웹캠으로 줌 채팅, 구글 밋을 진행하는데

내 얼굴을 보고 싶다면 이 카메라가 찍고 있는 것을 보고싶다는 얘기와 같다.

 

그래서 우리는 우리의 프로필을 클릭하여 우리의 Rendering Texture에 접근해서

해당 카메라가 찍고 있는 것을 보는 것이다!!

 

 

 

그렇게 해당 카메라가 찍고 있는 내용은 Target Texture에 담긴다.

 

그렇다면 Rendering Texture를 아까 UI에 보여주면 되겠네???

정답이다.

 

우리가 만든 Inspector창을 아래와 같은 Hierarchy를 가지고 있고

RawImage에 RenderingTexture를 넣었다.

 

 

다시 말해서 이제 RawImage는 저 Texture를 가지고 있는 카메라의 내용을 보여주게 되는 것이다.

 


 

요약

 

RenderingTexutre를 이용한 UI의 편의성 제공

DragHandler를 이용해 PointerInput에 대한 정보로 조작

EventHandler 이용으로 선택, 비선택 구분

 

 


참고링크

https://www.youtube.com/watch?v=tJ_ycboPFmY&t=10s 

반응형
그리드형