강께르의 개발일지

[유니티] 20210927_수업 1일차 본문

프로그래밍/유니티

[유니티] 20210927_수업 1일차

강께르 2021. 9. 28. 00:41

많은 부분이 기능으로 제공하기에 WINAPI처럼 프로그래머가 구현하려고 하지 않아도 된다.

3D 그래픽스에 대한 이해가 필요하다.

 

스크립트를 작성할 때 유의할 점

클래스명과 파일명이 일치해야한다.

다르면 게임 오브젝트에 스크립트가 컴포넌트로 추가되지 않는다.

일치하지 않으면 빌드가 되더라도 그 컴포넌트의 기능을 사용할 수 없다.

 

유니티를 옮기거나, 버전 관리를 위해 저장할 때

4개의 폴더만 관리하면 된다.

Assets

Packages

ProjectSettings

UserSettings

나머지는 폴더나 파일은 유니티에 알아서 관리해준다.

 

Packages 폴더 : 기본 기능 외에 필요한 기능을 이 폴더에 포함시키는 형태로 사용된다.

예 : 3d로 프로젝트를 만들면 2d에 필요한 패키지는 포함되지 않아서 만약 사용하고프면 따로 추가해야 한다.

 

object / Object

object : C#의 최상위 클래스인 object형

Object : UnityEngine 네임스페이스에 있는 최상위 클래스인 Object형

 

유니티 상에서 디버그

플레이 중일 때, 편집을 하고나서 중지하면 편집한 내용이 싹 다 플레이 전으로 돌아간다.

 

비주얼 스튜디오 내에서 중단점을 찍고 디버그 버튼(유니티에 연결)을 눌러 디버그를 할 수 있다.

 

조건 : 중단점 찍는 부분에 오른쪽 마우스 버튼을 눌러 조건을 넣을 수 있다.

특정 조건을 만족하면 중단점이 호출될 수 있도록 조정 가능하다.

 

추적 : 중단점 찍는 부분에 오른쪽 마우스 버튼을 눌러 작업을 넣을 수 있다.

비주얼 스튜디오 출력창에 해당 코드를 진행하게 되면 작업으로 타이핑해놓은 것을 출력 가능하다.

 

Debug 클래스

Debug.Log()로 콘솔 디버그 창에 출력이 가능하다.

릴리즈를 위해 있는 기능이기보다는 디버그를 위해 있는 기능이다.

하지만 릴리즈에 이 코드가 제외되지는 않는다.

 

LogWarning

LogError

Log

등 아이콘이 다른 출력문이 있으니 골라 쓰자.

 

DrawRay()로 특정 선을 디버그용으로 그릴 수 있다. 게임 씬에선 보이지 않는다.

 

OnDrawGizmos() 

기즈모 상에 그리는 것을 추가하기 위해 쓰이는 기본 제공 함수이다.

 

: 현재 프로젝트 상에 떠 있는 오브젝트들을 그래픽으로 표현한다.

하이어라키 : 현재 프로젝트 상에 떠 있는 오브젝트들을 텍스트로 표현한다.

- 오브젝트들은 계층구조를 가질 수 있다. AB의 자식 오브젝트가 될 수 있다.

 

씬 파일은 확장자 .unity로 관리된다.

기본적으로 텍스트 입출력으로 관리되는 이 파일은 텍스트파일로 열어서 확인이 가능하다. 있다는 것만 알아두자.

 

씬 : 게임 오브젝트들의 집합

게임 오브젝트 : 하이어라키 뷰에 등록된 것들이자 컴포넌트들의 집합

컴포넌트 : Monobehavior를 상속받은 스크립트들이며 무조건 게임 오브젝트에 추가되어 사용해야하는 것들이다.

컴포넌트가 있는 인스펙터 상에서 하는 모든 조작들은 원래 다 코드로 수행할 수 있는 것들이다.

 

프로젝트를 생성하면 3d 기준으로 게임 오브젝트 두개는 필수적으로 추가되는데 카메라와 광원이다.

 

스프라이트 데이터에 관해

에셋에서 다운로드하고 임포트하여 추가하면 유독 오래 걸리는 시간이 있다.

그 이유는 유니티는 받아온 스프라이트 데이터를 그 자체로 바로 쓰지 않기 때문이다.

실제 유니티 상에서는 해시된 파일로 다시 만든다. 다른 데이터로 가공되어지는 과정이 걸리는 것이다.

 

- MeshRenderer는 겉모습에 대한 컴포넌트인가 보다.

 

코드 상에서 오브젝트 찾기

Find() : 이름으로 찾기. 쓰지 마라. 문자열 비교로 모든 오브젝트를 순회하기에 매 프레임마다 들이는 비용이 너무 많다.

FindGameObjectWithTag() : 유니티 상에서 게임 오브젝트들마다 부여할 수 있는 태그로 찾는 것. 그나마 낫다.

FindObjectOfType<T>() : T라는 이름을 가진 컴포넌트를 가진 오브젝트의 컴포넌트를 반환해준다. 사용하지마라.

 

멤버변수를 public으로 선언하고 원하는 오브젝트를 드래그 드롭하여 할당할 수 있다. 하지만 동적 생성에 대한 인스턴스는 처리하기 힘드므로 코드와 드래그 드롭을 적절히 섞어 쓰자.

 

- 형 변환은 as 연산자를 사용하자.

 

초기화 함수

유니티는 플레이 시, 실행되는 함수의 순서가 있다.

게임 오브젝트 하나에 대한 예시이다.

멤버 이니셜라이저 : 필드에서의 초기화된 값이 있을 때 (동적 추가, 첫 추가 시)

인스펙터의 값 할당 : 인스펙터에 의한 데이터 기록이 있을 때

Awake() : 인스턴스가 생성이 될 때

OnEnable() : 체크박스 활성화될 때

OnDisable() : 체크박스가 비활성화될 때

Start() : 생성 후 다음 업데이트일 때

 

플레이 버튼을 누르면 씬을 비우고 씬에 기록된 게임 오브젝트를 순회하면서 new하고, 그 오브젝트들의 컴포넌트를 순회하면서 new해주는 과정이 수행된다.

 

각 컴포넌트는 new해주는 과정을 거치면 같은 클래스에서 나온 거여도 오브젝트가 다르면 다른 인스턴스이다.

 

실시간 프로그래밍

컴퓨터에 성능에 따라 초당 프레임의 호출횟수가 얼마나 차이나는지 프로그래머가 컨트롤할 수 없다.

그래서 실시간 프로그래밍이 필요하다.

 

오브젝트를 이동시키기

Vector3는 3차원 공간의 한 점으로 쓰일 수 있고, 벡터로 쓰일 때가 있으니 목적에 따라 잘 구분해야한다.

벡터일 때의 의미는 원점으로부터 목적하는 곳까지의 방향성을 의미한다.

속력, 이동량, 힘, 속도 등을 표현한다.

 

Time.deltaTime은 프레임 간의 시간 차이를 구해ㅜㄴ다.

 

유니티에서의 속도는 1f 초당 x 혹은 y 혹은 z가 1만큼의 단위로 움직이는 것을 의미한다.

 

부모-자식 관계에서 로컬 포지션의 원점은 부모 오브젝트의 position이다.

 

ProjectSetting에서 Axis를 설정해주는 것이 있다.

var h = Input.GetAxis("Horizontal");
var v = Input.GetAxis("Vertical");

설정해준 Axis를 함수를 통해 값을 얻을 수 있다.

float 값으로 -1부터 1까지 할당한 키에 따라서 값의 변동이 일어난다.

이를 통해 키가 입력된 것을 이용하고 프로그래밍할 수 있다.

 

하지만 문제가 있다. 이동의 경우 대각 이동할 시 대각 방향으로 1이라는 속도로 움직여야하는 상황이 아닌 1.414만큼의 속도로 움직이게 되는 상황이 일어난다.

 

이 경우 GetAxisRaw()라는 함수를 사용해 GetAxis에 비해 가속도가 추가된 거 같은 부드러운 값 증감이 일어나지 않지만 얻어낸 값에 따른 nomalized를 수행한다면 대각 이동에 대한 문제는 해결될 것이다.

 

Translate()는 첫 번째 매개변수로 위치를 변동시킬 Vector3 값을 넣고 두번째 매개변수로는 해당 오브젝트의 이동을 글로벌 기준인지 로컬 기준인지 설정해준다.

 

회전

float 값 세개를 필요로 하는 EulerAngle을 이용해 회전을 다룬다.

직관적으로 이해하기 쉬워서 EulerAngle을 많이 사용하는 듯 하지만

Rotation을 수정하려면 EulerAngle.x라고 멤버변수에 접근해야한다.

Rotate()를 이용해 x, y, z의 회전을 수행할 수 있다.

 

쿼터니언이라는 4원수를 활용한 회전을 더 많이 사용한다고 한다.

 

Transform.LookAt()을 이용해 한 transform에 대해 추적? 바라보기?가 가능하다.

 

선형 보간법

점 A와 점 B가 있다고 하자.

그 사이에 임의의 점 C가 있다고 할 때,

점 C의 값을 몰라 특정하기 어렵다고 한다.

그 때, A, B를 이용해서 그 사이에 있는 점 C의 값을 구하는 것이 선형 보간법이다.

 

A와 B 사이의 거리를 1이라고 가정하고 그 거리를 의미하는 변수를 t라고 가정하자.

t가 만약 0이거나 0보다 작다면 점 A의 값을 반환할 것이고,

t가 만약 1이거나 1보다 크다면 점 B의 값을 반환할 것이다.

그 외의 상황에서는 거리에 대한 t를 곱하여 값을 구하면 되는 것이다.

 

이를 이용해 한 대상을 트래킹하는 카메라를 구현할 수 있었다.

 

고정적으로 거리를 둘 z값과 y값이 있다고 할 때,

점 A는 카메라의 위치

점 B는 카메라가 최대한 사물을 따라갈 수 있는 최소의 거리 즉, z값과 y값만큼의 거리를 의미하는 점

t는 점 B를 향해 고정적으로 따라가는 속도 X 단위시간

으로 부여한다.

 

이를 이용해 사물이 빠르게 이동해도 카메라는 단위시간에 따라 속도를 내며 사물을 따라갈 것이고

단위 시간마다 카메라의 특정 위치는 선형 보간법에 의해 구할 수 있을 것이다.

 

이를 Transform.Lerp()라는 함수를 이용해 해결할 수 있었다.

 

만약 카메라가 부자연스럽게 사물을 비추는 경향이 있다면

카메라가 마지막으로 위치할 점이 사물의 뒤인지 앞인지 판단해볼 필요가 있다.