Chapter 10-1. 생존킷 : 생존 킷 제작
카테고리: Unity Lesson 3
태그: Unity Game Engine
인프런에 있는 케이디님의 [유니티 3D] 실전! 생존게임 만들기 - Advanced 강의를 듣고 정리한 필기입니다. 😀
🌜 강의 들으러 가기 Click
생존 킷 : 생존 킷 제작
🚀 컴퓨터 만들기
로켓 안에 들어가면 이렇게 컴퓨터를 할 수 있고, 컴퓨터로 원하는 아이템을 클릭하여 제작할 수 있다. 원하는 슬롯을 클릭하면 해당 아이템이 위의 굴뚝같은 곳에서 생성되어 떨어지게 된다.
- 컴퓨터 오브젝트
- 캔버스 (컴퓨터 모니터 화면을 나타낼 UI 캔버스)
- 초록색 배경 이미지
- 6 개의 슬롯
- 초록색 배경 이미지
- 아이템이 생성될 위치를 나타낼 빈 오브젝트
Item Appear Pos
- 가운데 상단의 굴뚝같이 생긴 곳에서 아이템이 떨어지게끔 할 것이다.
- 따라서 그 위치에 빈 오브젝트를 배치했고 이의 트랜스폼을 아이템 생성 위치로 사용할 것이다.
- 캔버스 (컴퓨터 모니터 화면을 나타낼 UI 캔버스)
✈ 컴퓨터 오브젝트
컴퓨터에 필요한 컴포넌트들
- Box Collider 2 개
- 위에서 아이템이 생성되어 떨어질 때 땅바닥으로 떨어지지 않도록 콜라이더 2 개로 약간의 받침대 모양을 만들었다.
- Audio Source
- 슬롯 버튼을 누를 때, 아이템을 생성할 때 등등 효과음을 재생하기 위해서
- Play On Awake 는 해제해준다.
- 📜CoumputerKit.cs
- 버튼을 누르면 아이템을 생성하고 그 아이템 제작에 필요했던 기존 보유 아이템들을 차감하고 효과음을 재생하고 등등 이런 일을 할 것이다.
- 밑에 후술
✈ 컴퓨터 UI 만들기
Canvas - World Space
컴퓨터 화면으로 사용할 UI. 따라서 이 컴퓨터 모니터로 사용할 Canvas 의 Render Mode 를 World Space 로 해야 한다. 오브젝트로서 월드 상에 배치될 수 있는 UI Canvas 여야 하기 떄문에. 보통의 Canvas 상태인 Overlay 모드일 때는 카메라 화면 위에 덮어 씌워져 렌더링 되기 때문에 씬 상에 배치된 모든 3D 오브젝트들이 그려지고 난 후에 캔버스가 가장 나중에 그려지지만, 이 World Space 모드는 그런거 없다. 다른 씬 상의 오브젝트들과 같다. 캔버스의 크기는 컴퓨터 모니터 화면과 일치하게 scale 과 너비 높이를 조정하였다.
-
Order in Layer 값을 1 로 해준다.
Sort Layer
- 같은 씬 내의 다른 Render 들과 비교했을 때의 캔버스의 렌더 순서를 관리한다.
Z
좌표와 관계없이 렌더링 순서를 제어 할 수 있게 된다.
- Raycast 에 쓰는 그 Layer 와는 전혀 다르다!!
- 같은 Sort Layer 끼리는 같은 Render 순서를 가진다.
- 작은 값을 가지는 Sort Layer 에 속한 오브젝트들일 수록 먼저 그려지고, 큰 값을 가지는 SOrt Layer 에 속한 오브젝트일 수록 나중에 그려지기 떄문에 덮어 씌워져 그려지게 된다.
- 즉, 레이어 목록에서 위에 있는 것일 수록 작은 값
- 같은 씬 내의 다른 Render 들과 비교했을 때의 캔버스의 렌더 순서를 관리한다.
Order in Layer
- 동일한 Sort Layer 내에서의 순서! 마찬가지로 작은 값일 수록 같은 Sort Layer 에 속한 오브젝트들 중에서도 먼저 그려지고 큰 값이면 반대.
- 위 사진을 예로 들자면 “default” 라는 이름의 Sort Layer 에 속한 오브젝트들 중에서도 0 번째, 즉 가장 먼저 그려짐.
Order in Layer 값을 0 으로 했을 때의 모습이다. 컴퓨터 오브젝트의 모니터 부분보다 렌더링 순서가 더 앞서 덮혀져 잘 안보이게 된다. 사실 잘 이해가 안됐던게.. 이 컴퓨터 오브젝트는 조립된게 아닌 전체적인 하나의 오브젝트일 뿐인데 왜 컴퓨터의 다른 부분들은 이 캔버스보다 렌더링이 앞서서 덮혀지는데 왜 유독 컴퓨터의 모니터부분만 캔버스보다 렌더링을 뒤에 해서 캔버스를 덮는걸까? 강의하신 분께서 이 컴퓨터 모델 에셋을 만드실 때 모니터 부분만 렌더링 우선순위에 조작을 가하신걸까? 그럴 수가 있나? Blender 도 미숙하고 3D 모델을 제대로 만들어 본 적이 없어서 잘 모르겠다.. 왜 컴퓨터의 오직 모니터부분만 저렇게 캔버스를 덮어서 렌더링이 되는걸까? 어렵다.. 혹시 이 글을 보고 계신 방문자분께서 이 이유데 대해 아신다면 꼭.. 댓글로 저도 좀 알려주세요 ㅠㅠ
Order in Layer 값을 1 로 해주니 캔버스가 잘 보이게 되었다. 이렇게 Order in layer 값을 높여줄 수록 렌더링이 가장 늦게 되어 가장 먼저 덮혀져 그려지므로 잘 보이게 된다. 씬 상의 다른 오브젝트들보다 이 캔버스의 렌더링 순서를 더 뒤로 밀어 주었다고 이해 하고 넘어가야 겠다. ㅠ
슬롯들
화면의 6 개의 이미지 슬롯에 버튼 이벤트를 달아준다. 이 버튼을 누르면 아이템이 생성되는 일을 하는 함수를 호출하도록 📜ComputerKit 에서 함수를 짤 것이다.
🚀 아이템 만들기
아이템 프리팹
컴퓨터에서 생성할 아이템이다. 아이템이라 작고 귀엽다. 컴퓨터에서 첫 번째 슬롯을 누르면 생성시킬 포션 조작대이다. 아이템화일 때 모습이기 때문에 작게 만들어 주었다. 나중에 이 아이템으로 실제로 배치할 땐 원래 크기로 배치할 것이다.
- 필요한 컴포넌트
- Box Collider
- Collider 가 있어야 바닥을 안뚫는다.
- Rigidbody
- 중력이 있어야 컴퓨터에서 아이템을 생성했을 때 위에서 떨어질 수 있다.
- 질량을 작게 0.01 로
- 📜ItemPickUp 스크립트를 붙인다.
- 아래에서 만들
Item
을 할당해준다. - 이 스크립트가 붙어야 아이템으로서 역할을 할 수 있다. 주울 수 있고 또 아이템으로서 인식할 수 있다.
- 아래에서 만들
- Box Collider
- 태그와 레이어는 “Item” 으로 설정해준다.
- 그래야 📜ActionController 에서 카메라를 통해 아이템으로 인식 할 수 있다.
Item
아이템 프리팹은 방금 위에서 만든 프리팹 할당
📜ComputerKit
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[System.Serializable]
public class Kit // 하나의 아이템이 담고 있는 정보
{
public string kitName;
public string kitDescription;
public string[] needItemName;
public int[] needItemNumber;
public GameObject go_Kit_Prefab;
}
public class ComputerKit : MonoBehaviour
{
[SerializeField]
private Kit[] kits; // 컴퓨터로 생성할 수 있는 아이템 배열
[SerializeField]
private Transform tf_ItemAppear; // 아이템 나오는 구멍의 트랜스폼 정보 (Item Appear Pos)
private bool isCraft = false; // 지금 제작 되는 중인지. false 일 때만 제작 가능하게 할 것.
// 필요한 컴포넌트
private Inventory theInventory; // 📜Inventory.cs
private AudioSource theAudio;
[SerializeField] private AudioClip sound_ButtonClick; // 버튼 클릭 사운드
[SerializeField] private AudioClip sound_Beep; // 아이템 부족하여 키트 생성이 불가능할 때 사운드
[SerializeField] private AudioClip sound_Activated; // 아이템 생성 소리
[SerializeField] private AudioClip sound_Output; // 아이템 나오는 소리
void Start()
{
theInventory = FindObjectOfType<Inventory>();
theAudio = GetComponent<AudioSource>();
}
private void PlaySE(AudioClip _clip) // 효과음 재생
{
theAudio.clip = _clip;
theAudio.Play();
}
public void ClickButton(int _slotNumber) // 슬롯 버튼 클릭시 호출
{
PlaySE(sound_ButtonClick); // 일단 버튼 클릭음 재생
if(!isCraft) // 현재 제작 중이 아니라면 제작 가능
{
if (!CheckIngredient(_slotNumber)) // 재료 있는지 체크
return;
isCraft = true; // 중복 실행 방지. 제작 중입니다.
UseIngredient(_slotNumber); // 재료 사용(보유 아이템에서 제작에 쓰인 갯수만큼 차감)
StartCoroutine(CraftCoroutine(_slotNumber)); // 키트 생성
}
}
private bool CheckIngredient(int _slotNumber)
{
for (int i = 0; i < kits[_slotNumber].needItemName.Length; i++)
{
if (theInventory.GetItemCount(kits[_slotNumber].needItemName[i]) < kits[_slotNumber].needItemNumber[i])
{
PlaySE(sound_Beep); // 아이템 제작 재료 모잘라서 생성할 수 없는 경우 경고음 재생
return false;
}
}
return true;
}
private void UseIngredient(int _slotNumber)
{
for (int i = 0; i < kits[_slotNumber].needItemName.Length; i++)
theInventory.SetItemCount(kits[_slotNumber].needItemName[i], kits[_slotNumber].needItemNumber[i]);
}
IEnumerator CraftCoroutine(int _slotNumber) // 버튼 누르면 3 초 대기 후 아이템 생성
{
PlaySE(sound_Activated); // 아이템 생성 소리 재생
yield return new WaitForSeconds(3f);
PlaySE(sound_Output); // 아이템 빠져나오는 소리 재생
Instantiate(kits[_slotNumber].go_Kit_Prefab, tf_ItemAppear.position, Quaternion.identity); // 아이템 생성
isCraft = false; // 제작이 끝났으니 다시 false로
}
}
CheckIngredient 함수와 UseIngredient 함수에 대한 원리는 9.4 : 건축 아이템 소모 포스트 참고
- 아이템이 생성되는 곳으로서 지정해놓기 위해 만들었던 빈 오브젝트인
Item Appear Pos
를tf_ItemAppear
에 ㅎ라당. - 일단 6개의 슬롯 중 하나만 해볼거라서
kits
배열의 사이즈는 우선 1로 (나중에 6 개 다 채워보는게 좋겠다.)- 포션 제작 도구를 제작하려면 “Twig” 아이템이 2 개 있어야..
- 효과음들도 할당
- 첫 번째 슬롯의 버튼 이벤트는 ClickButton(0) 호출, 두 번째 슬롯의 버튼 이벤트는 ClickButton(1) 호출등등 이런식으로 하게끔 모든 슬롯의 버튼 이벤트에 함수 연결.
🌜 개인 공부 기록용 블로그입니다. 오류나 틀린 부분이 있을 경우
언제든지 댓글 혹은 메일로 지적해주시면 감사하겠습니다! 😄
댓글 남기기