Game/Unity

[유니티] 프리팹(Prefabs)과 감지(Detection), 충돌(Collider) (1)

nowkoes 2023. 1. 26. 15:18

목표

- 프리팹의 개념을 이해하고 프리팹 인스턴스를 생성하기.

- 프리팹화된 몹들을 감지하기.


프리팹(Prefabs)

 게임을 하다 보면 동일한 목표를 가진 오브젝트가 여러 마리 생성되는 것을 쉽게 볼 수 있다. 예를 들어 보자. 우리가 한 번 씩 해본 메이플 스토리를 생각해보면, 사냥을 할 때 맵에 있는 몬스터들을 봤을 때 동일한 몬스터가 같은 패턴으로 행동한다. 일정 범위 내의 플레이어를 인식하고, 몬스터의 고유의 행동(공격)을 한다. 만약 이러한 몹들이 생성될 때마다 생성된 수만큼 오브젝트를 생성하고 컴포넌트를 부착한다면 굉장히 비효율적일 것이다. 

메이플스토리의 사냥터 중 하나. 기쁨의 에르다라는 동일한 몹이 맵에 여러 개 생성되어 있다.

 

 이러한 상황을 해결하기 위해 사용하는 것이 바로 프리팹이다. Unity 공식 문서에 따르면 Unity의 프리팹 시스템은 게임 오브젝트를 생성, 설정 및 저장할 수 있으며, 해당 게임 오브젝트의 모든 컴포넌트, 프로퍼티 값, 자식 게임 오브젝트를 재사용 가능한 에셋으로 만들 수 있다고 한다. 즉, 에셋화하는 것이라고 생각하면 편하다. 

 

 이러한 프리팹의 특징은 여러 가지가 존재한다. 먼저 씬에 새로운 프리팹 인스턴스를 만들기 위한 템플릿 역할을 하게 된다는 것이 있다. 템플릿의 역할을 하기 때문에 이 에셋에 대한 편집 사항을 적용하면 모든 인스턴스에 자동으로 반영할 수 있다. 그리고 생성된 프리팹 인스턴스는 서로 독립적으로 동작한다. 하지만 모든 프리팹 인스턴스가 동일하진 않다. 설정을 오버라이드하여 일부 인스턴스를 다르게 만들수도 있지만, 이는 추후에 다뤄보도록 하자.

 

몬스터 프리팹 생성

 지금부터 간단하게 프리팹 시스템을 만들어 보자. 목표는 맵에 동일한 행동을 하는 10마리의 몹을 생성하는 것이다. 지난 포스트에서 다룬 경로를 설정하여 이동하는 것을 몬스터의 패턴으로 정의하겠다.

지난 이동 파트에서 다룬 파일을 그대로 들고왔다.

 

 오브젝트를 프리팹화하는 것은 생각보다 간단한다. 프리팹으로 변경하고 싶은 오브젝트를 만들어 둔 프로젝트로 드래그하면 된다. 오브젝트가 성공적으로 프리팹화되었으면 Hieararchy창과 프로젝트 창에 파랗게 표시될 것이다. 

성공적으로 에셋화된 큐브(Model)

 

 이렇게 프리팹화된 오브젝트는 이미 에셋으로 작동되기 때문에 Hieararchy창에서 지워도 문제가 되지 않는다. 프리팹을 기반으로 한 인스턴스는 런타임 시점에서 월드에 오브젝트로 존재하기 때문에 굳이 하이라키 창에 넣어둘 필요가 없다. 만약 프리팹을 해제하고 싶다면 프리팹을 하이라키 창에 다시 불러와 우클릭을 해 Unpack을 하도록 하자. 

프리팹 해제 방법

 

몹 생성(Instantiate)

 프리팹을 성공적으로 구축했다면, 이제 몹을 생성해보자. 몹을 생성할 때 자주 사용하는 함수가 바로 Object.Instantiate() 함수다. 유니티 공식 문서에 따르면 오브젝트 orginal을 position에서 복제하여 생성할 때 쓰인다고 적시되어 있다.

출처: https://docs.unity3d.com/kr/530/ScriptReference/Object.Instantiate.html

 

 

 이때 몹을 생성하기 위해서는 포인트가 필요하니까 Spawn Point라는 오브젝트를 하나 만들고, 이에 부착할 스크립트 SpawnPoint를 만들자.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SpawnPoint : MonoBehaviour
{
    public PathMove cube;
    public Transform spawnPoint;

    void Update()
    {
        Instantiate(cube, spawnPoint.position, spawnPoint.rotation);
        // cube를 spawnPoint.position에서 spawnPoint.rotation의 회전으로 생성
    }
}

 

 이렇게 작성을 마쳤다면 이제 몹이 게임 시작과 동시에 생성될 것이다. 하지만 문제가 하나 있다. 몹이 Update() 문이 호출될 때마다 생성된다는 것이다. 따라서 우리는 몹을 생성할 때 시간 제한(쿨타임)을 두고, 월드에 생성 제한 수를 둘 것이다. 앞선 코드를 수정하면 다음과 같다.

using System.Collections;
using System.Collections.Generic;
using Unity.Collections;
using UnityEngine;

public class SpawnPoint : MonoBehaviour
{
    public PathMove cube; // 프리팹(몹)
    public Transform spawnPoint; // 스폰 지점
    public float timeToSpawn = 1.5f; // 스폰 시간 간격
    private float spawnCounter; 
    public int amountToSpawn = 10; // 몹 제한 수 

    void Start()
    {
        spawnCounter = timeToSpawn; 
    }

    void Update()
    {
        if (amountToSpawn > 0) // 현재 몹이 1마리 이상일 때
        {
            spawnCounter -= Time.deltaTime;
            // 스폰 시간 간격을 1씩 줄이기

            if (spawnCounter <= 0) // 스폰 시간이 다 되었을 때
            {
                spawnCounter = timeToSpawn; // 다시 시간 초기화
                Instantiate(cube, spawnPoint.position, spawnPoint.rotation);
                // 몹 생성
                amountToSpawn--;
                // 몹 제한 수 줄이기
            }
        }
    }
}

게임 실행 화면


요약

- 오브젝트를 프리팹으로 변경하여 인스턴스화하면 효율성이 증대한다.
- 프리팹 인스턴스를 생성할 때는 시간 간격, 몹 제한 수 등을 설정하여 개발자의 로직에 맞게 프리팹 시스템을 작동시킬 수 있다.
반응형