Programming 

씬 불러오기

 

작성 기준 버전 :: 2019.2

 

[이 포스트의 내용은 유튜브 영상으로도 시청하실 수 있습니다]

 

유니티 엔진의 씬은 게임의 맵이나 레벨 개념에 해당한다. 그리고 대부분의 게임은 하나보다 많은 맵이나 레벨, 즉 씬으로 구성된다. 그래서 게임에서 다른 씬으로 넘어가기 위해서는 씬과 씬 사이를 이동하기 위해서 다른 씬을 불러오는 방법을 알아야 한다.

 

씬 세팅하기

 

 

먼저 프로젝트를 제일 처음 생성했을 때 있는 씬에 큐브 오브젝트를 생성하고 카메라 앞 왼쪽 화면에 보이게 적당히 배치한 다음 씬을 저장한다. [Ctrl + S] 단축키를 누르면 간단하게 씬의 변경 내용을 저장할 수 있다.

 

그리고 프로젝트 뷰의 Scenes 폴더 아래에 지금 로드되어 있는 씬인 Sample Scene의 이름을 Scene1로 변경한다.

 

그 다음에는 이 Scene1에서 이동하게 될 새로운 씬을 생성하자.

 

 

프로젝트 뷰에 우클릭하고 [Create > Scene] 항목을 선택하면 새로운 씬을 생성할 수 있다. 새로 생성한 씬의 이름은 Scene2로 한다.

 

 

이렇게 생성한 씬 애셋을 더블 클릭하면 하이어라키에 열려있던 씬이 Scene1에서 Scene2로 바뀐다.

 

 

그리고 Scene2에는 Shpere 게임 오브젝트를 생성해서 카메라 앞 오른쪽 화면에 보이게 배치한다. 이렇게 하면 Scene1에 있다가 Scene2를 불러오면 화면 앞에 있는 게임 오브젝트의 모양이 바뀌면서 씬이 바뀌었다는 것을 명확하게 알 수 있을 것이다.

 

Scene2를 저장하고 다시 Scene1로 돌아간다.

 

SceneMover 스크립트 작성하기

 

그 다음에는 SceneMover라는 이름으로 C# 스크립트를 생성하자.

 

using UnityEngine.SceneManagement;

 

제일 먼저 스크립트의 상단에 using UnityEngine.SceneManagement; 라는 코드를 작성한다. 이 코드는 개발자가 스크립트 에디터에게 "SceneMover.cs 파일에서 UnityEngine.SceneManagement 네임스페이스에 들어있는 씬과 관련된 기능을 사용하겠다"라고 알려주는 역할을 한다.

 

참고로 네임스페이스라는 것은 C#에서 특정한 기능을 묶어두는 데 주로 사용된다.

 

여기 UnityEngine.SceneManagement 네임스페이스에서는 유니티 엔진의 씬과 관련된 기능들이 담겨있다.

 

public class SceneMover : MonoBehaviour

{

    void Update()

    {

        if(Input.GetKeyDown(KeyCode.Space))

        {

            SceneManager.LoadScene("Scene2");

        }

    }

}

 

네임스페이스 선언이 끝나면 Update 함수에서 스페이스 키를 입력을 받았을 때, SceneManager.LoadScene 함수를 호출하게 만든다. 이 함수로 다른 씬을 불러올 수 있다. 

 

매개변수에 불러오고자하는 씬의 이름이나 번호를 넣으면 된다. 우리는 Scene1에서 Scene2로 이동할 생각이기 때문에 Scene2라는 이름을 넣어주면 된다.

 

코드를 저장하고 에디터로 돌아가서 게임 오브젝트를 하나 만들고 거기에 SceneMover 컴포넌트를 추가한다.

 

 

그리고 플레이 버튼을 누르고 스페이스 키를 눌러보면 Scene2라는 씬이 빌드 세팅에 추가되지 않았거나 애셋 번들로부터 불러올 수 없어서 로드할 수 없다는 로그가 나온다.

 

유니티에서 씬을 불러오기 위해서는 씬이 저장된 애셋 번들이 있든지 아니면 씬이 빌드 세팅에 추가되어 있어야 한다.

 

빌드 세팅에 씬 추가하기

 

씬을 빌드 세팅에 추가 시켜보자.

 

 

우선 상단 메뉴바에서 [File > Build Settings...] 항목을 선택하면 빌드 세팅 창이 열린다.

 

 

창 위쪽에 비어있는 Scenes In Build 칸을 볼 수 있는데 여기에 추가된 씬들은 게임에 포함되어 빌드된다.

 

만들어둔 Scene1과 Scene2를 Scenes In Build 칸에 끌어다 놓으면 Scenes In Build 칸에 추가한 씬이 표시될 것이다.

 

빌드 세팅 창을 끄고 다시 플레이를 시킨 뒤, 스페이스 버튼을 눌러보면 Scene1에서 Scene2로 이동하면서 Cube 오브젝트가 사라지고 Sphere 오브젝트가 나타난다.

 

이게 바로 제일 기본적인 씬 이동 방법이다.

 

Additive로 씬 불러오기

 

첫 번째 방법은 씬을 완전히 이동하는 방법이었다면 이번에는 기존의 씬을 남겨둔 상태로 새로운 씬을 겹쳐서 불러오는 방법을 알아보자.

 

public class SceneMover : MonoBehaviour

{

    void Update()

    {

        if(Input.GetKeyDown(KeyCode.Space))

        {

            SceneManager.LoadScene("Scene2", LoadSceneMode.Additive);

        }

    }

}

 

매개변수 "Scene2"뒤에 콤마(,)를 찍으면 두 번째 매개변수로 넣을 수 있는 옵션이 나타나는데, 형식이 LoadSceneMode 열거형인 것을 알 수 있다.

 

LoadSceneMode 모드에는 Single과 Addtive, 두 가지가 있는데 우선 Single은 기본 옵션으로 앞에서 구현한 것처럼 씬을 불러오면 이전 씬은 완전히 사라지고 새로운 씬으로 바뀌는 옵션이다. 그리고 Additive는 앞의 씬을 남겨두고 거기에 얹어서 새로운 씬을 불러오는 것이다.

 

두 번째 매개변수에 LoadSceneMode.Additive를 넣어준 뒤 코드를 저장하고 에디터로 돌아가서 게임을 플레이 시킨 다음에 스페이스 키를 누르면 Scene1이 남아있는 상태로 Scene2가 불러와지는 것을 볼 수 있다.

 

다만 콘솔 창을 보면 로그가 굉장히 많이 발생하고 씬을 불러오기 전보다 매우 밝은 것을 알 수 있는데, 이것은 씬 안에 소리를 감지하는 Audio Listener라는 컴포넌트와 Directional Light가 두 개가 있어서 발생하는 문제이다. 그리고 메인 카메라도 중복으로 두 개가 있는 상태이다.

 

이런 문제들 때문에 Addtive로 불러올 씬에는 불필요한 카메라나 Directional Light를 만들지 않는 것이 좋다.

 

비동기 방식 씬 불러오기

 

지금까지 사용한 LoadScene 함수는 동기 방식 함수이다. 이게 무슨 의미인가하면 LoadScene 함수로 씬을 호출하면 씬을 불러오는 과정이 끝날 때까지 다른 일을 아무 것도 하지 못한다는 뜻이다.

 

이 예시처럼 씬에 고작 오브젝트가 몇 개만 있는 게임이라면 LoadScene 함수만으로 씬을 불러와도 되겠지만 최신 게임들처럼 씬 하나에 엄청나게 많은 오브젝트들이 들어있는 무거운 게임이라면 씬을 불러오는 긴 시간동안 아무 것도 하지 못하게 될 것이다.

 

다른 씬을 불러오는 도중에 팁을 보여준다든지 플레이어에게 미니 게임을 할 수 있게 한다든지 해서 씬이 불러와지는 시간에 플레이어가 지루함을 느끼지 않도록 하려면 다른 작업을 처리할 수 있어야 한다. 거기에 필요한게 비동기 방식 씬 불러오기이다.

 

public class SceneMover : MonoBehaviour

{

    void Update()

    {

        if(Input.GetKeyDown(KeyCode.Space))

        {

            StartCoroutine(LoadSceneCoroutine());

        }

    }

 

    IEnumerator LoadSceneCoroutine()

    {

        yield return SceneManager.LoadSceneAsync("Scene2");

    }

}

 

LoadSceneAsync 함수를 사용하면 함수가 씬을 불러오는 도중에 다른 작업을 처리할 수 있게 된다.

 

단, 이 함수를 제대로 사용하려면 코루틴과 함께 사용해야 한다.

 

코드를 저장하고 에디터로 돌아가서 게임을 플레이 시킨 다음 스페이스 키를 누르면 사실 눈에 띄는 변화는 없다.

 

비동기 씬 로딩이 효과가 있으려면 그만큼 불러올 씬이 무겁고 불러올게 많아야 의미가 있다.

 

비동기 씬 불러오기 방식을 응용하는 방법은 아래의 포스트에서 확인할 수 있다.

 

[로딩 화면 구현하기(UI 방식)]

 

[로딩 화면 구현하기(로딩 씬 방식)]

반응형

Tutorial (2)

유니티 에디터의 화면 구성

 

작성 기준 버전 :: 2018.3.1f1

 

 

유니티 에디터로 프로젝트를 처음으로 열면 화면이 아래의 이미지와 같이 구성되어 있다.

 

 

 

이 화면의 구성에 대해서 하나씩 알아보도록 하자.

 

 

씬(Scene) 뷰

 

 

에디터 레이아웃 구성의 한 가운데 있는 것은 Scene 뷰다. 유니티에서 씬(Scene)이라는 개념은 일종의 맵(Map)이나 레벨(Level)에 해당한다. 씬 뷰는 이러한 씬에 배경을 꾸미기위해 소품이나 배경 건물 등을 배치하는데 사용된다.

 

 

하이어라키(Hierarchy) 창

 

 

씬 뷰의 좌측에 있는 하이어라키 창은 씬에 배치되어 있는 오브젝트들을 보여준다. 가장 상단에 SampleScene이라는 이름으로 현재 열려있는 씬의 이름이 표시되고, 그 아래에 그 씬에 포함된 오브젝트들이 나타난다. 기본적으로 배치되어 있는 오브젝트는 Main Camera라는 이름의 카메라와, Directional Light라는 이름의 조명이다.

 

 

프로젝트(Project) 창

 

 

프로젝트 창은 현재 프로젝트에 포함된 텍스처나 모델링, 스크립트, 씬 등의 애셋(Asset)을 보여주는 창이다. 개발 경험이 많지 않은 경우에는 프로젝트 창에 애셋들이 추가되는 대로 중구난방으로 쌓아두는 일이 많은데, 애셋들을 적절하게 분류해서 정리해두는 버릇을 들여두는게 나중에 필요한 애셋을 찾거나 불필요한 애셋을 정리할 때 큰 도움이 되며, 개발 속도에도 긍정적인 영향을 미칠 것이다.

 

 

인스펙터(Inspector) 창

 

 

인스펙터 창은 지금은 아무 내용이 없지만, 하이어라키 창에서 씬에 배치된 오브젝트나 프로젝트 창에서 프로젝트에 포함된 애셋을 선택하면 그것에 대한 자세한 정보를 보여주는 역할을 한다.

 

 

하이어라키 창에서 메인 카메라 오브젝트를 선택하고 인스펙터 창을 보면 메인 카메라 오브젝트의 자세한 정보를 확인하고 수정할 수 있게 된다.

 

 

게임(Game)

 

 

씬 창 뒤에 탭으로 되어 있는 게임 창 탭을 선택하면 씬 창이 뒤로 전환되고 게임 창이 앞으로 나온다.

 

게임 창은 씬 창과 같이 씬을 보여주는 역할을 하지만, 게임 창은 씬 창과는 다르게 카메라가 보여주는 것만을 볼 수 있는 창이다. 즉, 실제 게임에서 보게 될 장면을 보여주는 창이다.

 

 

 

 

 

콘솔(Console) 창

 

 

콘솔 창은 개발도중에 발생한 에러나 경고, 개발자가 기능을 테스트하거나 값을 체크하기 위해 출력시킨 로그 등이 출력되는 창이다. 출력된 로그를 더블클릭하면 비주얼 스튜디오가 열리고 해당 로그가 출력된 스크립트의 위치로 이동하게 된다.

 

로그의 종류

 

 

유니티 엔진에서 로그는 크게 일반 로그, 경고 로그, 에러 로그로 나누어지고, 일반 로그는 데이터의 값이나 진행 상황, 상태를 체크하기 위해 사용되는 로그이고, 경고 로그는 치명적이지는 않지만 수정할 것을 권장하는 로그이며, 에러 로그는 게임이 정지하거나 기능에 심각한 이상이 발생하는 상황에 대한 로그이다.

 

세부적인 버튼의 내용은 다음과 같다.

 

 

뒤의 세 개 버튼은 각각 일반 로그, 경고 로그, 에러 로그 보기 버튼이며, 해당 버튼을 눌러서 원하는 종류의 로그만 볼 수 있다.

 

 

일반 로그만 활성화한 상태이다.

 

 

경고 로그만 활성화한 상태이다.

 

 

 

에러 로그만 활성화한 상태이다.

 

 

Clear 버튼은 현재까지 출력된 로그들을 모두 지운다.

 

 

 

Collapse 버튼은 같은 내용의 로그가 여러 번 출력되면 여러 줄로 표시하지 않고 한 줄로 표시하며 같은 내용의 로그가 몇 번이나 출력되었는지를 보여주는 기능이다. 이것은 로그의 순서가 중요하지 않고, 출력되었느냐 혹은 몇 회나 출력되었는지가 중요한 경우에 사용하게 된다.

 

Clear on Play 버튼은 에디터에서 플레이 버튼을 눌렀을 때, 남아있는 로그를 모두 지우고 플레이를 시작하게 만든다. 남아있는 이전에 띄운 로그가 남아있다면 플레이 중에 뜨는 로그가 보기 힘들어지는 경우가 많기 때문에 사용한다.

 

Error Pause 버튼은 플레이 도중에 에러 로그가 발생하면 플레이를 일시정지 시키는 버튼이다. 에러가 나도 플레이가 계속되면 에러가 발생하는 순간을 놓칠 수도 있기 때문에 에러가 발생한 순간을 잡아내기 위해서 사용하는 기능이다.

 

Editor 버튼은 에디터의 로그를 출력한다는 뜻의 버튼이다. 나중에 모바일 게임을 개발하다보면 APK로 빌드한 앱을 모바일 기기에 설치해서 컴퓨터와 연결하고 실행해서 실시간으로 로그를 보기위해서 사용되는 버튼이다.

 

 

애셋 스토어(Asset Store) 창

 

 

 

 

애셋 스토어 창은 다른 개발자들이 만든 게임 개발용 애셋들을 구매할 수 있는 창이다. 대규모 개발팀이나 회사는 게임에 필요한 모든 리소스들을 개발할 여력이 있겠지만, 소규모 개발팀이나 1인 개발자는 모든 리소스를 만들어내기 매우 어렵기 때문에 다른 사람이 만든 애셋을 구매해서 사용하면 더 빠르게 게임을 개발할 수 있다는 장점이 있다.

 

 

그 외의 창들

 

유니티 엔진에는 방금 화면 구성에서 소개한 창들 외에도 많은 종류의 창들이 존재한다.

 

 

에디터 상단의 메뉴 바에서 Window 메뉴를 클릭해서 드롭다운 메뉴를 펼치면 숨겨진 창들의 목록을 보고 필요한 창을 열어서 사용할 수 있다.

 

 

그 외의 버튼들

 

 

이 버튼들은 씬에 배치된 오브젝트를 이동, 회전, 크기 조절을 하는데 사용되는 버튼들이다.

 

 

이 버튼들은 에디터에서 게임을 실행, 일시정지, 한 프레임씩 넘기기를 하는 버튼이다.

 

 

좌측 버튼부터 순서대로, 팀단위 작업을 위한 유니티 콜라보(Collaborate) 버튼, 유니티가 제공하는 서비스 버튼, 계정 관리 버튼, 씬 창에서 보이기 원하는 레이어를 선택하는 버튼, 유니티 에디터의 레이아웃 버튼이다.

 

 

유니티 에디터 레이아웃 수정하기

 

유니티 에디터의 화면 구성은 사용자가 편한 방식으로 레이아웃을 수정할 수 있다.

 

 

위치를 수정하려고하는 창의 탭을 드래그해서 에디터에서 완전히 떼어내거나 다른 곳에 배치할 수 있다.

 

 

완전히 떼어낸 하이어라키 창

 

 

다른 위치에 배치한 하이어라키 창

 

 

각자 사용하기 편한 방식으로 레이아웃을 배치해보자.

 

 

수정한 레이아웃 저장하기

 

수정한 레이아웃은 저장해두고 언제든지 다시 불러올 수 있다. 에디터 우측 상단 구석에 Default 버튼을 클릭하면 드롭다운 메뉴 중에 Save Layout... 버튼을 클릭하면 수정한 레이아웃의 이름을 지어줄 수 있는 대화상자가 뜬다.

 

 

좌측부터 게임, 씬, 콘솔이 한 묶음으로 묶여있고, 그 다음엔 하이어라키와 프로젝트, 마지막으로 인스펙터로 나열되서 3-2-1로 배치되어 있으니 이 레이아웃의 이름을 Countdown이라고 저장하겠다.

 

 

레이아웃을 저장하고 나면 Default로 되어있던 버튼이 Countdown으로 되어있으며 추가한 Countdown 레이아웃이 드롭다운 목록에 추가되어 있는 것을 확인할 수 있다. 이렇게 레이아웃을 저장해두면, 레이아웃이 바뀌어도 언제든지 손쉽게 자주 사용하는 레이아웃으로 돌아올 수 있다.

 

 

반응형

다른 레벨로 이동하기

 

작성 기준 버전 :: 4.21.1

 

대규모 오픈 월드 게임이 아닌 경우 장소를 이동할 때나 대규모 오픈 월드 게임이더라도 특정한 장소로 이동하는 경우에도 레벨 혹은 씬을 전환하는 방식을 주로 사용한다. 이번 섹션에서는 다른 레벨로 이동하는 방법에 대해서 알아본다.

 

프로젝트 생성

 

LevelOpenTest라는 이름으로 C++ 삼인칭 프로젝트 하나를 새로 생성한다.

 

 

 

레벨 구성

 

프로젝트가 생성되면 레벨은 다음과 같이 꾸며져 있을 것이다.

 

 

그 레벨을 다음과 같이 수정한다. 새로 만든 구역에 들어가면 다른 레벨로 이동하도록 만들 예정이다.

 

 

이 다음에는 이동할 레벨을 추가한다.

 

 

그리고 새로 추가한 레벨을 다음과 같이 꾸민다.

 

 

이 맵을 SecondMap이라는 이름으로 저장한다.

 

 

 

 

 

LevelTransferVolume

 

이 다음에는 콜리전에 플레이어가 닿으면 다른 레벨로 전송시키는 볼륨을 만든다.

 

Actor 클래스를 상속받아서 LevelTransferVolume 클래스를 만든다.

 

 

LevelTransferVolume.h에서 다음 함수와 멤버 변수를 선언한다.

 

protected:
    virtual void NotifyActorBeginOverlap(AActor* OtherActor) override;

private:
    UPROPERTY(EditAnywhere, meta = (AllowPrivateAccess = "true"))
    FString TransferLevelName;

    UPROPERTY()
    class UBoxComponent* TransferVolume;

 

LevelTransferVolume.cpp로 넘어가서 박스 컴포넌트의 기능과 레벨 이동 함수를 사용하기 위해서 다음 전처리기를 추가한다.

 

#include "Engine/Classes/Components/BoxComponent.h"

#include "Kismet/GameplayStatics.h"

 

생성자 함수에 TransferVolume를 초기화 하는 코드를 추가한다.

 

TransferVolume = CreateDefaultSubobject<UBoxComponent>(TEXT("TransferVolume"));
RootComponent = TransferVolume;
TransferVolume->SetCollisionProfileName(TEXT("OverlapOnlyPawn"));

 

NotifyActorBeginOverlap() 함수를 구현한다.

 

void ALevelTransferVolume::NotifyActorBeginOverlap(AActor * OtherActor)
{
    APawn* Pawn = Cast<APawn>(OtherActor);
    if (Pawn != nullptr)
    {
        UGameplayStatics::OpenLevel(this, TransferLevelName);
    }
}

 

UGamePlayStatics 클래스의 OpenLevel() 함수가 이번 섹션의 주 목적이다. OpenLevel() 함수를 호출해서 이동하고자 하는 레벨의 이름을 넣어주면 원하는 레벨로 이동이 가능하다.

 

코드 작성이 완료되면 프로젝트를 빌드하고 언리얼 에디터로 돌아간다.

 

기본 맵의 새로 뚫어놓은 위치에 볼륨을 배치한 뒤 Transfer Level Name을 SecondMap으로 설정한다.

 

 

플레이해서 볼륨을 배치한 곳으로 캐릭터를 이동시키면 지정해준 다른 맵으로 이동하는 것을 확인할 수 있다.

 

 

반응형

+ Recent posts