Chapter 11-2. 포션 제조 : 포션 제작 UI 만들기 (+ 프리팹 주의사항)
카테고리: Unity Lesson 3
태그: Unity Game Engine
인프런에 있는 케이디님의 [유니티 3D] 실전! 생존게임 만들기 - Advanced 강의를 듣고 정리한 필기입니다. 😀
🌜 강의 들으러 가기 Click
포션 제조 : 포션 제작 UI 만들기
🚀 연금 테이블
- 태그 “ArchemyTable”
- 레이어 “Building”
- Box Collider 3개
- 포션이 생성되는 아래쪽 검은 구멍 빼고 다 Collider로 감싸주었다.
- 이 곳에서 포션이 생성되어 빠져나오게 할거라 다른 곳들은 Collider로 막아준 것!
- 📜ArchemyTable 붙임
- 밑에 후술
- 자식 오브젝트로 포션 나오는 구멍쪽에 빈 오브젝트
Potion Appear Pos
를 두었다.- 포션 나올 위치 트랜스폼
그리고 이를 프리팹으로 만든다.
🚀 포션 제조 UI 만들기
- 연금 테이블에 다가가면 액션텍스트가 뜨고
E
키를 누르면 이렇게 포션 제조 UI 가 뜨게 할 것이다.- 📜ActionController 필요
- Create 버튼을 누르면 해당 포션이 생성되어 나오게 할 것이다.
- 포션 생성 함수를 이 버튼 이벤트로 연결시켜줄 것
🚀 포션 아이템
요로코롬 포션 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
- 포션 아이템을 생성한다.
우선 포션 아이템 1 개만 만들어두었다.
tf_BaseUI
에는 켜고 닫을 포션 제조 UI 이미지tf_PotionAppearPos
에는 포션 생성될 위치로 쓰기 위해 만들어뒀던 빈 오브젝트Potion Appear Pos
오브젝트 할당
첫번째 슬롯의 버튼 이벤트에 Buttonclick(0) 를 호출하였다. 즉 첫번째 CREATE 버튼을 누르면 위의 archemyItmes
배열의 0 인덱스 원소인 빨간 포션이 생성될 것이다.
프리팹화시 주의사항
연금 테이블 프리팹의 📜ArchemyTable 의 tf_BaseUI
와 tf_PotionAppearPos
에 Hierarchy 상에 존재하는 오브젝트가 할당해주었다. 이미 Hierarchy 상에 존재하는 연금 테이블 오브젝트의 경우엔 문제가 없지만 게임 중 실시간으로 프리팹을 통해 오브젝트를 찍어내는 경우엔 tf_BaseUI
와 tf_PotionAppearPos
에 아무것도 할당되어 있지 않고 None 상태인 것을 확인할 수 있다.(런타임 에러가 발생할 수 있어 위험함) 이 이유는 프리팹은 로컬 폴더에 자리잡는 외부 에셋이기 때문에 Hierarchy 상에 있는 오브젝트들에게 접근할 수 없기 때문이다. 할당해주더라도 게임이 시작되면 프리팹의 tf_BaseUI
와 tf_PotionAppearPos
은 None 이 되버릴 것이다.
- 해결 방법
- 1️⃣ 할당할 오브젝트를 그냥 프리팹에 속한 자식으로 넣어 같이 프리팹화 시켜버린다.
- 2️⃣ Start, Awake 에서 FindObjectOfType 함수를 통해 직접 오브젝트를 찾아 할당해준다.
첫 번째 방법을 사용하여 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();
}
}
}
연금 테이블 또한 플레이어가 가까이 가서 쳐다보면 액션 텍스트를 띄우고 E
키를 누르면 포션 제조 UI 가 뜰 수 있도록 처리를 해주었다. 연금 테이블의 레이어는 “Building”이기 때문에 메인 카메라가 Raycast 충돌 인식을 할 수 있도록 layerMask
에서 “Building”도 추가해준다.
🌜 개인 공부 기록용 블로그입니다. 오류나 틀린 부분이 있을 경우
언제든지 댓글 혹은 메일로 지적해주시면 감사하겠습니다! 😄
댓글 남기기