Chapter 11-2. 포션 제조 : 포션 제작 UI 만들기 (+ 프리팹 주의사항)

Date:     Updated:

카테고리:

태그:

인프런에 있는 케이디님의 [유니티 3D] 실전! 생존게임 만들기 - Advanced 강의를 듣고 정리한 필기입니다. 😀
🌜 강의 들으러 가기 Click

포션 제조 : 포션 제작 UI 만들기

🚀 연금 테이블

image

  • 태그 “ArchemyTable”
  • 레이어 “Building”
  • Box Collider 3개
    • 포션이 생성되는 아래쪽 검은 구멍 빼고 다 Collider로 감싸주었다.
    • 이 곳에서 포션이 생성되어 빠져나오게 할거라 다른 곳들은 Collider로 막아준 것!
  • 📜ArchemyTable 붙임
    • 밑에 후술
  • 자식 오브젝트로 포션 나오는 구멍쪽에 빈 오브젝트 Potion Appear Pos를 두었다.
    • 포션 나올 위치 트랜스폼

그리고 이를 프리팹으로 만든다.


🚀 포션 제조 UI 만들기

image

image

  • 연금 테이블에 다가가면 액션텍스트가 뜨고 E키를 누르면 이렇게 포션 제조 UI 가 뜨게 할 것이다.
    • 📜ActionController 필요
  • Create 버튼을 누르면 해당 포션이 생성되어 나오게 할 것이다.
    • 포션 생성 함수를 이 버튼 이벤트로 연결시켜줄 것


🚀 포션 아이템

image

요로코롬 포션 3 개 아이템 프리팹을 만들어주었다.

  • Box Collider
  • Rigidbody
  • 📜ItemPickUp
  • 태그와 레이어 모두 “Item”

그리고 Item 에셋도 3 개 각각 만들어주어 📜ItemPickUp 의 Item에 할당


🚀 포션 생성하기

📜GameManager

    public static bool isOpenArchemyTable = false; // 연금테이블 창 활성화

    void Update()
    {
        if (isOpenInventory || isOpenCraftManual || isOnComputer || isOpenArchemyTable)
        {
            Cursor.lockState = CursorLockMode.None;
            Cursor.visible = true;

            canPlayerMove = false;
        }
        else
        {
            Cursor.lockState = CursorLockMode.Locked;
            Cursor.visible = false;

            canPlayerMove = true;
        }
            
    }

외부 컴포넌트인 📜ArchemyTable 에서 isOpenArchemyTable를 True 로 바꿔 마우스 커서를 활성화 하고 플레이어의 움직임을 제한할 것이고, False로 바꿔 마우스 커서를 비활성화 하고 플레이어의 움직임을 활성화할 것이다.


📜ArchemyTable

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

[System.Serializable]
public class ArchemyItem
{
    public string itemName;
    public string itemDescription;
    public Sprite itemImage;

    public GameObject go_ItemPrefab; // 실제 생성될 포션
}

public class ArchemyTable : MonoBehaviour
{
    private bool isOpen = false;

    [SerializeField] private ArchemyItem[] archemyItems;  // 제작할 수 있는 연금 아이템 리스트
    [SerializeField] private Transform tf_BaseUI; // 연금 아이템 베이스 UI
    [SerializeField] private Transform tf_PotionAppearPos; // 포션이 생성될 위치
  • 연금 테이블에서 생성할 수 있는 포션 아이템들이 가지는 속성 묶음 👉 ArchemyItem
    • 이름, 설명, 이미지, 실제 생성될 포션 프리팹
      • 이렇게 4 가지 속성을 가지는 아이템이여야 한다.
    • 이 타입의 배열을 만든다. 즉, 이 연금테이블이 만들 수 있는 포션 아이템들 ArchemyItem[] archemyItems
  • isOpen
    • 연금 테이블 (포션 제조) UI를 키면 true, 닫으면 false
    void Update()
    {
        if (isOpen)
            if (Input.GetKeyDown(KeyCode.Escape))
                CloseWindow();
    }

    public void Window()
    {
        isOpen = !isOpen;
        if (isOpen)
            OpenWindow();
        else
            CloseWindow();
    }

    private void OpenWindow()
    {
        isOpen = true;
        GameManager.isOpenArchemyTable = true;
        tf_BaseUI.localScale = new Vector3(1f, 1f, 1f);
    }

    private void CloseWindow()
    {
        isOpen = false;
        GameManager.isOpenArchemyTable = false;
        tf_BaseUI.localScale = new Vector3(0f, 0f, 0f); // 꼼수 ⭐ 창 비활성화 하면 안됨. 아직 포션 제조중일 수 있어서 크기만 줄여 둠
    }

    public void Buttonclick(int _buttonNum)
    {
        ProductionComplete(_buttonNum);
    }

    private void ProductionComplete(int _buttonNum)
    {
        Instantiate(archemyItems[_buttonNum].go_ItemPrefab, tf_PotionAppearPos.position, Quaternion.identity);
    }
}

  • OpenWindow
    • tf_BaseUI.localScale = new Vector3(1f, 1f, 1f);
  • CloseWindow
    • tf_BaseUI.localScale = new Vector3(0f, 0f, 0f);

포션 제조 UI 를 활성화/비활성화 하지 않고 이렇게 꼼수를 써서 포션 제조 UI 를 열 땐 localSacle 크기를 원래대로 (1, 1, 1)로 한다. 반대로 포션 제조 UI를 닫을 땐 안보이도록 localSacle 크기를 (0, 0, 0)으로 한다. 이렇게 하는 이유는 포션 제조 UI 를 아예 SetActive(false) 하여 비활성화 해버리면 현재 제작이 진행중인 포션의 제작도 초기화 되어버리기 때문이다. 포션 생산을 한번 시작하면 포션 제조 UI 가 닫히더라도 진행되게 할 것이기 때문에 이렇게 눈속임 해준 것이다.

  • Buttonclick
    • 포션 제조 UI 의 CREATE 버튼 이벤트에 등록할 함수
    • ProductionComplete 함수를 호출하여 해당 포션을 생성한다.
  • ProductionComplete
    • 포션 아이템을 생성한다.

image

우선 포션 아이템 1 개만 만들어두었다.

  • tf_BaseUI에는 켜고 닫을 포션 제조 UI 이미지
  • tf_PotionAppearPos에는 포션 생성될 위치로 쓰기 위해 만들어뒀던 빈 오브젝트 Potion Appear Pos 오브젝트 할당

image

첫번째 슬롯의 버튼 이벤트에 Buttonclick(0) 를 호출하였다. 즉 첫번째 CREATE 버튼을 누르면 위의 archemyItmes 배열의 0 인덱스 원소인 빨간 포션이 생성될 것이다.

프리팹화시 주의사항

연금 테이블 프리팹의 📜ArchemyTable 의 tf_BaseUItf_PotionAppearPos에 Hierarchy 상에 존재하는 오브젝트가 할당해주었다. 이미 Hierarchy 상에 존재하는 연금 테이블 오브젝트의 경우엔 문제가 없지만 게임 중 실시간으로 프리팹을 통해 오브젝트를 찍어내는 경우엔 tf_BaseUItf_PotionAppearPos에 아무것도 할당되어 있지 않고 None 상태인 것을 확인할 수 있다.(런타임 에러가 발생할 수 있어 위험함) 이 이유는 프리팹은 로컬 폴더에 자리잡는 외부 에셋이기 때문에 Hierarchy 상에 있는 오브젝트들에게 접근할 수 없기 때문이다. 할당해주더라도 게임이 시작되면 프리팹의 tf_BaseUItf_PotionAppearPos은 None 이 되버릴 것이다.

  • 해결 방법
    • 1️⃣ 할당할 오브젝트를 그냥 프리팹에 속한 자식으로 넣어 같이 프리팹화 시켜버린다.
    • 2️⃣ Start, Awake 에서 FindObjectOfType 함수를 통해 직접 오브젝트를 찾아 할당해준다.

image

첫 번째 방법을 사용하여 Canvas를 연금 테이블 프리팹의 자식으로 하나 만들어주고 그 곳에 포션 제조 UI 들을 넣어주었다. 즉 포션 제조 UI 들을 연금 테이블 프리팹의 일부로서 같이 프리팹화 시켜버려서 해결했다.

또 이렇게 해서 좋은 점은.. 여러 연금테이블들이 하나의 포션 제조 UI 를 공유하지 않기 때문이다. 이렇게 하기 이전에 포션 제조 UI 는 Hierarchy 상에서 하나였기 때문에 연금 테이블 여러개를 찍어낸다면 이 포션 제조 UI 하나를 공유하기 때문에 문제가 생겼을 것이다. UI 상에선 A 테이블에서 a 포션 만드는데 B 테이블에서도 a 포션 만드는 중인 셈이 되었을 것.. 따라서 이렇게 UI 까지도 프리팹화하여 나중에 Hierarchy 에 실존하는 오브젝트로 찍어낼 때 각각 연금 테이블에 종속된 UI 들이 생기게 될 것이다. 테이블마다 따로따로 포션을 만들 수 있게 된다.


📜ActionController

    private void TryAction()
    {
        if(Input.GetKeyDown(KeyCode.E))
        {
            CheckAction();
            CanPickUp();
            CanMeat();
            CanDropFire();
            CanComputerPowerOn();
            CanArchemyTableOpen();
        }
    }

    private void CheckAction()
    {
        if (Physics.Raycast(transform.position, transform.forward, out hitInfo, range, layerMask))
        {
            if (hitInfo.transform.tag == "Item")
                ItemInfoAppear();
            else if (hitInfo.transform.tag == "Weak_Animal")
                MeatInfoAppear();
            else if (hitInfo.transform.tag == "Fire")
                FireInfoAppear();
            else if (hitInfo.transform.tag == "Computer")
                ComputerInfoAppear();
            else if (hitInfo.transform.tag == "ArchemyTable")
                ArchemyInfoAppear();
            else
                InfoDisappear();
        }
        else
            InfoDisappear();
    }

    private void ArchemyInfoAppear()
    {
        Reset();
        lookArchemyTable = true;
        actionText.gameObject.SetActive(true);
        actionText.text = "연금 테이블 조작 " + "<color=yellow>" + "(E)" + "</color>";
    }

    private void CanArchemyTableOpen()
    {
        if (lookArchemyTable)
        {
            if (hitInfo.transform != null)
            {
                hitInfo.transform.GetComponent<ArchemyTable>().Window();
                InfoDisappear();
            }
        }
    }

image

연금 테이블 또한 플레이어가 가까이 가서 쳐다보면 액션 텍스트를 띄우고 E키를 누르면 포션 제조 UI 가 뜰 수 있도록 처리를 해주었다. 연금 테이블의 레이어는 “Building”이기 때문에 메인 카메라가 Raycast 충돌 인식을 할 수 있도록 layerMask에서 “Building”도 추가해준다.




🌜 개인 공부 기록용 블로그입니다. 오류나 틀린 부분이 있을 경우 
언제든지 댓글 혹은 메일로 지적해주시면 감사하겠습니다! 😄

맨 위로 이동하기

Unity Lesson 3 카테고리 내 다른 글 보러가기

댓글 남기기