유니티(Unity) 프로그래밍

Unity Prefabs과 Stack, Queue

게임첫걸음 2024. 9. 26. 00:33

<Prefabs>

짱구 장난감 상자 (Prefab)

 Prefabs은 일종의 오브젝트를 모아놓은 상자라고 생각하면 됩니다. Project창에서 Create -> New Folder로 폴더 생성 후, Prefabs란 이름으로 명명합니다. Unity에서 Profabs 이름의 폴더는 따로 기능이 들어간 폴더로 간주합니다. 위 그림에서 장난감 역할로 넣어놓은 P_Ball 오브젝트가 Prefabs 폴더에 넣으면 이제 이 오브젝트는 필요할 때마다 코드를 통해 복사체(클론)를 생성하여 사용할 수 있습니다. 

 

  • 그냥 Hierarcy 창에서 오브젝트 소환해서 쓰면 안돼? 왜 굳이 그렇게 해야해?

그 이유는 여러 Scene에서 유연하게 사용할 수 있기 때문입니다.

Scene

Scene을 여러 개 사용하는 게임을 개발할 때 Hierarcy창에 똑같은 속성을 가진 오브젝트를 계속 만들어야하는 귀찮은 작업을 Prefabs에 넣어놓은 오브젝트들을 꺼내 사용하는 것으로 작업 효율을 크게 증가시켜줍니다. 그리고 앞써 복사체(클론)라고 언급했는데 Prefabs 폴더 안의 오브젝트를 Hierarcy창에 꺼내와서 막 변환시켜도 원본은 오브젝트는 변하지 않습니다. 혹여나 실험한다고 막 바꿨다가 기존 속성값을 잃어버리는 불상사를 방지할 수도 있습니다.

 

<Stack, Queue추가>

Stack과 Queue를 기억하시나요? 

스택 (Stack) (tistory.com)

 

스택 (Stack)

#include #include #include #include #define MAX_LEN 5int g_iarr[MAX_LEN] = { 0 };int g_curIdx = 0;void Push(int _data); //데이터 삽입용int Pop(); //데이터 제거용 (스택에서 데이터를 꺼내는 기능)void PrintAll(); //출력용inline int

hwangameinformation.tistory.com

큐 (Queue) (tistory.com)

 

큐 (Queue)

#include #include #define MAX_LEN 5#define ERROR_CODE 0xffffffffenum EMenu { kPut = 1, kGet, kExit };int g_queue[MAX_LEN] = { 0 };int g_curIdx = 0;// Put, Get// Enqueue, Dequeuevoid Put(int _data);int Get();void PrintAll();inline int CheckFull() { return g

hwangameinformation.tistory.com

기본적인 개념 등을 이해하기 위해서 이전에 썼던 글을 참고해주시는 것도 좋을 것 같습니다. 간단히 설명하면

  • Stack: 데이터 선입후출
  • Queue: 데이터 선입선출

예를 들어 Prefabs를 이용하여 World에 1개씩 5개를 랜덤한 위치에 소환하였다고 가정해보겠습니다.

Prefabs에서 소환한 5개의 오브젝트

  • Stack에 저장한 상태에서 1개씩 순서대로 Destroy할 시: 5 4 3 2 1 순서로 파괴
  • Queue에 저정한 상태에서 1개씩 순서대로 Destroy할 시: 1 2 3 4 5 순서로 파괴

이제 오브젝트 생성하고 Stack, Queue에 저장한 후, 삭제하여 두 데이터의 특징을 알아보겠습니다.

using UnityEngine;

public class DataSvDt : MonoBehaviour
{
    [SerializeField] private GameObject ballPrefab = null;  //직접 Inspector창을 통해 가져오는 방법
    private GameObject loadBallPrefab = null; //Load기능을 활용하여 Prefab을 가져오기 위한 변수
    
    private Stack<GameObject> stack = new Stack<GameObject>();
    private Queue<GameObject> queue = new Queue<GameObject>();
    
    private void Start()
    {
    	loadBallPrefab = (GameObject)Resources.Load("Prefabs\\P_Ball");
    	loadBallPrefab = Resources.Load("Prefabs\\P_Ball") as GameObject;
    	loadBallPrefab = Resources.Load<GameObject>("Prefabs\\P_Ball");
    }
    
    private void Update()
    {
    	if(Input.GetKeyDown(KeyCode.A))
        {
       	    GameObject ballGo = Instantiate(ballPrefab, 
            Vector3.zero, Quaternion.identity, trasnform);
            GameObject ballGo = Instantiate(ballPrefab, 
            Random.insideUnitySphere * 5f, Quaternion.identity, trasnform);
            queue.Enqueue(ballGo);
            stack.Push(ballGo);
        }
        
        if(Input.GetKeyDown(KeyCode.D))
        {
            GameObject go = null;
            
            if(queue.TryDequeue(out go))
            Destroy(go);
            
            if(stack.TryPop(out go))
            Destroy(go);
        }
    }
}

 Load 키워드에 대한 코드 3줄을 알아봅시다. 물론 셋 중 하나만 사용하면 됩니다. 이건 설명용으로 같은 기능의 코드를 3개 만들어놓은 것입니다.

  • loadBallPrefab = (데이터형)폴더이름.Load("폴더이름\\오브젝트 이름"); : Resources 폴더 내의 Prefabs폴더 안에 있는 P_Ball 오브젝트를 BallPrefab에 정의하라는 뜻
  • loadBallPrefab = 폴더이름.Load("폴더이름\\오브젝트이름") as 데이터형; : Resources 폴더 내의 Prefabs폴더 안에 있는 P_Ball 오브젝트를 GameObject형태로 변환하여 BallPrefab에 정의하라는 뜻
  • loadBallPrefab = 폴더이름.Load<데이터형>("Prefabs\\P_Ball"); : Resources 폴더 내의 Prefabs폴더 안에 있는 P_Ball 오브젝트를 GameObject형태로 변환하여 BallPrefab에 정의하라는 뜻

이제 오브젝트 생성 함수를 해석하겠습니다.

1. A를 누르면 ballGo라는 이름의 게임 오브젝트형 오브젝트를 생성하여 ballPrefab으로 지정된 오브젝트를, 원점 위치에, 기본회전(회전없이)으로 인스턴스화하고, 이 인스턴스는 transform 부모의 자식으로 생성됩니다. 여기서 부모는 이 스크립트를 가지고 있는 오브젝트가 됩니다. 

2. A를 누르면 ballGo라는 이름의 게임 오브젝트형 오브젝트를 생성하여 ballPrefab으로 지정된 오브젝트를, 구의 안쪽에 위치한 5f 반경의 좌표에서 무작위 위치에, 기본회전(회전없이)으로 인스턴스화하고, 이 인스턴스는 transform 부모의 자식으로 생성됩니다. 여기서 부모는 위와 같습니다.

3. Enqueue로 ballGo 오브젝트를 큐에 추가합니다.

4. Push로 ballGo 오브젝트를 스택에 추가합니다.

 

이제 오브젝트 파괴 함수를 해석하겠습니다.

  1. GameObject의 go 변수는 null로 초기화합니다.
  2. 큐에 go라는 오브젝트가 있다면 TryDequeue로 그걸 꺼내려고 시도합니다.
  3. 꺼내는데 성공했다면 그 오브젝트를 파괴합니다.
  4. 스택에 go라는 오브젝트가 있다면 Try로 그걸 꺼내려고 시도합니다.
  5. 꺼내는데 성공했다면 그 오브젝트를 파괴합니다.
  6. 여기서 스택은 선입후출, 큐는 선입선출 방식입니다.

'유니티(Unity) 프로그래밍' 카테고리의 다른 글

코루틴 (Coroutine)을 통한 Picking  (5) 2024.10.03
Unity 카메라  (1) 2024.09.29
Unity Collider(Trigger, Collision)  (2) 2024.09.24
Unity 충돌감지  (1) 2024.09.20
유니티3D 아날로그 시계  (0) 2024.09.19