[유니티] Unity 입문하기 3 :: Scripting 기초, Time.deltaTime
이번 글에서는 유니티 스크립트를 작성하기 위한 기초적인 개념에 대해서 설명하겠습니다.
먼저 저번에 배웠던 Script에 대해서 정리하면서 복습을 해봅시다!
Review 1 :: 용어 정리
- 스크립트(Script)란?
우리가 만드는 컴포넌트의 설계 도면(다른 말로 청사진 또는 Class). - 컴포넌트(Component)란?
게임오브젝트에 들어갈 실질적인 기능. (Ex) Camera, Audio Listener, Transform, Rigidbody,... - 게임오브젝트(GameObject)는 부착된 컴포넌트들에 의해서 동작을 하게 된다. (Ex) Camera컴포넌트가 달린 게임오브젝트는 카메라의 기능을 하고 달린 Transform컴포넌트의 위치가 (0, 0, 0)인 게임오브젝트는 월드상의 위치가 (0, 0, 0)이 된다.
Review 2 :: 기본적인 Component는 유니티가 제공해주는데 왜 Script를 우리가 만들어야 할까? 다른 말로 왜 기능을 우리가 따로 만들어야 할까?
그 이유는 유니티의 기본 컴포넌트만으로 우리의 게임을 제대로 구현할 수 없기 때문입니다. Script를 우리가 만들면 게임오브젝트의 동작을 시간의 지남에 따라 혹은, 어떤 이벤트가 발생했을 때, ..., 다른 컴포넌트들의 값들을 바꿔서 반응을 하거나 게임 오브젝트의 동작/상태를 제어할 수 있습니다.
Review 3 :: 스크립트를 만들자마자 자동 생성되어있는 Start와 Update는 뭘까?
스크립트의 기본이라고 할 수 있으며 만들면 자동으로 생성돼 있는 Start()와 Update()에 대해서는 "Unity 입문하기 2 :: 기본 개념 및 Script 소개"에서 미리 설명을 했습니다.
표로 정리해보자
지금까지는 복습이였고 오늘 새로 가르쳐 주고 싶은 것은 다음과 같습니다.
- (Console 창에) Debug 메시지 출력하기.
- Drag and Drop으로 변수 초기화하기.
- Time.deltaTime - 컴퓨터 성능과 무관하게 게임이 작동하기. (Ex) FrameDrop이 일어나면 총알이 느리게 가고 성능이 엄청 좋은 컴퓨터면 총알이 빠르게 나아가는 현상 해결하기.
제가 생각하기엔 유니티 스크립트를 짜기 시작하기 위해서는 이 세 가지 개념들을 가져가야 한다고 생각합니다.
1. Console 창에 Debug 메시지 출력
void Start()
{
Debug.Log("제일 먼저 한번만 출력")
}
void Update()
{
Debug.Log("매 프레임마다 계속 출력")
}
이렇게 하고 한번 콘솔창에 가서 메시지들이 어떻게 출력되는지 확인해보세요!
2. Drag and Drop으로 변수 초기화
아래의 코드와 같이 유니티에서 지원하는 특정한 클래스(또는 자료형)들은 Public이라면 인스펙터창에서 초기화를 할 수 있습니다.
월드상에 존재하는 게임 오브젝트와 같은 것은 Drag and Drop,
에셋 즉, Project창에 있는 파일들도 Drag and Drop,
숫자나 구조체나 문자열과 같은 값들은 우리가 입력할 수 있게 인스펙터 창이 변합니다.
(사실 Public이 아닌 Private이라도 인스펙터에서 초기화하게 할 수 있는 방법이 있습니다. 관심이 있다면 SerializeField라고 검색하시면 나옵니다.)
// 위의 코드 생략
public GameObject myGameObject;
public Transform myTransfrom;
public Vector3 myVector;
public string myName;
public int hp;
// Update함수가 아니라 Start함수에서 아래의 코드를 실행해도 상관이 없습니다.
// 차이는 Start함수에 아래코드를 작성하면 한번만 출력이됩니다.
void Update()
{
// 내가 초기화한 변수들을 출력해봅시다.
Debug.Log(myGameObject.name);
Debug.Log(myTransform);
Debug.Log(myVector);
Debug.Log(myName);
Debug.Log(hp);
// 내가 가져온 오브젝트를 1유니티미터씩 오른쪽으로 움직여라!
myTransfrom.Translate(Vector3.right);
}
// 아래의 코드 생략
인스펙터 창에서 어떻게 변하는지 확인해볼까요?
비어있는 변수들을 인스펙터에서 초기화해보겠습니다.
▶버튼을 눌러서 실행해서 인스펙터에서 초기화한 값들이 실제로 변수들에 초기화됐는지 확인해봅시다.
Null Reference Error (또는, UnsignedReferenceException)가 난다면 아래의 글을 확인해주세요.
아마 실행을 했을 때 콘솔 창에 빨갛게 null reference error가 나오는 분들이 있을 것 같아요. 그 오류 메시지의 뜻은, 간단히 말하자면, "아무것도 참조할 게 없다!"라는 뜻입니다. 그 이유는 아마도 인스펙터에서 초기화를 해주지 않은 비어있는 변수(변수가 가리키는 것이 아무것도 없다는 말입니다.)에 접근하려고 해서일 겁니다. 그럴 경우 간단히, if문으로 null 체크를 해주든지 다 인스펙터 창에서 초기화를 해주든지 하면 위의 코드에서는 해결이 될 겁니다!
잘 실행이 됐다면 아래와 같은 결과가 나올 것입니다!
3. Time.deltaTime을 이용한 컴퓨터 성능과 무관한 동작 구현하기
일단 Time.deltaTime은 뭘까요? 이전 프레임부터 현재 프레임이 일어나기까지 걸린 시간입니다.
이것이 왜 필요할까요?
컴퓨터 성능과 무관하게 게임이 작동하게 만들려면 필요합니다. 아직 안 와 닿으실 겁니다. 제가 컴퓨터 성능 때문에 발생하는 심각한 오류의 예를 한번 보여드리겠습니다. 다음의 예를 봅시다.
(Example)
* 편의를 위해서 유니티에서 position을 크기 1만큼 움직이는 것을 1유니티미터라고 가정하고 설명하겠습니다.
제가 Update함수에 내 캐릭터를 매 프레임마다 1유니티미터씩 오른쪽으로 움직여라! 라는 코드를 구현했다고 해봅시다.
void Update()
{
// 내 캐릭터를 1유니티미터씩 오른쪽으로 움직여라!
transform.Translate(Vector3.right);
}
다음과 같은 코드로 구현된 게임을 하는 사용자 A와 사용자 B가 있다고 합시다. 두 사용자가 게임을 하다가 다음과 같은 상황이 일어납니다.
사용자 A는 갑자기 렉이 걸려서 순간적으로 10fps가 되고 반면 다른 사용자 B는 컴퓨터가 엄청 좋아서 144fps가 됐습니다. 그러면 사용자 A의 캐릭터는 1초에 10유니티미터씩 움직이게 되고 사용자 B의 캐릭터는 1초에 144유니티미터씩 움직이게 됩니다. 이것은 엄청 심각한 오류입니다. 좋은 컴퓨터를 가진 사람이 유리한 게임이 됩니다...
이것을 해결하려면 어떻게 해야 할까요?
Time.deltaTime을 곱해주면 됩니다. 그러면 컴퓨터의 성능과 무관하게 프레임간의 간격에 비례하여 움직이게 됩니다. 자세하게 살펴볼까요?
void Update()
{
// 내 캐릭터를 컴퓨터 성능과 무관하게 움직여라 1초마다 일정한 간격(아래의 코드에서는 1미터)으로 움직여라!
transform.Translate(Vector3.right * Time.deltaTime);
}
사용자 A는 렉이 걸려서 순간적으로 10fps가 됐습니다. 프레임 사이의 간격(Time.deltaTime)은 1초를 약 10번 나누는 것보다 1초를 144번 나누는 것이 더 작으므로 사용자 B에 비해 커집니다. 그러면 우리가 Time.deltaTime을 곱해졌기 때문에 상대적으로 많이 움직이게 됩니다. 그리고 열개의 프레임이 다 지나면 Time.deltaTime의 합은 총 1(초)이 됩니다. (왜냐하면 10fps = 10frame per 1 second이므로).
사용자 B는 컴퓨터가 좋아서 144fps였습니다. 그러면 1초마다 더 많은 프레임이 있어야 하므로 프레임의 간격(Time.deltaTime)이 사용자 A에 비해 더 작아집니다. 사용자 B는 사용자 A에 비해 매프레임마다 더 작고 세밀하게(그러므로 더 부드럽게) 움직이게 됩니다.
결과적으로 위의 코드(Time.deltaTime을 곱한 코드)는 컴퓨터의 성능과 관련 없이 1초마다 1유니티미터씩 움직이는 게임이 됩니다.
댓글
이 글 공유하기
다른 글
-
[유니티] Unity 입문하기 5 :: Tag와 Name으로 게임 오브젝트 찾기
[유니티] Unity 입문하기 5 :: Tag와 Name으로 게임 오브젝트 찾기
2020.02.22 -
[유니티] Unity 입문하기 4 :: Transform, Rigidbody로 게임 오브젝트 이동시키기
[유니티] Unity 입문하기 4 :: Transform, Rigidbody로 게임 오브젝트 이동시키기
2020.02.22 -
[유니티] Unity 입문하기 2 :: 기본 개념 및 Script 소개
[유니티] Unity 입문하기 2 :: 기본 개념 및 Script 소개
2019.12.25 -
[유니티] Unity 입문하기 1 :: 유니티 설치 및 화면 구성
[유니티] Unity 입문하기 1 :: 유니티 설치 및 화면 구성
2019.12.24