유니티/실습

Unity - Inventory2 - 01 - 시스템 파악, Instantiate

파란색까마귀 2022. 2. 15. 14:09

 

대표사진 삭제
  • 오른쪽 정렬왼쪽 정렬가운데 정렬
  •  
  • 사진 편집
  •  
  • 작게문서 너비옆트임
  •  
  • 삭제

사진 설명을 입력하세요.

대표사진 삭제

사진 설명을 입력하세요.

 

구현목표는 이거다

 

고전 RPG나 파밍류 게임에서 주로 쓰는 인벤 방식인데,

템 크기에 따라 아이템칸을 사용해서 아이템 크기에 따른 패널티가 특징이다

 

단순 아이템 습득에서 끝나지 않고, 한번 더 머리를 써서 최대한 효율적으로 사용해야하기때문에

아이템 그 자체를 컨텐츠로 사용하는 방식이다

 

그런데.. 막상 구현해 보려고 하니까 자주 사용하던 방식인데, 막상 구현해보려고 세세한 부분은 어떻게 되어있는지 확실히 기억이 안나서

디아블로를 다시 받아서 직접 아이템들 들고 내리고 하면서 몇가지 규칙을 확인했다

 

대표사진 삭제

사진 설명을 입력하세요.

1. 마우스 클릭시, 마우스 위치에 아이템이 있을경우 커서아이콘이 사라지고 아이템이 마우스를 따라다닌다

2. 아이템을 들고 인벤토리 위에 위치했을때

2-1. 아이템을 놓을 수 있는 위치가 충분하다면 아이템을 놓는 부분이 녹색으로 표시됨

2-1-1. 마우스 커서가 인벤토리 바깥쪽에 위치할 경우 내부 위치로 한칸씩 보정을 해준다.

2-2. 아이템을 놓을 수 있는 위치에 다른 아이템이 한개 있다면, 아이템을 놓으면서 기존 아이템을 다시 손으로 집어든다

2-3. 아이템을 놓을 위치에 다른 아이템이 두가지 이상이면 빨갠색으로 표시되며 놓을 수 없다

3. 외부에서 아이템 습득 시, 비어있는 칸과 아이템 크기를 비교하여 습득 가능시 자동으로 위치를 찾아서 습득

 

참고로, 지난번엔 2-1항목 까지는 구현했지만 2-2항목 이후로는 구조상 도저히 계산이 불가해서 접었었다

그래서 이번엔 아예 기획부터 철저하게 짜기로 했다

 

구조는 크게 3가지 구조로 계획했다

 

1. 인벤토리 각 칸을 Node로 명명, 해당 노드를 관리하는 인벤토리 매니저 구현

해당 클래스는 여러개의 인벤을 구현하기 위해 독립적으로 구성

2. 아이템 정보를 모아두는 클래스 '아이템', 손에 들고있는 정보를 모아두는 클래스 'hand'

3. 각 정보를 판단해서 관리하는 '연결' 클래스

해당 클래스에서 각종 데이터를 종합해서 진행

 

여기서 핵심은 node와 node를 관리하는 nodemanager 두개다

node가 각각 칸의 정보를 가지고있고 nodemanager에서 각 칸의 정보를 관리하고 취합, 전달하는 방식이다

 

 

그럼 먼저 캔버스 오브젝트부터 생성하자

일반적인 2D 캔버스를 생성해서 Grid Layout Group컴포넌트와 Content Size Fitter를 추가한다

내부 항목은 스크립트에서 처리할 예정

그래도 Constraint 속성은 Fixed Column Count로 변경해주자

나중에 인벤 가로 칸 갯수만 받아서 스크립트로 수정해주면 된다

그외엔 cell size정도만 추후 기획에 맞게 적당히 정해주자

인벤토리 외각 배경을 위해 image를 넣어준다

 

 

 

Node오브젝트도 미리 만들어두고, 인벤 칸이 잘 보이도록 이미지 추가

그리고 마우스위치 확인을 위해 event trigger를 넣고 enter와 exit를 추가해준다

 

그리고 해당 오브젝트는 프리펩으로 빼두자

 

이제 nodemanager 스크립트를 생성하자

	[SerializeField]
	private int m_totalIndex = 30;

	//node
	[SerializeField]
	private GameObject m_nodeParents;
	[SerializeField]
	private GameObject m_node;
	[SerializeField]
	private int m_horizontalCount = 6;


	private int m_vertialCount;
	private Node[] m_nodeArray;

	private int m_currentOverIndex = -1;
 
 

 

 

입력 항목은 이정도로 구성

전체 칸 갯수 30을 잡고 가로 갯수를 6정도로 잡아준다

세로 길이는 외부에서 받지않고 계산해서 사용할 예정이니 private로 만들어주자

 

그리고 프리펩으로 만든 node오브젝트와 해당 오브젝트를 모아줄 부모오브젝트로 아까 만들었던

Grid Layout Group 컴포넌트가 있는 오브젝트를 할당해준다

 

(추가로, 테스트를 위해 아이템 크기를 3x3정도로 할당)

 

private void CreateSlot()
	{
		m_nodeParents.GetComponent<GridLayoutGroup>().constraintCount = m_horizontalCount;

		m_nodeArray = new Node[m_totalIndex];
		m_vertialCount = m_totalIndex / m_horizontalCount;		
	}
 

슬롯을 생성해주는 함수

아까 설정한대로, node 가로 갯수만큼 Grid Layout Group 컴포넌트 constraintCount항목을 변경해준다

 

node배열을 m_totalIndex만큼 초기화

그리고 node세로 갯수를 계산해서 저장해둔다

 

	private void CreateSlot()
	{
		m_nodeParents.GetComponent<GridLayoutGroup>().constraintCount = m_horizontalCount;

		m_nodeArray = new Node[m_totalIndex];
		m_vertialCount = m_totalIndex / m_horizontalCount;

		for (int i = 0; i < m_totalIndex; i++)
		{
			GameObject obj = (GameObject)Instantiate(m_node);
			obj.name = "[" + i % m_horizontalCount + ", " + i / m_horizontalCount + "]\n" + i;
			obj.GetComponentInChildren<Text>().text = obj.name;
			obj.transform.SetParent(m_nodeParents.transform);
		}
	}
 

for문을 사용하여 node프리펩을 m_totalIndex만큼 생성

구분하기 쉽도록 name을 변경해주고 하위 텍스트 컴포넌트에 표시해준다

 

그리고 위치를 m_nodeparents 자식으로 배치해준다

 

그러면 간단하게 구현완료

 

추가로.. 해당 부분은 오브젝트풀 방식으로 변경할 예정이다

Instantiate를 사용해서 오브젝트를 생성하면 속도가 매우 느리기때문에..

실제로도 고작 30개 만드는데 pc사양에서 약간의 멈춤이 발생할정도다

30칸짜리 인벤 하나만 달랑 사용할게 아니라면 다수 오브젝트 생성에 유리한 오브젝트풀로 구현하는게 좋다

 

 

 

 

728x90