[unity 3d] - 바라보는 오브젝트를 키 입력을 통해 인벤토리에 저장하기
< 구현 목표 >
나무 오브젝트를 바라보고 "G"키를 누르면 나무가 파괴되면서 인벤토리에 저장되도록 하기!
추후에 다른 오브젝트들도 추가하게되면 코드를 수정할 예정입니다!
먼저, 인벤토리 만드는 방식은 아래 블로그를 참고하였습니다.
유니티 (Unity) - 처음 만들어 보는 인벤토리 이해하기 (Inventory)
인벤토리를 만들기 위한 기본 구조를 살펴보겠습니다.인벤토리가 어떻게 작동하는지 알아보기 위한 아주 간단한 프로그램입니다. 사용된 아이콘 및 슬롯 이미지https://assetstore.unity.com/packages/2d/
geojun.tistory.com
Player 스크립트에서 필요한 전체 코드는 아래와 같습니다.
public Inventory inven11;
...
void ColliderObject()
{
Vector3 startPosition = transform.position + Vector3.up * 15f;
Debug.DrawRay(startPosition, transform.forward * 12f, Color.red);
RaycastHit hit;
if (Physics.Raycast(startPosition, transform.forward, out hit, 12))
{
int hitLayer = hit.collider.gameObject.layer;
if (hitLayer == LayerMask.NameToLayer("Logs"))
{
if (Input.GetKeyDown(KeyCode.G)) // 나무 얻기
{
string hitname = hit.collider.gameObject.name;
if (hitname.Substring(0, 3) == "log")
{
print(hit.collider.gameObject.name);
inven11.Check("log");
}
Destroy(hit.collider.gameObject);
}
}
...
}
}
}
...
void Inven()
{
if (Input.GetKeyDown(KeyCode.I))
{
if (!isClick) // 인벤토리 닫기
{
inven.SetActive(false);
isClick = true;
}
else // 인벤토리 열기
{
inven.SetActive(true);
isClick = false;
}
}
}
먼저 캐릭터에서 레이저를 쏘아서 닿은 물체의 정보를 얻기 위해서 레이저의 위치와 길이를 설정해주어야합니다.
position 값은 발 아래를 기준으로 하기 때문에 레이저를 상체에서 발사하도록 Vector3.up을 더해주었습니다.
Debug.DrawRay를 사용하면 시각적으로 레이저를 확인할 수 있습니다.
(시작 위치, 방향*길이, 색깔) 을 매개변수로 가집니다. 저는 레이저의 길이를 앞으로 12배만큼으로 설정했습니다.
Vector3 startPosition = transform.position + Vector3.up * 15f;
Debug.DrawRay(startPosition, transform.forward * 12f, Color.red);
hit은 레이저가 어떤 물체에 닿았을 때 그 충돌 정보를 저장하는 변수입니다.
첫 번째 if문에서 12는 transform.forward방향으로 길이 12배만큼 레이저를 발사해줍니다.
저는 충돌한 물체의 정보 중 충돌한 물체의 collider을 가져와주었습니다!
hitLayer은 충돌한 물체의 layer의 번호를 저장합니다.
나무들의 이름이 "log_a1" 이런식이라서 Substring을 통해 처음부터 3자리를 잘라서 "log"이면
Inventory의 Check 메서드를 실행해줍니다.
다 실행한 후에는 Destroy()를 통해 나무 오브젝트를 제거합니다.
RaycastHit hit;
if (Physics.Raycast(startPosition, transform.forward, out hit, 12))
{
int hitLayer = hit.collider.gameObject.layer;
if (hitLayer == LayerMask.NameToLayer("Logs")) //"Logs"라는 레이어의 번호와 같을때
{
if (Input.GetKeyDown(KeyCode.G)) // G를 눌러 나무 얻기
{
string hitname = hit.collider.gameObject.name;
if (hitname.Substring(0, 3) == "log")
{
print(hit.collider.gameObject.name);
inven11.Check("log");
}
Destroy(hit.collider.gameObject);
}
}
...
}
아래는 기본적으로 위의 블로그에서 구현했던 Inventory 스크립트를 수정한 코드입니다.
public List<Item> items;
public TextMeshProUGUI[] slotText;
private Slot[] slots;
...
void Awake()
{
FreshSlot();
for (int i = 0; i < slots.Length; i++)
{
slotText[i].text = "0"; // 처음엔 0으로 초기화
slotText[i].gameObject.SetActive(false);
}
}
public void Check(string name)
{
...
int i = 0;
for (;i < slots.Length; i++)
{
slotText[i].gameObject.SetActive(true);
if (slots[i].item != null && slots[i].item.itemName == name)
{
print("correct");
slotText[i].text = (int.Parse(slotText[i].text) + 1).ToString();
}
if (int.Parse(slotText[i].text) == 5)
{
print("나무를 5개 모았습니다!");
bridge.SetActive(true);
}
}
}
먼저 items에는 등록할 아이템들을 저장해주고, slotText는 각 아이템의 갯수를 나타냅니다.
slots는 인벤토리의 각 슬롯들을 저장해줍니다.
public List<Item> items;
public TextMeshProUGUI[] slotText;
private Slot[] slots;
slotText를 각각 "0"으로 초기화해주고, 보이지 않게 해줍니다.
void Awake()
{
...
for (int i = 0; i < slots.Length; i++)
{
slotText[i].text = "0"; // 처음엔 0으로 초기화
slotText[i].gameObject.SetActive(false);
}
}
각 slotText가 보이게 해주고, 해당 슬롯이 비어있지 않고, item의 이름이 매개변수로 받아온 name과 같으면, 해당 슬롯의 숫자를 1 증가시켜서 text를 새로 저장해주었습니다.
그리고 총 5개를 모으면 다리가 나타나도록 설정했습니다.
public void Check(string name)
{
...
int i = 0;
for (;i < slots.Length; i++)
{
slotText[i].gameObject.SetActive(true);
if (slots[i].item != null && slots[i].item.itemName == name)
{
slotText[i].text = (int.Parse(slotText[i].text) + 1).ToString();
}
if (int.Parse(slotText[i].text) == 5)
{
print("나무를 5개 모았습니다!");
bridge.SetActive(true);
}
}
}