본문 바로가기

내일배움캠프/Unity강의 게임개발입문

[TIL 24.05.08] Unity 게임 개발 입문 강의록(1)

강의를 들으면서 동시에 내가 배운 내용을 작성하는 강의록이다. 확실하게 알고 있다 생각하는 내용 일부는 생략할 수도 있다. 

 

목   차

     


    Unity 설치 및 소개

    Unity 설치하는 법

    버전을 2022.3.17으로 맞춰야 한대서 찾으러 갔지만, 처음에는 암만 봐도 찾을 수 없었다!

    당시 상황

    딱 요만큼만 보이고, 내가 찾는 버전은 안보였다. 하지만, 강의에서 시키는대로 하니 내가 필요한 버전을 허브에다가 무사히 다운로드 받을 수 있었다.

    Archive >  download archive(하이퍼링크) > 원하는 버전 찾기 > Unity Hub 버튼 클릭

    이 과정을 따라가면 알아서 유니티 허브에서 해당 버전의 다운로드가 시작된다.

    Unity 소개

    Unity의 개요이다. 하지만 대충은 알아도 아직 남에게 아무 자료 없이 설명할 정도는 아니라 한 번 정리해봤다.

    #게임 엔진이란?

    • 게임 개발할 수 있는 환경(다양한 기능 포함)을 제공하는 프로그램.
    • 그래픽, 물리, 사운드, 애니메이션, 인공지능 등 다양한 요소 관리 및 통합.
    • 혼자 다 만들 능력이 있어도 소형 게임사라면 직접 만들 바에 엔진을 사용해서 다른 기능을 구현하는게 효율적!

    #Unity의 특징

    • 다양한 플랫폼(윈도우, 안드로이드, IOS 등)에서 실행 가능한 게임 개발 (a.k.a. 크로스플랫폼)
    • 사용자 친화적인 인터페이스와 강력한 기능 제공

    개인적으로 안드로이드 스튜디오에서는 UI 만들기가 너무 힘들었다. 물론 내가 그 프로그램의 도구가 손에 익지 않아서도 있겠지만, 둘 다 처음 만지는 입장에서는 유니티가 훨씬 만들기 편했다!

    #Unity의 구조

    • 내부적으로는 C++로 코어엔진이 구성되어 있음.
    • C# 구현부가 코어엔진을 연결해주고, 여기서 C#을 통해 스크립트를 작성함.

     

    기존에는 각 게임사가 자기 고유의 게임엔진을 직접 만들어 썼지만, 작은 게임회사는 고유 엔진을 만들기 힘들고 새로운 기능을 추가하려 해도 품이 많이 들었다. 그에 따라 이미 존재하는 엔진을 변형해서 쓰는 쪽으로 방향성이 변하게 되었다.

    • 유니티는 최초의 게임엔진? X
    • 유니티로 인디게임만 가능? X
    • 개발자만 유니티 활용? 아트, 기획 등도 종종 활용!
    • 최신버전이 무조건 좋나? 이미 개발중에 갑자기 버전을 바꿔버리면 참조하던 meta 데이터에 변화가 생겨버림.
      -> 오류 유발! (Package, Asset도 지원을 안할 수 있음.)
    • 따라서 처음 시작할 때만 버전을 고민해봐야 한다.

    Unity 살펴보기

    유니티 간단 요약

    유니티: 게임 개발을 위한 통합 개발 환경

    #유니티 주요 기능

    • 프로젝트 관리: 새 프로젝트 생성, 프로젝트 파일 구성 및 관리
    • 씬 관리: 게임의 각 장면과 화면을 구성하는 요소
    • 에셋 관리: 게임에 필요한 리소스(이미지, 사운드, 모델 등)를 관리
    • 컴파일 및 빌드: 스크립트 코드를 컴파일하여 실행 가능한 게임으로 빌드
    • 디버깅: 코드 실행 중에 오류를 찾고 수정
    • 에디터 확장 기능: 유니티 에디터를 사용자의 요구에 맞게 확장할 수 있는 기능 제공

    # Scene

    • 연극에서 하나의 막과 유사함.
    • 게임의 각 장면 또는 화면을 의미하고, 씬 단위로 오브젝트를 로드하고 언로드함.
    • 게임은 하나 이상의 씬으로 구성되며, 각 씬은 게임의 특정 부분을 담당함.
    • ex) 메뉴 씬, 게임 플레이 씬, 엔딩 (최소한 이정도는 필요하다!)

    #Game Object

    캐릭터 게임 오브젝트에 필요한 것

    • 충돌 감지
    • 캐릭터 이미지
    • 이름 등을 표시하는 UI
    • 애니메이션

    이처럼, 게임 오브젝트는 여러 요소를 포함하는 컴포넌트의 그룹이라 할 수 있다.

     

    Transform : 위치, 크기, 회전에 관한 정보를 담음

     - 게임 오브젝트의 컴포넌트 중 가장 중요함

     - 입은 장비 정보 등을 부모-자식 관계로 연결해 주는 것도 Transform

     

    보이지 않는 게임 오브젝트: GameManager 등.

     - GameManager: 게임의 심판 역할.

     - Sprite Renderer가 포함되어 있지 않다면 보이지 않는 게임 오브젝트.

     

    #Component

    게임 오브젝트를 구성하는 부품.

    • Transform
    • SpriteRenderer (이미지 표현)
    • Rigidbody (중력/강체물)
    • Script (애니/충돌체/그 외 Custom)

    이런 것들이 Component 들이다.

     

    Monobehaviour: 컴포넌트!

     - 이걸 상속받아야만 AddComponent할 수 있다.

     

    #Asset

    코드를 포함하여 게임에 필요한 모든 리소스

    • 이미지
    • 사운드
    • 모델

    프로젝트의 Asset 폴더에 저장된다.

    유니티 시작하기

    ! 프로젝트 이름 / 경로는 영어로 하는 것을 권장함. (에러의 근원이 됨.)

    #Unity  인터페이스

    노션에 올라와 있는 설명 이미지
    • (B) Hierarchy 뷰: 현재 씬의 게임 오브젝트 계층 구조 표시 및 편집
    • (D) Scene 뷰: 게임 개발자의 관점에서, 현재 씬의 오브젝트들의 배치 등을 관리
    • (C) Game 뷰: 게임 플레이어들의 관점의 뷰로, 카메라가 찍은 플레이 화면을 확인
    • (F) Inspector 뷰: 선택된 게임 오브젝트의 속성 및 구성 요소 편집
    • (G) Project 뷰: 프로젝트의 에셋 표시 및 관리
    • (H) Console 뷰: 게임 실행 중의 로그 및 메시지 표시

    #이번 강의에서 진행할 인터페이스 세팅

    1. 상단 메뉴 - Windows - Layouts - 2 by 3 로 기본 세팅.
    2. Hiearchy 세팅을 왼쪽으로 빼기
    3. Scene과 Game을 나란히 두기
    4. Project를 아래로 길게 나오게 하기
    5. Inspector를 오른쪽에 일자로 빼기

    => 이렇게 세팅하면 위의 인터페이스 설명에서 나온 것과 같은 화면이 완성된다.

    나는 이 레이아웃을 강의해주시는 튜터님 이름을 따서 jiwon이라는 이름으로 저장해주었다. 

    (만약 이 서순을 따랐다면 오른쪽위의 2 by 3 라고 써 있는 토글을, 아니면 Layout이라 써 있는 것을 클릭하면 Save 버튼을 찾을 수 있다.)

    #유니티 조작 배우기

    • 마우스 좌클릭: 게임 오브젝트 선택
    • 마우스 우클릭: w, s, a, d, q, e 키로 씬 뷰를 1인칭 이동 가능, 드래그 시 씬 뷰 회전. (나는 씬 뷰 이동이던데..?)
    • 마우스 스크롤: 줌인 & 아웃
    • 마우스 스크롤 클릭: 씬 뷰 이동
    • alt + 마우스 왼쪽 드래그: 씬 뷰 화면 중심 회전
    • alt + 마우스 오른쪽 드래그: 줌 인 & 아웃

    Scene 창의 왼쪽 위 도구들은 순서대로 q, w, e, r, t, y 를 누르면 그 순서 번째로 바뀐다!

    • Hand Tool (손 도구, 단축키 : Q) : 씬 뷰를 이동시킴
    • Move Tool (이동 도구, 단축키 : W) : 게임오브젝트를 이동시킴
    • Rotate Tool (회전 도구, 단축키 : E) : 게임오브젝트를 회전시킴
    • Scale Tool (스케일 도구, 단축키 : R) : 게임오브젝트의 스케일을 조절함
    • Rect Tool (사각형 도구, 단축키 : T) : 게임오브젝트의 스케일을 사각형 방향으로 조절함
    • Transform Tool (좌표변형 도구, 단축키 : Y) : MoveTool, RotateTool, ScaleTool 을 동시에 사용함.

    VS 시작하기

    #vs 세팅하기

    상단 메뉴 - Edit - Preferences 선택

    좌측단 External Tools - External Script Editor가 Visual Studio로 시작하는지 확인하기.


    게임 개발 맛보기 "PONG"

    가장 기본적이고 쉬운 게임인 "핑퐁" 게임을 만들어본다. 스크립트는 직접 작성하지 않고, Package에 포함된 스크립트를 그대로 사용하되 그 내용만 이해하고 넘어갔다. 

    SpriteRenderer

    2D 이미지를 표현하는 컴포넌트.

    • Sprite(이미지)
    • Color(색상)
    • 상하(FlipY) 좌우(FlipX) 반전
    • 그리는 우선순위 (Sorting Layer, Order in Layer)
    • 등등

    Rigidbody2D

    대충 물리와 관련된 것.

    XXXCollider2D

    충돌의 범위를 결정하는 컴포넌트.

    XXX - 충돌의 모양. (Box, Circle, Capsule 등)

    OnCollisionXXX2D 계열의 이벤트가 충돌 시 발생한다.

    게임 로직 및 상태 관리

    #빌드하기

    1. File - Build Settings
    2. Scenes In Build에 SampleScene이 없다면 Add Open Scenes를 클릭해준다.
    3. 하단의 Build 버튼을 클릭한다.

    TopDown Shooting 프로젝트 세팅

    이번 강의는 앞으로 강의에서 진행할 프로젝트의 전체적인 개요를 보여주는 프롤로그였다.

    클래스 구조(메인)

    이 이미지는 클래스의 메인 구조로, 알아두면 이 강의를 다 들은 후에 개인 프로젝트를 들을 때에도 도움이 되지 않을까 생각한다.

    클래스 구조(기타)

    위에서 표현하지 못한 추가적인 클래스 구조이다.

     

    아직 두 사진 모두 제대로 이해가 되지 않지만, 강의가 끝나고 다시 이 부분으로 돌아와서 복습을 한다면 내가 어떻게 클래스 구조를 짜고 프로젝트를 들어갈지 알 수 있을 것이라 믿는다.


    입력과 캐릭터 이동

    스크립트 라이프 사이클

    스크립트 라이프 사이

     Monobehaviour를 상속받는 클래스들은 유니티 이벤트 함수를 활용할 수 있다.

     

    1. Awake: 게임 오브젝트가 생성될 때 호출되는 메서드입니다. 주로 초기화 작업이 수행됩니다.
    2. OnEnable: 게임 오브젝트가 활성화될 때 호출되는 메서드입니다.
    3. Start: 게임 오브젝트가 활성화되어 게임 루프가 시작될 때 호출되는 메서드입니다. 초기 설정 및 시작 작업을 수행합니다.

    ----첫 프레임이 시작하기 전----
    4. FixedUpdate: 물리 엔진 업데이트 시 호출되는 메서드입니다. 물리적인 시뮬레이션에 관련된 작업을 처리할 때 사용됩니다.
    5. Update: 매 프레임마다 호출되는 메서드로, 게임 로직의 주요 업데이트가 이루어집니다.
    6. LateUpdate: Update 메서드 호출 이후에 호출되는 메서드입니다. 다른 오브젝트의 업데이트가 완료된 후에 작업을 수행하는 데 유용합니다. (카메라 이동 등 랜더링과 직접적으로 관련된 것.)

    ----파괴 계열----

    7. OnDisable: 게임 오브젝트가 비활성화될 때 호출되는 메서드입니다.
    8. OnDestroy: 게임 오브젝트가 파괴될 때 호출되는 메서드입니다. 자원 정리 및 해제 작업이 수행됩니다.

    9. OnApplicationQuit: 게임이 종료되었을 때 호출되는 메서드입니다.

     

    ↓이벤트 함수 실행순서 링크

    https://docs.unity3d.com/kr/2021.3/Manual/ExecutionOrder.html

     

    이벤트 함수의 실행 순서 - Unity 매뉴얼

    Unity 스크립트를 실행하면 사전에 지정한 순서대로 여러 개의 이벤트 함수가 실행됩니다. 이 페이지에서는 이러한 이벤트 함수를 소개하고 실행 시퀀스에 어떻게 포함되는지 설명합니다.

    docs.unity3d.com

     

    핵심 기능 소개

    #Pixel Per Unit

    스프라이트의 픽셀 수와 해당 스프라이트가 게임세계에서 차지하는 공간의 관계를 설명한다. 이 설명은 스프라이트 기준이기 때문에 UI, 이미지로 넘어가면 달라질 수 있다.

    ex) PPU = 100 일 때 스프라이트의 100픽셀은 게임세계에서 1 유니티 단위가 된다.

    • 스프라이트 크기: PPU가 커지면? 스프라이트의 크기는 작아진다.
    • 물리 시뮬레이션: 높은 PPU = 작은 스프라이트 = 높은 해상도의 물리 시뮬레이션
    • 퍼포먼스: 높은 PPU = 더 많은 연산 = 성능에 영향(과도한 계산 주의)
    • 일관성: 모든 스프라이트에 대해 일관된 PPU 값을 사용해야 스프라이트 간 크기 비율을 일정하게 유지할 수 있다. 일관성이 없으면 Pixel Perfect Camera를 활용하기 어려워질 수 있다.

    #계층 구조('Transform' 구조)

    • 각 게임 오브젝트는 Transform 컴포넌트를 가지고, Transform 컴포넌트는 게임 오브젝트들의 위치, 회전, 크기를 정의한다.
    • 게임 오브젝트는 다른 게임 오브젝트의 '자식' 이 될 수 있다.
    • 부모 오브젝트의 Transform이 변경되면(이동, 회전, 크기변경 등) 그 자식 오브젝트의 Transform에도 동일하게 적용이 된다.
    • 오브젝트 끼리의 계층적인 관계를 '트리 구조' 라고 한다. -> 복잡한 씬을 구성하고 관리하는데에 유용하다.
    이동,크기, 회전, 기울기

    Transform이 그렇게 불리는 이유가 뭘까? 

    →부모에 대한 "변환(Transformation)"을 나타내기 때문! 

    첫줄: x 두 번째 줄: y 세번째 줄: 1 →무슨 뜻이지...?

     

    *행렬이 정확히 뭘 뜻하는지에 대한 설명이 조금 부족했다*... 행렬 자체를 모른다기보다는 위의 4개 예시 중 한 개라도 조금 더 자세히 설명해줬으면 나머지는 응용으로 후에 공부라도 할텐데 어떻게 더 자세히 뜯어봐야 할지 감이 잘

    안온다.

     

    GPT에 이 내용에 대해 더 알고 싶어서 그대로 가져가서 물어본 후 가져온 답변에 대한 사진이다:


    이 글을 보고 아주 약간은 이해했다. 저 거대한 3*3 행렬과 [x, y, 1] 행렬을 곱하면 나오는 결과가 오른쪽의 [x+1, y + 1, 1] 의 결과가 되는 것이다.

    그리고 세 번째 행은... 음... 3차원 벡터에서 Quaternion 쓰는 것처럼 2차원에서 scale값 조절하려고 쓰는 것이라 한다. 벡터를 안배워서 명확히는 모르겠지만 대강 이해는 가는 것 같다.

     

    +) 행렬 곱 하는 법: 

    1. 첫 번째 행 = 1 * x + 0 * y + 1 * 1 = x + 1
    2. 두 번째 행 = 0 * x + 1 * y + 1 * 1 = y + 1
    3. 세 번째 행 = 0 * x + 0 * y + 1 * 1 = 1

    #로컬좌표계(Local Coordinate System) & 월드좌표계(World Coordinate System)

    로컬 좌표계: 유니티 인스펙터 창에서 볼 수 있는 position, scale, rotation 등.

    이는 월드 좌표가 아닌 부모에 대한 좌표이며, 부모에 대해 x축으로 2만큼 떨어져 있으면 오브젝트의 로컬 포지션은 (2, 0, 0)이 되는 것이다. 

    즉, <로컬 좌표계 = 부모에 대한 상대위치> 이다. 

    ex) localPosition, localRotation, localScale 등. (feat. Script)

     

    월드 좌표계: 게임 세계의 전체적인 참조 프레임을 기준으로, 모든 게임 오브젝트가 공유하는 게임 환경 내의 절대적인 위치를 뜻한다.

    <월드 좌표계 = 절대 위치> 

    ex) position, rotation, lossyScale 을 통해 참조한다.

    #Input.GetAxis

    • 유니티의 입력시스템(InputManager?) 에서 사용하는 메서드.
    • 입력 축의 값을 반환함. (Axis의 뜻이 x축 할 때의 그 축.)
    • -1 ~ 1 사이의 값을 반환.
    • 1은 똑바로, -1은 거꾸로, 0은 수평 상태라 생각하면 될 듯?
    • ex) 수평 이동 처리: Input.GetAxis("Horizontal")을 사용함. *스펠링 주의*
    • 이 값은 플레이어의 이속, 회전소도와 같은 변수에 적용하여 게임오브젝트를 제어할 수 있다.
    • 끝에 Raw를 붙이면 미끄러지는 듯한 느낌을 덜 받을 수 있다.

    #Time.deltaTime

    이전 프레임으로부터 현재 프레임까지의 경과 시간을 알리는 메서드.

    프레임 속도와 무관하게 일정한 시간 간격으로 동작하는 게임을 만들 때 사용됨. (Update가 프레임 단위이기 때문.)

    ex) transform.Translate(Vector3.forward * speed * Time.deltaTime) -> 프레임과 무관한 이동속도 보장. 

     

    +) delta: 차이를 전통적으로 뜻해옴.(함수 배울 때 그 세모모양 그거)

     

    #접근 제한자와 직렬화 속성

    Public, Private, Protected: 설명 생략.

     

    [SerializeField]: 직렬화 하려는 Public이 아닌 멤버 위에 붙여주면 직렬화가 가능하게 한다.

    (단, 애초에 직렬화가 안되는 것들은 제외: 클래스 위에 처럼.)

    public class ExampleClass : MonoBehaviour
    {
        public int publicVariable;
        private int privateVariable;
        
        [SerializeField]
        private int serializedFieldVariable;
        
        private void Start()
        {
            publicVariable = 10;  // 외부에서 접근 가능
            privateVariable = 20; // 클래스 내부에서만 접근 가능
            serializedFieldVariable = 30; // 인스펙터에서 접근 가능
        }
    }

     


    Input System으로 입력 업그레이드!

    InputManager의 문제점

    #조이스틱 등 다양한 입력 장비 대응

    • 다양한 플랫폼에 대응하기 힘들다.
    • 키 리바인딩(키셋팅 변경) 역시 힘들.

    #입력 처리와 실제 로직 실행 주체의 분리 여부

    우리가 만들 게임은 TopDownController - TopDownInputController의 상속관계로 분리가 되어 있다. 또, Movement는 별도로 나누어져 있다.

    => 입력 처리와 실제 로직의 실행 주체를 분리하기 위해서!

    +상속 관계: 몬스터와 캐릭터를 일괄적으로 관리할 수 있도록 하기 위해서.

     

    이러한 설계 원칙을 단일 책임 원칙(Single Responsibility Principle - SRP) 이라고 한다.

    New Input System

    #핵심 개념

    • Input Action: 입력 행동 정의
    • Input Action Asset: 여러 입력행동을 그룹화한다.
    • Player Input Component: 자동으로 입력 행동을 처리하고 해당 게임 오브젝트에 메시지를 보낸다.

    #장점

    1. Cross-Platform Compatibility: 다양한 입력장치에 대해 일관된 방식으로 작동.
    2. Rebinding: 플레이어가 게임 내에서 입력 설정을 변경할 수 있음.
    3. Multiplayer Support: 여러 플레이어가 동일 장치/각각의 장치에서 플레이 할 때 입력을 쉽게 처리함.

    설계하기

    TopDownController: 몬스터, 캐릭터 등의 행동의 전반적인 구성에 대한 정의.

    ㄴPlayerInputController: 외부 기기를 통해 입력받은 플레이어의 행동.

    TopDownMovement: 실제로 이동할 때 Controller가 호출할 예정.

     

    Action을 이용한 관리: 옵저버 패턴. Invoke. 다른 말로는 PubSub 패턴이라고도 함. (Publish - Subscribe)

     

    마우스 관련 이벤트: OnLookEvent 정의&호출.

    플레이어 만들기

    Send Messages: 같은 게임오브젝트의 모든 컴포넌트에 뿌려지는 메시지를 날림.

    Broadcast Messages: 같은 게임오브젝트와 그 자식 게임오브젝트의 모든 컴포넌트에 뿌려지는 메시지를 날림.

    Invoke Unity Event: OnClick 처럼 UnityEvent 형태로 관리됨.

    Invoke C Sharp evnents: PlayerInut.OnActionTRiggered에 호출하고 싶은 이벤트 등록해서 어떤 이벤트인지 확인해서 쓸 수 있음.

    #VS에서 Ctrl + "." 하면 클래스를 새로운 .cs 파일로 함.


    충돌 처리와 맵 구성

    충돌과 각 컴포넌트의 이해

    Unity에서 충돌과 관련하여 중요한 것: Collider & Rigidbody 

    물리 시뮬레이션 & 충돌 감지를 처리하는 데에 필수적임.

    #Collider

    • 게임 오브젝트에 물리적 형태 부여 -> 충돌감지를 가능하게 함.
    • BoxCollider: 사각형, Sphere는 구형, Mesh는 복잡한 메시 형태.
    메시 콜라이더 예. 출처: https://ssabi.tistory.com/45

    메시의 뜻: 점(Vertex), 선(Edge), 면(Face)의 집합

    #Rigidbody

    • 게임 오브젝트에 물리 법칙을 적용.
    • 충돌하는 두 객체 중 한 쪽(주로 움직이는 쪽)에는 Rigidbody가 있어야 Collider와 충돌할 수 있음.
    • Trigger 역시 Rigidbody 필요함. 
    • 이는 움직이는 쪽이 물리 시뮬을 하면서 충돌체크를 하기 때문!

    충돌 시의 이벤트 예(2d면 2D가 있어야 함.):

    • OnCollisionEnter
    • OnCollisionStay
    • OncollisionExit

    타일맵

    Unity의 Tilemap 시스템을 사용하면 타일 기반의 게임 환경을 쉽게 만들 수 있다.

    #Tilemap 시스템의 구성요소

    • Tilemap GameObject: 타일맵 구조를 구성하는 데 사용. Tilemap Grid의 자식. 특정 타일의 배치를 관리.
    • Grid GameObject: 모든 타일맵이 위치하는 기본 격자.
    • Tilemap Renderer: Tilemap의 모양을 실제로 그리는 역할.
    • Tilemap Collider 2D: Tilemap에 물리적인 경계를 추가하는 데 사용. (아마 맵의 끝...?)
    • Tile Assets: 개별 타일의 모양과 동작을 정의. 타일 여러개를 묶어 Tileset이라고도 함.

     


     

    마무리

    생각보다 고작 1주차짜리임에도 불구하고 너무 많은 내용들(물론 매우 알차긴 했다)을 담고 있어서 놀랐다. 강의 시간 자체는 5시간 언저리, 거기다 2배속으로 듣고 있기에 이론적으로는 2시간 반 가량이면 다 들어야 하지만 2배속으로 듣고 있음에도 모르는 개념이 나올 때마다 잘 살펴보고 실습도 해보고, 이해한 대로 TIL까지 쓰면서 진행하다보니 그 2배 즈음 되는 9시간(밥 먹는 시간 2시간 + 발제&팀 노션 정리 포함하면 12시간)을 소모했는데도 결국 절반 정도밖에 듣지 못했다. 내일 나머지 전부 다 듣고 개인 프로젝트 틀 까지는 개인 레포지토리에 올릴 수 있기를 희망한다.

     

    저번에 보니 나한테는 없었지만 개인 프로젝트 할 때도 ReadMe 와 commit을 신경써달라는 피드백을 받은 동기들이 있어서 그 점 역시 참고해 혼자만의 git 컨벤션을 어느 정도 지켜서 해볼 예정이다.