멋쟁이사자처럼/유니티 게임 개발 3기

[멋쟁이사자처럼 부트캠프 TIL 회고] 유니티 게임 개발 3기 3일차

MaterialStone 2024. 11. 22. 21:13
namespace UnityGameDevelopment.Day3 {
    public class Outline {
    	public static string Chapter1 = "유니티 에디터: 레이아웃";
        public static string Chapter2 = "게임 오브젝트";
        public static string Chapter3 = "유니티 C# 프로그래밍 기초 2";
    }
}

 

 

1. 유니티 에디터: 레이아웃

씬 뷰

씬 뷰

씬 뷰(Scene View)는 생성 중인 월드를 표시하는 대화형 뷰이며, 장면, 캐릭터, 광원, 게임 오브젝트의 모든 유형을 선택하고 배치하는 데 사용됩니다.

유니티 공식 문서

 

씬(Scene)은 유니티에서 구성할 수 있는 하나의 월드입니다. 여기에 다양한 오브젝트를 배치할 수 있습니다.

씬 기즈모

씬 기즈모

씬 기즈모(Scene Gizmo)는 씬 뷰에 나타나며, 씬 뷰 카메라의 현재 방향을 표시합니다. 이 기즈모로 시야각과 투사 모드를 빨리 변경할 수 있습니다.

투사모드

Perspective 모드

Perspective 모드는 원근법을 적용하여 씬을 표시합니다.

Orthographic 모드

Orthographic(혹은 Isometric) 모드는 원근이 없고, 전면도, 평면도 혹은 측면도를 얻는 데 유용합니다.

도구 모음

도구 모음

도구 모음은 시점 혹은 오브젝트를 조작할 수 있는 도구를 모아둔 오버레이입니다. 손 도구, 이동 도구, 회전 도구, 크기 도구 등이 있습니다. 자세한 내용은 여기를 참고하십시오.

프레임 셀렉트

오브젝트를 선택한 후 F키를 누르면 씬 뷰의 시점을 오브젝트 바로 앞으로 이동시켜줍니다.

 

하이어라키 뷰

하이어라키 뷰

모델, 카메라, 프리팹 등과 같은 모든 게임 오브젝트를 씬에 표시합니다. 계층 창을 사용하여 씬에 사용할 게임 오브젝트를 정렬하고 그룹화할 수 있습니다. 씬 뷰에 게임 오브젝트를 추가하거나 제거하면 계층 창에서도 추가되거나 제거됩니다.

유니티 공식 문서

 

게임 오브젝트 생성

컨텍스트 메뉴

하이어라키 뷰에서 게임 오브젝트 생성을 할 수 있습니다. 하이어라키 뷰의 빈 공간을 마우스 오른쪽 버튼으로 클릭하여 컨텍스트 메뉴를 열고, 생성할 오브젝트를 선택하여 생성합니다.

그룹화

다음과 같이 게임 오브젝트를 그룹화할 수 있습니다.

게임 오브젝트 그룹화

큐브를 2개 만들고 배치합니다. 그 후 하이어라키 뷰에서 두 오브젝트를 선택하고 Ctrl+Shift+G를 눌러 그룹화할 수 있습니다. 혹은 빈 오브젝트를 생성하고 두 큐브 오브젝트를 생성한 빈 오브젝트에 드래그하여 그룹화를 할 수 있습니다.

가시성 및 선택 가능성

가시성 및 선택 가능성

하이어라키 뷰에서 게임 오브젝트별로 가시성과 선택 가능성을 토글할 수 있습니다. 가시성은 월드에는 존재하지만 씬 뷰에서 보이는 지에 대한 여부입니다. 선택 가능성은 도구로 편집 가능성 여부입니다. 각 아이콘을 토글하여 설정할 수 있습니다.

 

게임 뷰

게임 뷰

애플리케이션의 카메라에서 렌더링되며, 최종적으로 퍼블리시된 애플리케이션을 보여줍니다.

유니티 공식 문서

 

게임 뷰에는 해상도 조절을 할 수 있어 다양한 해상도에서 테스트해볼 수 있습니다. 화면을 임의로 확대 축소가 가능하며, 플레이할 때의 각종 통계를 볼수 있습니다. 통계는 에디터에서 플레이 시 갱신됩니다. 그리고 씬 카메라와는 별도로 씬 내 카메라 컴포넌트를 가진 오브젝트에 의해 보고 있는 시점으로 씬이 렌더링됩니다.

 

프로젝트 뷰

프로젝트 뷰

프로젝트에 속한 에셋에 액세스하고 에셋을 관리할 수 있습니다.

유니티 공식 문서

 

애니메이션, 씬, 스크립트, 머티리얼 등 프로젝트가 관리하는 각종 에셋을 한눈에 보여줍니다. 마우스 오른쪽 클릭으로 필요한 에셋을 생성할 수 있고 외부에 있는 이미지나 에셋을 가져올 수 있습니다.

 

인스펙터 뷰

인스펙터 뷰

게임 오브젝트, Unity 컴포넌트, 에셋, 머티리얼, 에디터 내 설정 및 환경 설정을 비롯하여 Unity 에디터의 거의 모든 요소에 대한 설정과 프로퍼티를 확인하고 편집할 수 있습니다.

유니티 공식 문서

 

인스펙터 뷰에서는 게임 오브젝트 활성화 및 비활성화, 게임 오브젝트 이름, 태그, 레이어, 컴포넌트 등의 세부 사항을 설정할 수 있습니다.

 

2. 게임 오브젝트

게임 오브젝트

Unity의 기초적인 오브젝트로 캐릭터, 소품, 배경을 나타냅니다. 독자적으로 많은 것을 하기보다는 실질적 기능을 수행하는 컴포넌트(Components)의 컨테이너 역할을 합니다.

유니티 공식 문서

 

빈 게임 오브젝트

빈 게임 오브젝트 생성

빈 게임 오브젝트는 Transform 컴포넌트를 제외한 아무런 컴포넌트를 가지고 있지 않은 게임 오브젝트입니다. 컴포넌트가 없으므로 화면에 렌더링되지 않는 특징이 있습니다. 게임 오브젝트를 그룹화할 때 사용합니다. 하이어라키 뷰에서 마우스 오른쪽을 클릭하여 컨텍스트 메뉴를 열고 Create Empty를 선택합니다. Ctrl+Shift+N을 사용하여 생성할 수도 있습니다.

 

프리미티브 오브젝트

프리미티브 오브젝트(Primitive Object)는 3D 기본 도형 오브젝트입니다. 프리미티브 오브젝트에는 6가지 종류가 있습니다.

  • 큐브(Cube)
  • 구체(Sphere)
  • 캡슐(Capsule)
  • 원기중(Cylinder)
  • 평면(Plane)
  • 사각형(Quad)

 

평면과 사각형

평면과 사각형

평면과 사각형 오브젝트는 겉으로 보기에는 같아보이지만 면을 이루는 정점의 개수가 차이납니다. 평면은 지형을 만들 때 주로 사용하고, 사각형은 단순 이미지를 표시할 때 사용합니다.

 

버텍스와 엣지, 폴리곤

버텍스, 엣지, 폴리곤, 메시

버텍스(Vertex, 정점)는 하나의 점을 의미합니다. 좌표이외의 색상, 법선 등 다양한 정보를 갖고 있습니다. 엣지(Edge, 모서리)는 두 정점을 잇는 모서리입니다. 폴리곤(Polygon)은 3개 이상의 정점으로 이루어진 도형입니다. 폴리곤이 모여서 하나의 물체를 만들 수 있는데 이를 메시(Mesh)라고 합니다.

 

하이 폴리곤과 로우 폴리곤

하이 폴리곤 vs. 로우 폴리곤

메시를 이루는 폴리곤이 많을 경우 하이 폴리곤, 적을 경우 로우 폴리곤이라고 합니다. 로우 폴리곤은 비교적 폴리곤이 적으므로, 렌더링 시 연산량이 적어 최적화에 유리합니다. 반면 하이 폴리곤은 연산량은 많지만 더 디테일한 부분까지 표현가능합니다.

 

3. 유니티 C# 프로그래밍 기초 2

유니티 C# 스크립트 생성 및 적용

폴더 생성

하이어라키 뷰에서 컨텍스트 메뉴를 열어서 폴더를 생성합니다. 이름을 Scripts라고 설정합니다.

생성된 스크립트

생성한 폴더에 마우스 오른쪽 클릭하여 컨텍스트 메뉴를 열고 C# Script를 생성합니다. 위 이미지는 기본 이름으로 스크립트를 생성한 모습입니다.

 

스크립트를 편집하기 위해 열기 전에 편집하는 에디터를 설정할 수 있습니다.

편집 에디터 설정

유니티 에디터를 설치할 때 Visual Studio 에디터를 설치했다면 External Script Editor에 표시됩니다. 각자 원하는 데이터를 선택한 후 프로젝트 뷰에서 전에 생성한 스크립트를 더블클릭하여 에디터를 실행합니다.

기본 스크립트 코드

스크립트를 생성하면 위와 같은 코드가 작성된 스크립트가 자동으로 생성됩니다. 앞으로 스크립트는 기본 코드에서 수정하여 작성합니다. 유니티 에디터의 콘솔 뷰에 메세지를 출력하는 것으로 스크립트 생성과 적용법은 마무리하겠습니다.

 

코드를 아래와 같이 수정하고 저장합니다.

수정된 스크립트 코드

유니티로 돌아와서 빈 게임 오브젝트를 만든 후 스크립트를 적용합니다.

스크립트 적용을 위한 오브젝트 생성

 

생성한 오브젝트에 수정한 스크립트를 적용합니다. 생성한 오브젝트를 선택하면 인스펙터 뷰에 오브젝트 정보가 표시됩니다. 이 상태에서 프로젝트 뷰에 있는 스크립트를 드래그해서 인스펙터 뷰의 빈 공간에 드래그합니다.

인스펙터 뷰에 스크립트를 드래그 앤 드랍
스크립트가 적용된 오브젝트
플레이 버튼

Ctrl+Shift+C를 눌러 콘솔 뷰를 열고 에디터 중앙에 플레이 버튼을 눌러 실행합니다.

 

출력된 메세지

위 이미지처럼 콘솔 뷰에 메세지가 잘 나오는지 확인합니다.

 

클래스와 객체

클래스 구성 요소

클래스는 객체를 만들기 위한 설계도입니다. 클래스는 내부에 변수라는 데이터 항목과 혹은 함수라는 작업 항목을 가질 수 있습니다. 이를 각각 멤버 변수, 멤버 함수라고 부릅니다. 클래스는 직접 사용하지 않고 클래스로부터 객체를 만들어서 이것을 사용합니다. 따라서 클래스는 유일하게 하나 존재하고 객체는 여러 개 존재할 수 있습니다.

 

class Person {
    public int age;
    
    public void Speak() {
    	// 말하는 작업을 수행하는 코드...
    }
}

 

위 코드는 사람을 모델링하여 age라는 데이터 항목과 Speak라는 작업 항목으로 구성하도록 설계한 예시입니다.

 

객체는 클래스를 본따 만들어지며, 객체마다 각각 메모리에 공간을 차지합니다.

예를 들어, 위 Person 클래스의 객체를 생성하는 코드는 다음과 같습니다.

Person person1 = new Person();
Person person2 = new Person();

person1.age = 20; // person1 객체의 age 변수에 20을 할당합니다.
person2.age = 23; // person2 객체의 age 변수에 23을 할당합니다.
person2.Speak(); // person2 객체의 Speak 작업을 수행합니다.

 

위 코드는 Person 클래스로부터 new 키워드를 사용하여 Person 객체를 생성하는 코드입니다. person1과 person2는 메모리 상에 생성되며, age 변수는 각각 다른 값을 갖을 수 있습니다.

 

변수

변수는 값을 저장할 수 있는 메모리의 한 공간입니다. 유형별로 가질 수 있는 값이 다릅니다. 이를 자료형이라고 합니다.

변수의 자료형은 다음과 같습니다.

  • 정수형
  • 실수형
  • 논리형
  • 문자형
  • 문자열형

변수는 다음과 같이 만들 수 있습니다. 이를 선언한다고 합니다.

int a; // 변수 a를 선언하였습니다.

 

변수는 값을 가질 수 있습니다. 그러기 위해 변수에 값을 할당해야합니다. 변수에 값을 할당하는 것은 다음과 같은 형태로 할 수 있습니다.

a = 10; // 변수 a에 10이라는 정수 값을 할당했습니다.

 

등호(=)는 '양변이 같다'라는 의미가 아니라 '오른쪽에 있는 값을 왼쪽에 있는 변수에 대입하겠다'라는 뜻입니다.

 

변수는 선언과 동시에 값을 할당할 수 있는데, 이를 초기화라고합니다.

int b = 20; // 변수 b를 선언하고 초기화했습니다.

 

다음은 각 자료형별로 변수를 선언하고 초기화하는 코드입니다.

int bananaCount = 1;
float radius = 2.34f;
bool isCompleted = true;
char character = 'a';
string message = "안녕하세요";

 

상수

상수는 변수와는 다르게 변하지 않는 수입니다. 상수도 변수와 마찬가지로 선언해야하며, 자료형을 명시해야합니다.

const float PI = 3.141592f; // const를 붙여 상수를 선언합니다.

 

초기화로만 값을 할당할 수 있고, 그 후에 할당하게 되면 오류가 발생합니다.

함수

함수

함수는 특정한 기능을 수행하도록 나눠진 작업 단위입니다. 수학에서의 함수와 비슷합니다. 하지만 수학에서의 함수와의 차이점은 입력값과 반환값이 없을 수 있다는 것입니다. 입력으로 들어오는 값을 인수(Argument)라고 하며 출력값을 반환값 혹은 리턴값이라고 부릅니다.

 

다음과 같은 형태로 함수를 만들 수 있습니다.

자료형 함수이름(자료형 입력1, 자료형 입력2, ...) {
	// 코드를 작성합니다.
}

 

함수의 반환값에 대한 자료형은 함수 이름 앞에 적습니다. 입력을 받지 않고 싶을 때에는 소괄호 안을 비워둡니다. 입력을 받을 때는 각각의 입력값에 대한 자료형을 명시해야합니다. 반환값이 없을 때는 함수의 반환값에 대한 자료형에 void를 적어둡니다. 하지만 반환값이 있도록 만들 경우, 반드시 함수 안에서 return 문을 사용하여 값을 반환해야합니다.

 

아래는 정수 a와 b, 두 개의 값을 입력받아 a+b를 계산한 정수 값을 반환하는 함수를 보여줍니다.

int add(int a, int b)
{
    return a + b;
}

 

 

함수를 실행하는 것을 '호출한다'고 표현합니다. 함수는 다음과 같이 호출합니다.

함수이름(입력1, 입력2, ...);

 

함수에 들어가는 입력이 없다면 소괄호 안을 비워주고 호출합니다. 입력이 있다면, 순서에 맞게 입력합니다.

다음은 add 함수를 호출하는 예제입니다.

int result = add(2, 3); // 2 + 3을 계산하고 이를 반환하여 새로운 변수 result에 할당합니다.

 

유니티 스크립트의 생명 주기

유니티 스크립트의 생명 주기

 

유니티 스크립트는 위와 같은 순서대로 실행됩니다. 처음에 초기화를 하고, 중앙에 반복 루프를 통해 게임의 데이터 갱신과 렌더링을 반복적으로 수행하도록 설계되어있습니다. 한 번의 반복 루프를 한 프레임(Frame)이라고 합니다. 컴퓨터의 성능에 따라 1초에 반복하는 프레임의 수가 결정됩니다. 이를 FPS(Frame Per Seconds)라고 합니다.

 

각 함수는 특정 시점이 되면 엔진에 의해 실행됩니다. 따라서 위 함수들은 개발자가 직접 실행할 필요는 없습니다. 다음은 실행되는 주요 함수에 대한 설명입니다.

 

Awake 함수

항상 Start 함수 전에 호출되며 프리팹이 인스턴스화 된 직후에 호출됩니다. 게임 오브젝트가 시작하는 동안 비활성 상태인 경우 Awake 함수는 활성화될 때까지 호출되지 않습니다.

 

OnEnable 함수

오브젝트가 활성화된 경우에만 오브젝트 활성화 직후 호출됩니다. 레벨이 로드되거나 스크립트 컴포넌트를 포함한 게임 오브젝트가 인스턴스화될 때와 같이 MonoBehaviour를 생성할 때 호출됩니다.

 

Start 함수

스크립트 인스턴스가 활성화된 경우에만 첫 번째 프레임 업데이트 전에 호출됩니다.

 

Update 함수

프레임 업데이트를 위한 주요 작업 함수입니다. 프레임당 한 번 실행됩니다.

 

OnDisable 함수

동작이 비활성화되거나 비활성 상태일 때 호출됩니다.

 

OnDestroy 함수

오브젝트 존재의 마지막 프레임에 대해 모든 프레임 업데이트를 마친 후 호출됩니다. 오브젝트는 Object.Destroy 또는 씬 종료에 대한 응답으로 파괴될 수 있습니다.

 


실습 및 응용

▶ 해상도 변경해보기

기본 설정
16:9

 

16:10

 

▶ 프리미티브 오브젝트를 하나씩 씬에 일렬로 배치해보기

프리미티브 오브젝트 생성

프리미티브 오브젝트들을 하나씩 씬에 생성합니다. 이를 도구를 이용하거나 인스펙터 뷰의 Transform의 값을 바꿔서 하나씩 이동할 수 있습니다. 하지만 여기서는 한번에 일렬로 배치하는 방법을 써서 배치해보도록 하겠습니다.

프리미티브 오브젝트 전부 선택

 

먼저 프리미티브 오브젝트를 전부 선택합니다.

일정 간격 배치

인스펙터 창에서 Transform 컴포넌트의 X좌표에 위와 같이 L(-20,20)을 적습니다. L(a,b)의 의미는 a에서 b까지 일정 간격으로 배치하겠다는 뜻입니다.

배치 결과

일렬로 배치된 걸 볼 수 있습니다.

 

 프리미티브 오브젝트로 어몽어스 캐릭터 만들어보기

평면 오브젝트 생성

평면 오브젝트를 추가합니다. 그리고 선택을 할 수 없게 만듭니다.

캐릭터 몸통 오브젝트

캡슐 오브젝트를 만들고 Body라고 지어줍니다.

캐릭터 몸통 만들기

캐릭터 몸통을 이리저리 조작해서 넙적하게 만들어줍니다. 파란색 축(Z축) 방향이 캐릭터의 앞쪽을 바라보도록 만들 예정입니다.

두 다리

실린더 오브젝트로 캐릭터의 두 다리를 만들어줍니다.

두 다리

다리 하나를 만들고 조절합니다. 그리고 다리 오브젝트를 선택하고 Ctrl+D를 눌러 오브젝트를 복제합니다. 복제된 오브젝트를 잘 이동하여 왼쪽 오른쪽 다리를 만들어줍니다.

고글

캡슐 오브젝트를 만들어줍니다. 캐릭터의 고글을 만들어 줄 겁니다.

고글

크기와 위치를 잘 조절하여 몸통에 적절히 붙입니다.

생명 유지 장치

큐브 오브젝트를 생성하여 생명 유지 장치를 만들어 줍니다. 이름은 간단하게 Bag으로 지었습니다.

생명 유지 장치

그럴싸하게 배치된 모습입니다.

부모 오브젝트로 그룹화

빈 게임 오브젝트를 생성하여 모든 파츠를 그룹화해줍니다. 파츠를 모두 선택하고 Ctrl+Shift+G를 눌러 묶어줍니다.

어몽어스 캐릭터 결과

어몽어스 캐릭터가 완성되었습니다. 이렇게 보니 맹해 보이네요...

 

 스크립트 만들어서 콘솔에 출력해보기

메세지 변수 출력

메세지 변수를 클래스의 멤버 변수로 추가하고, 이를 출력하는 스크립트를 작성하였습니다.

출력 결과

게임 오브젝트에 스크립트를 추가하고 플레이하여 콘솔 창에 메세지가 출력된 결과를 확인했습니다.

 

 스크립트로 어몽어스 게임의 모델 클래스 구성해보기

어몽어스 캐릭터 클래스

어몽어스 캐릭터 클래스를 설계해봤습니다. 먼저 플레이어마다 구분할 수 있는 각자의 이름이 있어야합니다. 그리고 특수 효과를 위해 캐릭터의 크기를 만들어봤습니다. 그리고 캐릭터별로 색상을 가질 수 있게 색상 변수를 추가하였습니다. 캐릭터는 이동하므로 이동하는 속력을 변수로 만들어보았습니다. 그리고 캐릭터가 임포스터인지 알려줄 수 있는 변수도 추가하였습니다.