개발단에 가입하여 베르의 게임 개발 유튜브를 후원해주세요!

 

베르의 게임 개발 유튜브

안녕하세요! 여러분들과 함께 게임 개발을 공부하는 베르입니다! 게임 개발에 도움이 되는 강좌들을 올리는 채널입니다! [투네이션 후원] https://toon.at/donate/637735212761460238 [유니티 어필리에이트

www.youtube.com

 

안녕하세요! 여러분들과 함께 게임 개발을 공부하는 베르입니다!

이번에는 유니티에서 JSON을 사용하는 방법에 대해서 알아봅시다.

 

사용 엔진 버전 : 2020.3

 

타임라인

0:00 인트로

0:10 JSON이란?

1:04 JSON 데이터의 기본구조

1:50 JSON 데이터 검사기

2:23 Newtonsoft JSON 라이브러리

3:15 유니티 엔진 .NET 세팅

3:56 오브젝트를 JSON 데이터로

6:50 JSON 데이터를 오브젝트로

7:45 유니티에서 JSON 사용시 주의점

10:11 유니티의 JSONUtility

11:39 Vector3 시리얼라이즈

12:44 모노비헤이비어를 상속받는 클래스의 오브젝트 시리얼라이즈

14:27 JSON 데이터 파일로 저장하기

15:47 파일로 저장한 JSON 데이터 불러오기

16:23 JSON 2 C sharp

17:16 아웃트로

 

[예제]

https://drive.google.com/file/d/1G2e87vkxyG2cFRM0YhUp9mpOATCVBkB1/view?usp=sharing

 

스크립트

인트로

안녕하세요. 여러분들과 함께 게임 개발을 공부하는 베르입니다.

이번 영상에서는 유니티에서 JSON을 사용하는 방법에 대해서 알아보도록 하겠습니다.

JSON이란?

JSON을 사용하는 방법에 대해서 알아보기 전에 JSON이 무엇인지 알아보도록 하겠습니다.

JSON은 웹이나 네트워크에서 서버와 클라이언트 사이에 데이터를 주고 받을 때 사용하는 개방형 표준 포맷입니다.

좀 더 쉽게 말해보자면 어떻게 서버와 클라이언트 사이에 데이터를 주고 받을지에 대한 약속 같은 겁니다.

이 JSON이라는 포맷은 텍스트를 사용하기 때문에 사람이 이해하기 쉽다는 장점을 가지고 있습니다.

그래서 유니티에서도 상당히 많이 사용되며, 네트워크 게임을 개발할 때 게임에 필요한 데이터를 주고 받거나, 게임 진행 상황이나 게임 설정을 저장하는 식으로 사용됩니다.

XML이라는 것도 사용 범위가 거의 일치하지만 XML은 JSON에 비해서 가독성이 떨어지고 데이터를 넣거나 꺼내기 위해서 파싱하는 과정이 까다로운데 반해서, JSON은 XML에 비해서 가독성이 좋고 직렬화와 비직렬화 함수를 통해서 오브젝트에서 JSON 데이터로, JSON 데이터에서 오브젝트로 편하게 변환할 수 있다는 장점이 있습니다.

JSON 데이터의 기본 구조

앞서 말했다시피 JSON 데이터는 텍스트로 구성되며 이런 형태의 구조를 가지고 있습니다.

찬찬히 보시면 아시겠지만 JSON의 데이터는 key와 value의 쌍으로 이루어진 데이터로 저장하는데, items와 같이 배열로 된 데이터 역시 저장이 가능하고 객체 안에 객체를 넣는 것도 가능합니다.

그리고 데이터 내용이 문자열로 되어 있기 때문에 사람이 알아보기 매우 쉽습니다.

JSON 데이터에서 중괄호는 객체를 의미하고, 대괄호는 순서가 있는 배열을 나타냅니다.

그리고 JSON은 정수, 실수, 문자열, 불리언, null 등의 데이터 타입을 지원합니다.

추가로 JSON은 주석을 지원하지 않기 때문에, JSON 파일을 사람이 읽고 수정할 수 있도록 할 계획이라면 key의 이름을 명확하게 정해서 이 값이 무엇을 의미하는지 알려주는게 좋습니다.

JSON 데이터 검사기

이런 JSON의 단점으로는 작은 문법 오류에도 민감하게 반응한다는 점입니다.

중간에 중괄호나 대괄호, 콜론, 쉼표가 하나라도 빠지면 JSON 파일이 깨져버리고 문자열 형태인 JSON 데이터를 원하는 데이터로 변환할 수 없게 됩니다.

이런 문제 때문에 구글에서 JSON 검사기를 검색하면 JSON 데이터가 유효한지 검사해주는 웹 페이지들이 많습니다.

JSON 데이터를 작성하고 난 뒤에는, JSON 데이터 파일의 깨짐으로 인한 버그를 막기 위해서 이런 JSON 검사기로 검사하고 사용하는 것이 좋습니다.

Newtonsoft JSON 라이브러리

그럼 이제 유니티에서 JSON을 사용하는 방법을 알아보겠습니다.

유니티에서 JSON을 사용하는 방법은 여러 가지가 있는데 그 중 첫 번째는 Newtonsoft의 라이브러리를 사용하는 것입니다.

먼저 구글에서 Newtonsoft JSON을 검색하면 첫 페이지에서 Json.NET - Newtonsoft 페이지를 찾을 수 있습니다.

이 페이지에 접속하고 Download 버튼을 누른 뒤 아래 쪽에 있는 Json.NET 버튼을 클릭합니다.

그러면 Newtonsoft의 깃허브 페이지로 이동하게 됩니다.

이 릴리즈 페이지에서 최신 버전의 압축 파일을 다운로드 받아줍니다.

다운로드가 완료된 다음에는 받은 파일의 압축을 해제하고 Bin 폴더로 들어가서 이중에 필요한 .NET 버전을 선택합니다.

보통은 .NET 4.5 버전을 선택하면 됩니다.

여기 있는 DLL 파일을 JSON을 사용할 프로젝트 폴더 안으로 옮겨줍니다.

.NET 4.X 이상 세팅

단, 여기서 놓치지 말아야 할 주의 사항이 있습니다.

우리가 임포트한 DLL은 .NET 4버전 이상에서 사용되는 것인데 기본적으로 설정을 건드리지 않은 유니티 엔진은 .NET 2.0을 사용합니다.

그래서 에디터 상태에서는 DLL이 잘 동작하는데 막상 게임을 빌드하면 DLL이 동작하지 않게 됩니다.

이 문제를 수정하기 위해서는 먼저 상단 메뉴 바에서 [Edit > Project Settings] 항목을 선택해서 프로젝트 세팅 창을 열어줍니다.

그리고 Player 항목을 선택하고 Other Settings 카테고리를 보면 Api Compatibility Level 프로퍼티를 볼 수 있습니다.

이 프로퍼티를 .NET 4.X로 변경해줍니다.

오브젝트를 JSON 데이터로

모든 세팅을 마친 다음에는 본격적으로 Newtonsoft의 라이브러리를 사용해보겠습니다.

먼저 해볼 작업은 C# 클래스를 기본으로 생성된 오브젝트에 담긴 데이터를 JSON 데이터로 변환하는 것입니다.

NewtonsoftJsonExample이라는 이름으로 새 스크립트를 생성하고 스크립트 에디터로 이동합니다.

스크립트에서 Newtonsoft JSON 라이브러리를 사용하기 위해서 스크립트의 상단에 Newtonsoft.Json 네임스페이스를 using 선언해줍니다.

이제 Newtonsoft의 JSON 라이브러리를 사용할 준비가 끝났습니다.

본격적인 테스트 이전에 테스트 용도로 사용할 클래스를 하나 정의하겠습니다.

이 클래스에는 JSON에 담을 수 있는 대부분의 타입을 멤버변수로 하나씩 넣도록 하겠습니다.

int, float, bool, string처럼 가장 기본적인 데이터 타입부터 배열, 리스트, 딕셔너리같은 컨테이너 타입, 그리고 사용자가 직접 정의한 클래스 형식도 한 클래스에 묶어서 JSON 데이터로 만들 수 있습니다.

멤버 변수 선언이 끝난 다음에는 생성자에서 각 값을 자동으로 초기화하게 만들어주고 Print 함수를 만들어서 모든 값을 하나씩 출력하는 코드도 작성해줍니다.

JsonTestClass 작성이 끝난 다음에는 NewtonsoftJsonExample클래스의 Start 함수로 이동합니다.

먼저 JsonTestClass의 오브젝트를 생성해서 JSON 데이터로 만들어보겠습니다.

하나의 오브젝트를 문자열인 JSON 데이터로 만드는 과정은 아주 간단합니다.

JsonConvert의 SerializeObject 함수를 호출해서 오브젝트를 매개변수로 넣어주기만 하면 됩니다.

이 과정을 직렬화라고 부릅니다.

이렇게 JSON 데이터로 바뀐 문자열을 출력하게 만든 뒤 코드를 저장하고 에디터로 돌아가서 테스트해보겠습니다.

에디터로 돌아와서는 새 게임 오브젝트를 하나 만들고 방금 만든 컴포넌트를 붙여줍니다.

그리고 게임을 플레이시켜보면 우리가 만든 JsonTestClass의 오브젝트가 문자열로 바뀐 것을 볼 수 있습니다.

문자열로 바뀐 JSON 데이터를 찬찬히 뜯어보면 우리가 클래스의 멤버 변수로 선언해주고 값으로 넣어준 것들이 제대로 문자열로 바뀌어 담긴 것을 확인할 수 있습니다.

JSON 데이터를 오브젝트로

그럼 이제 반대로 문자열로 된 JSON 데이터를 오브젝트로 변환해보겠습니다.

다시 NewtonsoftJsonExample의 Start 함수로 돌아가서 jTest2 변수를 만들고 JsonConvert의 DeserializeObject 함수를 호출해줍니다.

JSON 데이터를 다시 오브젝트로 바꿀 때는 JSON 데이터를 어떤 오브젝트로 변환하는지 명시적으로 함수에 알려줘야합니다.

만약 JSON 데이터가 가진 구조가 함수에 알려준 클래스의 구조와 다르다면 변환 도중에 에러가 발생하기 때문에 잘 확인하고 진행해야 합니다.

JSON 데이터를 다시 오브젝트로 만든 다음에는 변환 확인을 위해서 jTest2의 Print 함수를 호출해줍니다.

코드 작성이 끝나면 코드를 저장하고 에디터로 돌아갑니다.

그리고 게임을 플레이시켜보면 JSON 데이터로 바뀌었던 jTest1의 내용이 정상적으로 JsonTestClass로 바뀌어서 출력되는 것을 볼 수 있습니다.

유니티에서 JSON 사용시 주의점

이번에는 유니티에서 JSON을 사용할 때 주의해야 할 점을 알아보겠습니다.

에디터에서 TestMono라는 이름으로 C# 스크립트를 생성하고 스크립트를 열어줍니다.

그리고 int 타입 멤버 변수만 하나 만들어주고 NewtonsoftJsonExample스크립트로 이동합니다.

이렇게 새 게임 오브젝트를 생성하고 여기에 TestMono를 붙인 다음, 이 TestMono를 가져와서 JSON 데이터로 변환해서 출력하는 코드를 작성합니다.

이 코드의 기본 의도는 클래스에 들어있는 int 타입의 i를 JSON 데이터로 만들어서 저장하려는 것입니다.

하지만 이 코드를 저장하고 에디터로 돌아가서 플레이해보면 전혀 의도대로 동작하지 않고 JsonSerializationException을 발생시킵니다.

로그를 읽어보면 Self Referencing loop, 즉 자기 참조 루프에 빠진 것을 알 수 있습니다.

이 예외는 gameObject에서 gameObject를 호출할 수 있는 순환구조 때문에 생기는 것인데, 이 문제를 해결할 방법은 있지만, 이후에도 다른 예외가 많이 발생하고 몇몇 문제는 해결책이 없기 때문에 Newtonsoft의 JSON 라이브러리로는 모노비헤이비어를 상속받는 클래스의 오브젝트를 JSON 데이터로 시리얼라이즈할 수는 없습니다.

그렇기 때문에 모노비헤이비어를 상속받는 클래스의 오브젝트를 시리얼라이즈하는 대신에 스크립트가 가지고 있는 프로퍼티 중에서 필요한 프로퍼티를 클래스로 묶어서 해당 클래스만 시리얼라이즈 하거나 뒤에서 설명할 유니티가 기본 제공하는 JsonUtility 기능을 사용해서 시리얼라이즈하는 것을 추천합니다.

다음 문제는 Vector3를 시리얼라이즈 하는 문제입니다.

Vector3 역시 간단한 벡터를 담은 클래스를 만들고 시리얼라이즈 하려고 하면 모노비헤이비어를 상속 받은 클래스의 오브젝트를 시리얼라이즈하려고 할 때처럼 Self Referencing loop 문제가 발생합니다.

이것 역시 Vector3의 프로퍼티인 normalized에서 다시 normalized를 호출할 수 있기 때문에 발생하는 문제입니다.

이 문제를 해결하기 위해서는 이렇게 JsonSerializerSetting 오브젝트를 만들고 ReferenceLoopHandling을 Ignore로 설정하고 시리얼라이즈를 해야합니다.

하지만 이런 식으로 레퍼런스 반복을 무시하게 만들어도 normalized 벡터나 벡터의 길이 등의 불필요한 값들이 시리얼라이즈되기 때문에 쓸데없이 JSON 데이터의 길이나 용량이 늘어나는 문제가 생깁니다.

외부 라이브러리를 이용해서 Vector3에서 좌표 값만을 JSON 데이터로 시리얼라이즈하기를 원한다면 이렇게 별도의 시리얼라이즈용 Vector 클래스를 만들어서 시리얼라이즈해야 할 겁니다.

유니티의 JsonUtility

외부 라이브러리인 Newtonsoft의 Json 라이브러리를 알아보았으니 이제 유니티에서 기본 제공되는 JsonUtility를 알아보겠습니다.

그리고 시리얼라이즈와 디시리얼라이즈에 대해서는 앞에서 다 설명했으니 여기서는 한꺼번에 가겠습니다.

먼저 JsonUtilityExample이라는 이름으로 새 C# 스크립트를 생성합니다.

그리고 아까 전에 만들어둔 JsonTestClass 클래스를 이용해서 오브젝트에서 JSON 데이터로 만들겠습니다.

JsonUtility의 ToJson 함수를 사용하면 됩니다.

반대로 JSON 데이터에서 오브젝트로 만들 때는 JsonUtility의 FromJson 함수를 사용하면 됩니다.

나머지는 전부 동일합니다.

다만 JsonUtility의 단점은 기본적인 데이터 타입과 배열, 리스트에 대한 시리얼라이즈만 지원합니다.

그래서 JSON 데이터로 변경된 결과물을 보면 데이터 내에 딕셔너리와 직접 생성한 클래스가 보이지 않는 것을 알 수 있습니다.

직접 생성한 클래스의 경우에는 [System.Serializable] 어트리뷰트를 붙여줘야만 JSON 데이터로 함께 변환되며, 딕셔너리는 아예 지원하지 않습니다.

때문에 딕셔너리를 시리얼라이즈하려면 외부 라이브러리를 사용해야 합니다.

Vector3 시리얼라이즈

이제 유니티의 JsonUtility가 제공하는 특수 기능을 알아보겠습니다.

앞에서도 보았다시피 외부 라이브러리로는 유니티 내장 클래스를 시리얼라이즈할 때 자기 참조 문제가 발생해서 시리얼라이즈가 제대로 이루어지지 않습니다.

특히 Vector3 타입은 유니티에 내장된 클래스로써 위치나 방향을 표시하는데 자주 쓰입니다

그렇기 때문에 이전에 접속한 캐릭터의 마지막 위치 같은 데이터로 저장될 수 있습니다.

하지만 Vector3는 유니티의 JsonUtility나 유니티의 특성에 맞춘 라이브러리가 아닌 일반 JSON 라이브러리를 사용해서 시리얼라이즈를 하면 normalized 프로퍼티로 인해서 Self Reference loop 문제를 발생시킵니다.

이 문제를 해결해도 저장하려고한 좌표값 외에 벡터의 길이와, 제곱 그리고 정규화된 벡터와 그 길이같은 필요하지 않은 정보를 많이 포함하게 됩니다.

하지만 JsonUtility를 사용해서 앞에서 만든 벡터를 담은 클래스로 테스트 해보면 불필요한 값을 제외하고 필요한 좌표만 저장되는 것을 확인할 수 있습니다.

모노비헤이비어를 상속받는 클래스의 오브젝트 시리얼라이즈

그리고 유니티의 JsonUtility를 사용하면 모노비헤이비어를 상속받는 클래스의 오브젝트 역시 시리얼라이즈가 가능합니다.

앞에서 사용한 TestMono 클래스에 간단하게 Vector3 타입의 멤버 변수를 추가하고 JsonUtilityExample의 Start 함수에서 새 게임 오브젝트를 생성하고 거기에 TestMono 컴포넌트를 붙인 뒤 JsonUtility로 시리얼라이즈하는 코드를 작성합니다.

여기서 주의할 점은 모노비헤이비어를 상속받는 클래스의 오브젝트를 시리얼라이즈 할 때는 클래스가 컴포넌트로 붙어있는 게임 오브젝트가 아니라 GetComponent등으로 직접 가져온 클래스의 오브젝트로 시리얼라이즈해야 합니다.

코드를 저장하고 에디터로 돌아가서 테스트해보면 JsonUtility로 모노비헤이비어를 상속받는 클래스의 오브젝트를 시리얼라이즈 했을 때 문제 없이 깔끔하게 오브젝트가 JSON 데이터로 변환되는 모습을 볼 수 있습니다.

그럼 다시 이 데이터를 오브젝트로 변환해보겠습니다.

코드로 돌아가서 FromJson 함수를 사용해서 디시리얼라이즈하는 코드를 작성하고 테스트합니다.

그러면 이렇게 새로운 인스턴스를 생성하지 못했다고 에러가 발생하고 디시리얼라이즈에 실패합니다.

이 문제를 해결하기 위해서는 FromJson 함수 대신에 FromJsonOvewrite 함수를 사용해야 합니다.

이 함수는 JSON 데이터를 오브젝트로 변환할 때 새로운 오브젝트를 만들지 않고 기존에 있는 오브젝트에 클래스의 변수 값을 덮어씌우는 처리를 합니다.

한 마디로 모노비헤이비어를 상속받는 오브젝트의 JSON 데이터를 다시 오브젝트로 만들려면 같은 형태를 가진 오브젝트를 미리 생성한 뒤에 디시리얼라이즈해야 한다는 뜻입니다.

이 기능을 이용하면 게임 내의 오브젝트를 JSON 데이터로 저장해서 게임 진행 상황을 저장하고 다시 불러와서 게임 진행 상황을 원래대로 세팅하는 세이브&로드 기능을 구현할 수 있습니다.

JSON 데이터 파일로 저장하기

그럼 일종의 세이브 파일을 만들기 위해 JSON 데이터로 변환된 정보를 파일로 저장하는 방법을 알아봅시다.

먼저 JsonSaveLoader라는 이름으로 C# 스크립트를 생성합니다.

스크립트 생성이 완료되고 나면 파일 입출력과 문자열 처리를 하기 위해서 스크립트의 상단에 System.IO 네임스페이스와 System.Text 네임스페이스를 using 선언해줍니다.

그리고 Json 기능을 사용하기 위해서 Newtonsoft.Json 네임스페이스도 using 선언합니다.

그리고 Start 함수에서 파일을 저장할 경로와 파일 이름으로 FileStream을 만들어 줍니다.

보통 json 파일은 .json이라는 확장자를 가집니다.

그 다음 문자열인 JSON 데이터를 Encoding.UTF8의 GetBytes 함수로 byte 배열로 만들어줍니다.

그리고 이렇게 만든 데이터를 fileStream에 써줍니다.

코드 작성을 마친 후에 저장하고 에디터로 돌아가서 플레이해보면 지정한 경로에 json 파일이 생성되고 그 내용이 정상적으로 저장된 모습을 볼 수 있습니다.

파일로 저장한 JSON 데이터 불러오기

그 다음은 이렇게 저장한 json 파일을 읽어 들일 차례입니다.

역시 이번에도 FileStream을 생성하되 이번에는 FileMode를 Open으로 설정합니다.

그리고 생성된 fileStream에서 Read로 데이터를 읽어들인 다음, 읽은 데이터를 반대로 string으로 인코딩 해줍니다.

그 다음에 이 문자열을 디시리얼라이즈 해줍니다.

코드를 저장하고 에디터에서 플레이해보면 정상적으로 파일의 JSON 데이터가 로드되어서 오브젝트로 변환되고 오브젝트의 내용이 로그로 출력되는 것을 볼 수 있습니다.

JSON 2 C Sharp

마지막으로 유용한 사이트를 하나 더 추천해드리겠습니다.

보통 서버 단 작업을 하는 개발자와 협업을 하다보면 보통 주고 받는 데이터 타입을 테이블이나 표로 만들어서 주고 받겠지만, 작업이 빠르게 진행되어야 하는 경우에는 그냥 JSON 데이터로 던지고 클라이언트에서 이 JSON 데이터의 구조만 보고 직접 클래스를 짜야하는 경우도 왕왕 발생합니다.

물론 받은 JSON 데이터를 일일이 분석해서 클래스를 짜도 되겠지만 훨씬 간단하고 원터치로 JSON데이터를 클래스로 만드는 방법이 있습니다.

구글에서 JSON 2 C sharp이라고 검색하면 JSON을 바로 C# 클래스로 변환해주는 사이트들이 나옵니다.

이중에서 적당한 사이트를 골라서 접속하고 JSON 데이터를 입력한 뒤 Convert 버튼을 눌러주면 JSON 데이터 구조를 분석해서 자동으로 C# 클래스로 만들어줍니다.

이 코드를 복사해서 클래스 이름만 원하는 대로 바꿔서 사용하면 됩니다.

아웃트로

이번 영상에서는 유니티에서 JSON을 다루는 방법을 알아보았습니다.

이 강좌는 시청자 여러분들의 시청과 후원으로 제작되었습니다.

이상 베르의 게임 개발 유튜브였습니다. 감사합니다.

 

[유니티 어필리에이트 프로그램]

아래의 링크를 통해 에셋을 구매하시거나 유니티를 구독하시면 수익의 일부가 베르에게 수수료로 지급되어 채널의 운영에 도움이 됩니다.

 

에셋스토어

여러분의 작업에 필요한 베스트 에셋을 찾아보세요. 유니티 에셋스토어가 2D, 3D 모델, SDK, 템플릿, 툴 등 여러분의 콘텐츠 제작에 날개를 달아줄 다양한 에셋을 제공합니다.

assetstore.unity.com

 

Easy 2D, 3D, VR, & AR software for cross-platform development of games and mobile apps. - Unity Store

Have a 2D, 3D, VR, or AR project that needs cross-platform functionality? We can help. Take a look at the easy-to-use Unity Plus real-time dev platform!

store.unity.com

 

Create 2D & 3D Experiences With Unity's Game Engine | Unity Pro - Unity Store

Unity Pro software is a real-time 3D platform for teams who want to design cross-platform, 2D, 3D, VR, AR & mobile experiences with a full suite of advanced tools.

store.unity.com

[투네이션]

 

-

 

toon.at

[Patreon]

 

WER's GAME DEVELOP CHANNEL님이 Game making class videos 창작 중 | Patreon

WER's GAME DEVELOP CHANNEL의 후원자가 되어보세요. 아티스트와 크리에이터를 위한 세계 최대의 멤버십 플랫폼에서 멤버십 전용 콘텐츠와 체험을 즐길 수 있습니다.

www.patreon.com

[디스코드 채널]

 

Join the 베르의 게임 개발 채널 Discord Server!

Check out the 베르의 게임 개발 채널 community on Discord - hang out with 399 other members and enjoy free voice and text chat.

discord.com

 

반응형

개발단에 가입하여 베르의 게임 개발 유튜브를 후원해주세요!

 

베르의 게임 개발 유튜브

안녕하세요! 여러분들과 함께 게임 개발을 공부하는 베르입니다! 게임 개발에 도움이 되는 강좌들을 올리는 채널입니다! [투네이션 후원] https://toon.at/donate/637735212761460238 [유니티 어필리에이트

www.youtube.com

 

안녕하세요! 여러분들과 함께 게임 개발을 공부하는 베르입니다!

이번 강좌에서는 유니티 엔진에서 시간과 관련된 프로퍼티들을 제공하는 Time 클래스의 주요 프로퍼티에 대해서 알아봅시다. 본 강좌는 이전에 올라온 Time 클래스 관련 강좌를 하나로 묶은 것입니다.

 

사용 엔진 버전 : 2020.3

 

타임라인

0:00 인트로

0:11 detaTime

3:03 timeScale

4:37 unscaledDeltaTime

6:10 time

7:27 realtimeSinceStartup

8:53 timeSinceLevelLoad

9:56 아웃트로

스크립트

인트로

안녕하세요. 여러분들과 함께 게임 개발을 공부하는 베르입니다.

이번에는 유니티 엔진에서 시간과 관련된 값들을 제공해주는 Time 클래스의 프로퍼티들에 대해서 알아보겠습니다.

deltaTime

제일 먼저 설명할 프로퍼티는 deltaTime 입니다.

먼저 deltaTime에서 delta는 보통 값의 차이를 의미하는 단어입니다.

시간을 의미하는 Time과 조합해서 생각해보면 deltaTime은 차이가 나는 시간이라는 뜻으로 지난 프레임이 완료되는 데까지 걸린 시간 차이를 의미하며 단위는 초 단위입니다.

한마디로 한 프레임을 진행하는데 걸린 시간이라는 뜻이죠.

그래서 게임을 진행하다가 컴퓨터 사양이나 게임의 최적화 문제로 게임의 프레임이 떨어지는 프레임 드랍 현상이 일어나면 이 deltaTime 값은 한 프레임의 화면을 렌더링하는데 걸리는 시간만큼 커지게 됩니다.

보통 30프레임 기준의 게임에서는 한 프레임당 deltaTime이 0.033정도가 나와야하고 60프레임 기준의 게임에서는 한 프레임당 0.016 정도가 나와야 합니다.

유니티 에디터에서 스크립트를 하나 생성하고 Start 함수에서 Application.targetFrameRate를 30으로 지정한 다음 Update 함수에서 Time.deltaTime을 디버그로 출력시키도록 코드를 작성합니다.

코드를 모두 작성한 다음에는 코드를 저장하고 에디터로 돌아가서 아무 게임 오브젝트에나 방금 만든 컴포넌트를 붙이고 게임을 실행해보면 앞에서 말한대로 약 0.033초에 가까운 값이 매 프레임마다 갱신되는 것을 볼 수 있습니다.

그리고 다시 스크립트에서 targetFrameRate를 60으로 변경하고 에디터로 돌아가서 테스트해보면 0.016초에 가깝게 deltaTime 값이 나오는 것을 확인할 수 있습니다.

그럼 이 delta time은 어디에 사용될까요?

그 예시를 보여드리도록 하겠습니다.

먼저 Update 함수에서 W키를 누르면 오브젝트를 이동시키는 코드를 작성해보겠습니다.

이 때 이동 코드에서 캐릭터의 이동 방향과 속도만 이용해서 캐릭터를 이동시키면 문제가 발생하게됩니다.

이 비교 영상처럼 프레임이 10일 때와 60일 때 캐릭터가 다른 속도로 움직이게 되는 겁니다.

이 문제의 원인은 프레임이 10일 때는 1초에 캐릭터를 10번 움직이게 되고, 프레임이 60일 때는 1초에 캐릭터를 60번 움직이기 때문입니다.

좀 더 풀어서 설명해보자면 이 코드에서는 프레임이 10일 때는 1의 속도로 캐릭터를 1초동안 10번 움직이기 때문에 이동한 거리가 10이 되는 것이고, 프레임이 60일 때는 1의 속도로 캐릭터를 1초동안 60번 움직이기 때문에 이동한 거리가 60이 됩니다.

1초 동안 움직인 횟수가 달라서 움직인 거리 역시 달라지는 것이죠.

이것은 컴퓨터의 성능이 오브젝트의 속도에 영향을 미치게 되는 것으로 보통의 게임에서는 발생해서는 안되는 문제입니다.

이 문제를 해결하기 위한 방법이 바로 이 이동 값에 delta time을 곱해주는 겁니다.

이렇게 이동 벡터에 delta time을 곱해주고 나면, 게임이 몇 프레임으로 진행되는지에 전혀 상관없이 오브젝트는 동일한 속도로 움직이게 됩니다.

이런 식으로 이동이나 회전 등 움직임에 있어서 시간의 영향을 받는 기능을 만들 때는 값에 deltaTime을 곱해서 흘러간 프레임 시간만큼만 가중치를 줌으로써 프로세서 속도의 영향에서 자유로워 지게됩니다.

timeScale

그 다음 프로퍼티는 timeScale 입니다.

time scale라는 프로퍼티의 이름을 단순하게 번역해보면 시간의 크기라는 뜻입니다.

이 값을 조절하면 시간이 흐르는 속도를 조절하여 시간이 빠르게 흐르거나 느리게 흐르게 만들 수 있습니다.

C# 스트립트를 하나 생성하고 스크립트 에디터를 엽니다.

스크립트 에디터가 열리고 나면 float 타입으로 timer 변수를 만들어줍니다.

그리고 Update 함수에서 timer 변수에 deltaTime 값을 누적시키며 더하고 그 timer 변수를 이용해서 오브젝트가 Sin 그래프를 따라서 움직이게 만들어 줍니다.

그 아래에는 키보드 화살 키를 눌러서 timeScale를 늘리거나 줄이는 코드를 작성합니다.

그리고 숫자 1을 누르면 timeScale를 1로 만들도록 해줍니다.

코드를 모두 작성한 다음에는 코드를 저장하고 에디터로 이동합니다.

에디터로 이동한 다음에는 큐브 오브젝트를 생성하고 방금 만든 컴포넌트를 붙여줍니다.

이제 게임을 플레이시켜 보겠습니다.

게임이 시작되면 큐브가 왕복으로 움직이는 모습을 볼 수 있는데 이때 위쪽 화살표 키를 누르면 time scale이 커지면서 큐브의 움직임이 빨라집니다.

반대로 아래쪽 화살표 키를 누르면 time scale이 작아지면서 큐브의 움직임이 느려집니다.

그러다가 time scale이 0이 되면 움직임이 완전히 멈춥니다.

그리고 숫자 1 키를 누르면 time scale이 1이 되면서 원래의 속도로 움직입니다.

이런 식으로 time scale을 조절해서 슬로우 모션같은 연출을 할 수 있습니다.

unscaledDeltaTime

그 다음 알아볼 프로퍼티는 unscaledDeltaTime입니다.

delta time에 대해서 설명했을 때 이야기한 것처럼 delta time은 게임에서 플레이어의 입력과 게임 처리, 화면 렌더링 등의 작업이 한 번 처리되고 그 결과물이 플레이어의 모니터에 그려지는 한 프레임이 진행되는 시간을 의미합니다.

이 delta time에 unscaled를 붙임으로써 크기가 바뀌지 않은 delta time을 의미하게 됩니다.

time scale의 영향을 받지 않는 delta time인 것이죠.

새 C# 스크립트를 생성하고 앞에서 만든 컴포넌트에서 오브젝트를 이동시키는 코드를 복사해서 Update 함수에 붙여넣어줍니다.

그리고 timer에 더해주는 값을 deltaTime에서 unscaledDeltaTime으로 바꿔줍니다.

코드를 모두 작성한 다음에는 저장하고 에디터로 돌아갑니다.

그리고 씬에 새로운 3D 오브젝트를 배치하고 거기에 새로 만든 컴포넌트를 붙여줍니다.

그 다음 게임을 플레이시키면 거의 비슷한 속도로 움직이는 두 오브젝트가 보일 겁니다.

이 때 화살표 키를 눌러서 time scale을 조절하면 delta time으로 움직이는 오브젝트의 속도는 time scale의 영향을 받아 느려지거나 빨라지지만, unscaled delta time으로 움직이는 오브젝트의 속도는 전혀 영향을 받지 않고 동일한 속도로 움직이는 것을 볼 수 있습니다.

이런 식으로 어떤 오브젝트의 움직임이 time scale의 영향을 받지 않기를 원할 때는 unscaled delta time을 사용해야 합니다.

time scale과 delta time, unscaled delta time을 적절하게 조합해서 사용하면 특수한 스킬로 적들은 멈춰있거나 느려졌는데 플레이어만 정상적인 속도로 움직이는 기능을 연출할 수 있습니다.

time

그 다음 프로퍼티를 설명하기 전에 씬을 하나 새로 생성합니다.

Time 클래스의 프로퍼티인 time은 게임이 시작된 이후로부터 흐른 시간을 보여주는 프로퍼티입니다.

유니티 에디터에서 새 C# 클래스를 생성하고 스크립트 에디터를 열어줍니다.

비주얼 스튜디오가 열리고 나면 클래스의 상단에 UnityEngine.UI 네임스페이스를 using 선언해줍니다.

그리고 Text 타입으로 측정한 시간을 보여줄 timeText 변수를 선언해줍니다.

그 다음 Update 함수에서는 Time.time 값을 문자열로 만들어서 timeText로 출력하는 코드를 작성합니다.

코드를 모두 작성한 다음에는 코드를 저장하고 에디터로 돌아갑니다.

에디터에서는 Hierarchy 뷰에 우클릭해서 [UI > Text] 항목을 선택해서 텍스트 UI를 생성합니다.

그리고 Canvas 게임오브젝트에 방금 만든 컴포넌트를 붙인 뒤 Time Text 프로퍼티에 방금 만든 텍스트 UI를 할당해줍니다.

그 다음 게임을 플레이해보면 게임이 시작된 이후에 흐른 시간이 계속해서 올라가는 모습을 볼 수 있습니다.

realtimeSinceStartup

그 다음에 설명할 프로퍼티는 realtimeSinceStartup입니다.

이 realtimeSinceStartup 역시 time과 같이 게임이 시작된 이후로부터 흐른 시간을 보여주는 프로퍼티입니다.

그럼 이 realtimeSinceStartup 프로퍼티가 time 프로퍼티와 어떤 차이가 있는지 알아보겠습니다.

다시 스크립트로 돌아가서 Time.time을 출력하는 timeText에 realtimeSinceStartup도 함께 출력하도록 코드를 수정합니다.

그리고 키보드 화살표 키로 timeScale을 조절할 수 있는 코드를 작성합니다.

코드를 모두 수정한 다음에는 에디터로 돌아갑니다.

에디터로 돌아온 다음 게임을 플레이해보면 게임이 시작된 이후로 흐른 시간이 Time.time과 Time.realtimeSinceStartup 프로퍼티를 통해서 출력됩니다.

이 때 키보드의 화살표 키를 눌러서 time scale을 조절해보면 Time.time은 time scale 값에 따라 영향을 받지만 realtimeSinceStartup은 전혀 영향을 받지 않는 모습을 볼 수 있습니다.

거기에 추가로 게임을 잠시 일시정지시켰다가 플레이시켜보면 realtimeSinceStartup은 일시정지한 시간이 포함되어 값이 바뀐 것을 확인할 수 있습니다.

이렇게 게임이 시작된 시간 값을 출력하는 기능은 쓸데가 별로 없어보이지만, 게임을 실행한 시간을 기록해서 플레이어에게 업적을 준다던지, 너무 많은 시간동안 게임을 플레이하고 있는 유저가 있다면 경고문을 출력해주는 기능에 사용할 수 있습니다.

timeSinceLevelLoad

그리고 마지막으로 알아볼 프로퍼티는 timeSinceLevelLoad입니다.

이 프로퍼티는 마지막으로 씬이 로드된 이후로 흐른 시간을 의미합니다.

스크립트로 돌아가서 timeText에 timeSinceLevelLoad를 출력하는 코드를 추가합니다.

그리고 스크립트 상단에 UnityEngine.SceneManagement 네임스페이스를 using 선언하고 Update 함수에서 스페이스 키를 누르면 현재 씬을 다시 로드하도록 코드를 작성합니다.

코드를 모두 작성한 다음에는 코드를 저장하고 에디터로 돌아갑니다.

에디터에서는 빌드 세팅 창을 열어서 현재 씬을 Scenes In Build 목록에 추가해줍니다.

그 다음에 게임을 플레이해보면 time과 realtimeSinceStartup, 그리고 timeSinceLevelLoad 값이 동시에 상승하는 것을 확인할 수 있습니다.

이 때 스페이스 키를 누르면 현재 씬이 다시 로드되는데 time과 realtimeSinceStartup은 누적된 상태로 계속 증가하지만 timeSinceLevelLoad 값은 초기화되어서 0부터 다시 누적되는 모습을 볼 수 있습니다.

이 프로퍼티를 이용하면 던전 씬에 진입하고 난 이후에 플레이어가 던전을 클리어하는데 걸린 시간을 측정할 수 있습니다.

아웃트로

이번 영상에서는 Time 클래스의 여러 가지 프로퍼티에 대해서 알아보았습니다.

이 강좌는 구독자 여러분들의 시청과 후원으로 제작되었습니다.

이상 베르의 게임 개발 유튜브였습니다. 감사합니다.

 

[유니티 어필리에이트 프로그램]

아래의 링크를 통해 에셋을 구매하시거나 유니티를 구독하시면 수익의 일부가 베르에게 수수료로 지급되어 채널의 운영에 도움이 됩니다.

 

에셋스토어

여러분의 작업에 필요한 베스트 에셋을 찾아보세요. 유니티 에셋스토어가 2D, 3D 모델, SDK, 템플릿, 툴 등 여러분의 콘텐츠 제작에 날개를 달아줄 다양한 에셋을 제공합니다.

assetstore.unity.com

 

Easy 2D, 3D, VR, & AR software for cross-platform development of games and mobile apps. - Unity Store

Have a 2D, 3D, VR, or AR project that needs cross-platform functionality? We can help. Take a look at the easy-to-use Unity Plus real-time dev platform!

store.unity.com

 

Create 2D & 3D Experiences With Unity's Game Engine | Unity Pro - Unity Store

Unity Pro software is a real-time 3D platform for teams who want to design cross-platform, 2D, 3D, VR, AR & mobile experiences with a full suite of advanced tools.

store.unity.com

[투네이션]

 

-

 

toon.at

[Patreon]

 

WER's GAME DEVELOP CHANNEL님이 Game making class videos 창작 중 | Patreon

WER's GAME DEVELOP CHANNEL의 후원자가 되어보세요. 아티스트와 크리에이터를 위한 세계 최대의 멤버십 플랫폼에서 멤버십 전용 콘텐츠와 체험을 즐길 수 있습니다.

www.patreon.com

[디스코드 채널]

 

Join the 베르의 게임 개발 채널 Discord Server!

Check out the 베르의 게임 개발 채널 community on Discord - hang out with 399 other members and enjoy free voice and text chat.

discord.com

 

반응형

'Unity3D > Programming' 카테고리의 다른 글

[Unity] JSON  (0) 2022.04.05
[Unity] Time.time & Time.realtimeSinceStartup & Time.timeSinceLevelLoad  (0) 2021.12.07
[Unity] timeScale과 unscaledDeltaTime  (0) 2021.11.29
[Unity] Time.deltaTime  (1) 2021.11.22
[Unity] 인보크(Invoke)  (0) 2021.07.12

개발단에 가입하여 베르의 게임 개발 유튜브를 후원해주세요!

 

베르의 게임 개발 유튜브

안녕하세요! 여러분들과 함께 게임 개발을 공부하는 베르입니다! 게임 개발에 도움이 되는 강좌들을 올리는 채널입니다! [투네이션 후원] https://toon.at/donate/637735212761460238 [유니티 어필리에이트

www.youtube.com

 

안녕하세요! 여러분들과 함께 게임 개발을 공부하는 베르입니다!

이번에는 Time 클래스의 프로퍼티 중에서 time, realtimeSinceStartup, timeSinceLevelLoad에 대해서 알아보겠습니다.

 

사용 엔진 버전 : 2020.3

 

타임라인

0:00 인트로

0:14 Time.time

1:21 Time.realtimeSinceStartup

2:47 Time.timeSinceLevelLoad

3:57 아웃트로

스크립트

인트로

안녕하세요. 여러분들과 함께 게임 개발을 공부하는 베르입니다.

이번에는 Time 클래스의 프로퍼티 중에서 time과 realtimeSinceStartup, 그리고 timeSinceLevelLoad에 대해서 알아보도록 하겠습니다.

Time.time

Time 클래스의 프로퍼티인 time은 게임이 시작된 이후로부터 흐른 시간을 보여주는 프로퍼티입니다.

유니티 에디터에서 새 C# 클래스를 생성하고 스크립트 에디터를 열어줍니다.

비주얼 스튜디오가 열리고 나면 클래스의 상단에 UnityEngine.UI 네임스페이스를 using 선언해줍니다.

그리고 Text 타입으로 측정한 시간을 보여줄 timeText 변수를 선언해줍니다.

그 다음 Update 함수에서는 Time.time 값을 문자열로 만들어서 timeText로 출력하는 코드를 작성합니다.

코드를 모두 작성한 다음에는 코드를 저장하고 에디터로 돌아갑니다.

에디터에서는 Hierarchy 뷰에 우클릭해서 [UI > Text] 항목을 선택해서 텍스트 UI를 생성합니다.

그리고 Canvas 게임오브젝트에 방금 만든 컴포넌트를 붙인 뒤 Time Text 프로퍼티에 방금 만든 텍스트 UI를 할당해줍니다.

그 다음 게임을 플레이해보면 게임이 시작된 이후에 흐른 시간이 계속해서 올라가는 모습을 볼 수 있습니다.

Time.realtimeSinceStartup

그 다음에 설명할 프로퍼티는 realtimeSinceStartup입니다.

이 realtimeSinceStartup 역시 time과 같이 게임이 시작된 이후로부터 흐른 시간을 보여주는 프로퍼티입니다.

그럼 이 realtimeSinceStartup 프로퍼티가 time 프로퍼티와 어떤 차이가 있는지 알아보겠습니다.

다시 스크립트로 돌아가서 Time.time을 출력하는 timeText에 realtimeSinceStartup도 함께 출력하도록 코드를 수정합니다.

그리고 키보드 화살표 키로 timeScale을 조절할 수 있는 코드를 작성합니다.

코드를 모두 수정한 다음에는 에디터로 돌아갑니다.

에디터로 돌아온 다음 게임을 플레이해보면 게임이 시작된 이후로 흐른 시간이 Time.time과 Time.realtimeSinceStartup 프로퍼티를 통해서 출력됩니다.

이 때 키보드의 화살표 키를 눌러서 time scale을 조절해보면 Time.time은 time scale 값에 따라 영향을 받지만 realtimeSinceStartup은 전혀 영향을 받지 않는 모습을 볼 수 있습니다.

거기에 추가로 게임을 잠시 일시정지시켰다가 플레이시켜보면 realtimeSinceStartup은 일시정지한 시간이 포함되어 값이 바뀐 것을 확인할 수 있습니다.

이렇게 게임이 시작된 시간 값을 출력하는 기능은 쓸데가 별로 없어보이지만, 게임을 실행한 시간을 기록해서 플레이어에게 업적을 준다던지, 너무 많은 시간동안 게임을 플레이하고 있는 유저가 있다면 경고문을 출력해주는 기능에 사용할 수 있습니다.

Time.timeSinceLevelLoad

그리고 마지막으로 알아볼 프로퍼티는 timeSinceLevelLoad입니다.

이 프로퍼티는 마지막으로 씬이 로드된 이후로 흐른 시간을 의미합니다.

스크립트로 돌아가서 timeText에 timeSinceLevelLoad를 출력하는 코드를 추가합니다.

그리고 스크립트 상단에 UnityEngine.SceneManagement 네임스페이스를 using 선언하고 Update 함수에서 스페이스 키를 누르면 현재 씬을 다시 로드하도록 코드를 작성합니다.

코드를 모두 작성한 다음에는 코드를 저장하고 에디터로 돌아갑니다.

에디터에서는 빌드 세팅 창을 열어서 현재 씬을 Scenes In Build 목록에 추가해줍니다.

그 다음에 게임을 플레이해보면 time과 realtimeSinceStartup, 그리고 timeSinceLevelLoad 값이 동시에 상승하는 것을 확인할 수 있습니다.

이 때 스페이스 키를 누르면 현재 씬이 다시 로드되는데 time과 realtimeSinceStartup은 누적된 상태로 계속 증가하지만 timeSinceLevelLoad 값은 초기화되어서 0부터 다시 누적되는 모습을 볼 수 있습니다.

이 프로퍼티를 이용하면 던전 씬에 진입하고 난 이후에 플레이어가 던전을 클리어하는데 걸린 시간을 측정할 수 있습니다.

아웃트로

이번 영상에서는 Time 클래스의 프로퍼티 중에서 time과 realtimeSinceStartup, 그리고 timeSinceLevelLoad에 대해서 알아보았습니다.

이 강좌는 구독자 여러분들의 시청과 후원으로 제작되었습니다.

이상 베르의 게임 개발 유튜브였습니다. 감사합니다.

 

[유니티 어필리에이트 프로그램]

아래의 링크를 통해 에셋을 구매하시거나 유니티를 구독하시면 수익의 일부가 베르에게 수수료로 지급되어 채널의 운영에 도움이 됩니다.

 

에셋스토어

여러분의 작업에 필요한 베스트 에셋을 찾아보세요. 유니티 에셋스토어가 2D, 3D 모델, SDK, 템플릿, 툴 등 여러분의 콘텐츠 제작에 날개를 달아줄 다양한 에셋을 제공합니다.

assetstore.unity.com

 

Easy 2D, 3D, VR, & AR software for cross-platform development of games and mobile apps. - Unity Store

Have a 2D, 3D, VR, or AR project that needs cross-platform functionality? We can help. Take a look at the easy-to-use Unity Plus real-time dev platform!

store.unity.com

 

Create 2D & 3D Experiences With Unity's Game Engine | Unity Pro - Unity Store

Unity Pro software is a real-time 3D platform for teams who want to design cross-platform, 2D, 3D, VR, AR & mobile experiences with a full suite of advanced tools.

store.unity.com

[투네이션]

 

-

 

toon.at

[Patreon]

 

WER's GAME DEVELOP CHANNEL님이 Game making class videos 창작 중 | Patreon

WER's GAME DEVELOP CHANNEL의 후원자가 되어보세요. 아티스트와 크리에이터를 위한 세계 최대의 멤버십 플랫폼에서 멤버십 전용 콘텐츠와 체험을 즐길 수 있습니다.

www.patreon.com

[디스코드 채널]

 

Join the 베르의 게임 개발 채널 Discord Server!

Check out the 베르의 게임 개발 채널 community on Discord - hang out with 399 other members and enjoy free voice and text chat.

discord.com

 

반응형

'Unity3D > Programming' 카테고리의 다른 글

[Unity] JSON  (0) 2022.04.05
[Unity] Time 클래스 통합본  (0) 2021.12.27
[Unity] timeScale과 unscaledDeltaTime  (0) 2021.11.29
[Unity] Time.deltaTime  (1) 2021.11.22
[Unity] 인보크(Invoke)  (0) 2021.07.12

 

개발단에 가입하여 베르의 게임 개발 유튜브를 후원해주세요!

 

베르의 게임 개발 유튜브

안녕하세요! 여러분들과 함께 게임 개발을 공부하는 베르입니다! 게임 개발에 도움이 되는 강좌들을 올리는 채널입니다! [투네이션 후원] https://toon.at/donate/637735212761460238 [유니티 어필리에이트

www.youtube.com

 

안녕하세요! 여러분들과 함께 게임 개발을 공부하는 베르입니다!

이번에는 Time 클래스의 프로퍼티 중에서 timeScale과 unscaledDeltaTime에 대해서 알아봅시다!

 

사용 엔진 버전 : 2020.3

 

타임라인

0:00 인트로

0:10 Time.timeScale

1:40 Time.unscaledDeltaTime

3:14 아웃트로

스크립트

인트로

안녕하세요. 여러분들과 함께 게임 개발을 공부하는 베르입니다.

이번에는 Time 클래스의 프로퍼티인 timeScale과 unscaledDeltaTime에 대해서 알아보겠습니다.

Time.timeScale

time scale라는 프로퍼티의 이름을 단순하게 번역해보면 시간의 크기라는 뜻입니다.

이 값을 조절하면 시간이 흐르는 속도를 조절하여 시간이 빠르게 흐르거나 느리게 흐르게 만들 수 있습니다.

C# 스트립트를 하나 생성하고 스크립트 에디터를 엽니다.

스크립트 에디터가 열리고 나면 float 타입으로 timer 변수를 만들어줍니다.

그리고 Update 함수에서 timer 변수에 deltaTime 값을 누적시키며 더하고 그 timer 변수를 이용해서 오브젝트가 Sin 그래프를 따라서 움직이게 만들어 줍니다.

그 아래에는 키보드 화살 키를 눌러서 timeScale를 늘리거나 줄이는 코드를 작성합니다.

그리고 숫자 1을 누르면 timeScale를 1로 만들도록 해줍니다.

코드를 모두 작성한 다음에는 코드를 저장하고 에디터로 이동합니다.

에디터로 이동한 다음에는 큐브 오브젝트를 생성하고 방금 만든 컴포넌트를 붙여줍니다.

이제 게임을 플레이시켜 보겠습니다.

게임이 시작되면 큐브가 왕복으로 움직이는 모습을 볼 수 있는데 이때 위쪽 화살표 키를 누르면 time scale이 커지면서 큐브의 움직임이 빨라집니다.

반대로 아래쪽 화살표 키를 누르면 time scale이 작아지면서 큐브의 움직임이 느려집니다.

그러다가 time scale이 0이 되면 움직임이 완전히 멈춥니다.

그리고 숫자 1 키를 누르면 time scale이 1이 되면서 원래의 속도로 움직입니다.

이런 식으로 time scale을 조절해서 슬로우 모션같은 연출을 할 수 있습니다.

Time.unscaledDeltaTime

그 다음 알아볼 프로퍼티는 unscaledDeltaTime입니다.

delta time에 대해서 설명했을 때 이야기한 것처럼 delta time은 게임에서 플레이어의 입력과 게임 처리, 화면 렌더링 등의 작업이 한 번 처리되고 그 결과물이 플레이어의 모니터에 그려지는 한 프레임이 진행되는 시간을 의미합니다.

이 delta time에 unscaled를 붙임으로써 크기가 바뀌지 않은 delta time을 의미하게 됩니다.

time scale의 영향을 받지 않는 delta time인 것이죠.

새 C# 스크립트를 생성하고 앞에서 만든 컴포넌트에서 오브젝트를 이동시키는 코드를 복사해서 Update 함수에 붙여넣어줍니다.

그리고 timer에 더해주는 값을 deltaTime에서 unscaledDeltaTime으로 바꿔줍니다.

코드를 모두 작성한 다음에는 저장하고 에디터로 돌아갑니다.

그리고 씬에 새로운 3D 오브젝트를 배치하고 거기에 새로 만든 컴포넌트를 붙여줍니다.

그 다음 게임을 플레이시키면 거의 비슷한 속도로 움직이는 두 오브젝트가 보일 겁니다.

이 때 화살표 키를 눌러서 time scale을 조절하면 delta time으로 움직이는 오브젝트의 속도는 time scale의 영향을 받아 느려지거나 빨라지지만, unscaled delta time으로 움직이는 오브젝트의 속도는 전혀 영향을 받지 않고 동일한 속도로 움직이는 것을 볼 수 있습니다.

이런 식으로 어떤 오브젝트의 움직임이 time scale의 영향을 받지 않기를 원할 때는 unscaled delta time을 사용해야 합니다.

time scale과 delta time, unscaled delta time을 적절하게 조합해서 사용하면 특수한 스킬로 적들은 멈춰있거나 느려졌는데 플레이어만 정상적인 속도로 움직이는 기능을 연출할 수 있습니다.

아웃트로

이번 영상에서는 Time 클래스의 time scale과 unscaled delta time 프로퍼티에 대해서 알아보았습니다.

이상 베르의 게임 개발 유튜브였습니다. 감사합니다.

 

[유니티 어필리에이트 프로그램]

아래의 링크를 통해 에셋을 구매하시거나 유니티를 구독하시면 수익의 일부가 베르에게 수수료로 지급되어 채널의 운영에 도움이 됩니다.

 

에셋스토어

여러분의 작업에 필요한 베스트 에셋을 찾아보세요. 유니티 에셋스토어가 2D, 3D 모델, SDK, 템플릿, 툴 등 여러분의 콘텐츠 제작에 날개를 달아줄 다양한 에셋을 제공합니다.

assetstore.unity.com

 

Easy 2D, 3D, VR, & AR software for cross-platform development of games and mobile apps. - Unity Store

Have a 2D, 3D, VR, or AR project that needs cross-platform functionality? We can help. Take a look at the easy-to-use Unity Plus real-time dev platform!

store.unity.com

 

Create 2D & 3D Experiences With Unity's Game Engine | Unity Pro - Unity Store

Unity Pro software is a real-time 3D platform for teams who want to design cross-platform, 2D, 3D, VR, AR & mobile experiences with a full suite of advanced tools.

store.unity.com

[투네이션]

 

-

 

toon.at

[Patreon]

 

WER's GAME DEVELOP CHANNEL님이 Game making class videos 창작 중 | Patreon

WER's GAME DEVELOP CHANNEL의 후원자가 되어보세요. 아티스트와 크리에이터를 위한 세계 최대의 멤버십 플랫폼에서 멤버십 전용 콘텐츠와 체험을 즐길 수 있습니다.

www.patreon.com

[디스코드 채널]

 

Join the 베르의 게임 개발 채널 Discord Server!

Check out the 베르의 게임 개발 채널 community on Discord - hang out with 399 other members and enjoy free voice and text chat.

discord.com

 

반응형

안녕하세요! 여러분들과 함께 게임 개발을 공부하는 베르입니다!

이번에는 유니티 Time 클래스의 deltaTime 프로퍼티에 대해서 알아봅시다.

 

사용 엔진 버전 : 2020.3

 

타임라인

0:00 인트로

0:09 Time.deltaTime

2:58 아웃트로

 

스크립트

인트로

안녕하세요. 여러분들과 함께 게임 개발을 공부하는 베르입니다.

이번 강좌에서는 Time 클래스의 delta Time 프로퍼티에 대해서 알아봅시다.

deltaTime

먼저 deltaTime에서 delta는 보통 값의 차이를 의미하는 단어입니다.

시간을 의미하는 Time과 조합해서 생각해보면 deltaTime은 차이가 나는 시간이라는 뜻으로 지난 프레임이 완료되는 데까지 걸린 시간 차이를 의미하며 단위는 초 단위입니다.

한마디로 한 프레임을 진행하는데 걸린 시간이라는 뜻이죠.

그래서 게임을 진행하다가 컴퓨터 사양이나 게임의 최적화 문제로 게임의 프레임이 떨어지는 프레임 드랍 현상이 일어나면 이 deltaTime 값은 한 프레임의 화면을 렌더링하는데 걸리는 시간만큼 커지게 됩니다.

보통 30프레임 기준의 게임에서는 한 프레임당 deltaTime이 0.033정도가 나와야하고 60프레임 기준의 게임에서는 한 프레임당 0.016 정도가 나와야 합니다.

유니티 에디터에서 스크립트를 하나 생성하고 Start 함수에서 Application.targetFrameRate를 30으로 지정한 다음 Update 함수에서 Time.deltaTime을 디버그로 출력시키도록 코드를 작성합니다.

코드를 모두 작성한 다음에는 코드를 저장하고 에디터로 돌아가서 아무 게임 오브젝트에나 방금 만든 컴포넌트를 붙이고 게임을 실행해보면 앞에서 말한대로 약 0.033초에 가까운 값이 매 프레임마다 갱신되는 것을 볼 수 있습니다.

그리고 다시 스크립트에서 targetFrameRate를 60으로 변경하고 에디터로 돌아가서 테스트해보면 0.016초에 가깝게 deltaTime 값이 나오는 것을 확인할 수 있습니다.

그럼 이 delta time은 어디에 사용될까요?

그 예시를 보여드리도록 하겠습니다.

먼저 Update 함수에서 W키를 누르면 오브젝트를 이동시키는 코드를 작성해보겠습니다.

이 때 이동 코드에서 캐릭터의 이동 방향과 속도만 이용해서 캐릭터를 이동시키면 문제가 발생하게됩니다.

이 비교 영상처럼 프레임이 10일 때와 60일 때 캐릭터가 다른 속도로 움직이게 되는 겁니다.

이 문제의 원인은 프레임이 10일 때는 1초에 캐릭터를 10번 움직이게 되고, 프레임이 60일 때는 1초에 캐릭터를 60번 움직이기 때문입니다.

좀 더 풀어서 설명해보자면 이 코드에서는 프레임이 10일 때는 1의 속도로 캐릭터를 1초동안 10번 움직이기 때문에 이동한 거리가 10이 되는 것이고, 프레임이 60일 때는 1의 속도로 캐릭터를 1초동안 60번 움직이기 때문에 이동한 거리가 60이 됩니다.

1초 동안 움직인 횟수가 달라서 움직인 거리 역시 달라지는 것이죠.

이것은 컴퓨터의 성능이 오브젝트의 속도에 영향을 미치게 되는 것으로 보통의 게임에서는 발생해서는 안되는 문제입니다.

이 문제를 해결하기 위한 방법이 바로 이 이동 값에 delta time을 곱해주는 겁니다.

이렇게 이동 벡터에 delta time을 곱해주고 나면, 게임이 몇 프레임으로 진행되는지에 전혀 상관없이 오브젝트는 동일한 속도로 움직이게 됩니다.

이런 식으로 이동이나 회전 등 움직임에 있어서 시간의 영향을 받는 기능을 만들 때는 값에 deltaTime을 곱해서 흘러간 프레임 시간만큼만 가중치를 줌으로써 프로세서 속도의 영향에서 자유로워 지게됩니다.

아웃트로

이번 영상에서는 유니티 Time 클래스의 deltaTime에 대해서 알아보았습니다.

이상 베르의 게임 개발 유튜브였습니다. 감사합니다.

 

[유니티 어필리에이트 프로그램]

아래의 링크를 통해 에셋을 구매하시거나 유니티를 구독하시면 수익의 일부가 베르에게 수수료로 지급되어 채널의 운영에 도움이 됩니다.

 

에셋스토어

여러분의 작업에 필요한 베스트 에셋을 찾아보세요. 유니티 에셋스토어가 2D, 3D 모델, SDK, 템플릿, 툴 등 여러분의 콘텐츠 제작에 날개를 달아줄 다양한 에셋을 제공합니다.

assetstore.unity.com

 

Easy 2D, 3D, VR, & AR software for cross-platform development of games and mobile apps. - Unity Store

Have a 2D, 3D, VR, or AR project that needs cross-platform functionality? We can help. Take a look at the easy-to-use Unity Plus real-time dev platform!

store.unity.com

 

Create 2D & 3D Experiences With Unity's Game Engine | Unity Pro - Unity Store

Unity Pro software is a real-time 3D platform for teams who want to design cross-platform, 2D, 3D, VR, AR & mobile experiences with a full suite of advanced tools.

store.unity.com

[투네이션]

 

-

 

toon.at

[Patreon]

 

WER's GAME DEVELOP CHANNEL님이 Game making class videos 창작 중 | Patreon

WER's GAME DEVELOP CHANNEL의 후원자가 되어보세요. 아티스트와 크리에이터를 위한 세계 최대의 멤버십 플랫폼에서 멤버십 전용 콘텐츠와 체험을 즐길 수 있습니다.

www.patreon.com

[디스코드 채널]

 

Join the 베르의 게임 개발 채널 Discord Server!

Check out the 베르의 게임 개발 채널 community on Discord - hang out with 399 other members and enjoy free voice and text chat.

discord.com

 

반응형

사용 버전 : 2019.4

스크립트

인트로

안녕하세요. 여러분들과 함께 게임 개발을 공부하는 베르입니다.

이번 영상에서는 유니티의 인보크에 대해서 알아보도록 하겠습니다.

기본 인보크

우선 인보크란 유니티 엔진에서 모든 유니티 스크립트의 기본 클래스인 MonoBehaviour 클래스에서 제공되는 함수로써 기본적으로 원하는 함수를 일정 시간 후에 호출하거나 일정 시간마다 반복해서 호출할 수 있게 해주는 기능을 제공합니다.

우선 인보크 기능을 테스트해보기 위해서 프로젝트 뷰에서 InvokeTester라는 이름으로 C# 스크립트를 생성하고 스크립트 에디터를 엽니다.

스크립트 에디터가 열리고 나면 CreateCube 함수를 만들고 큐브를 랜덤한 위치에 생성하도록 코드를 작성합니다.

그리고 Start 함수로 가서 Invoke 함수를 호출해줍니다.

이 때 Invoke로 호출될 함수의 이름을 문자열로 넣고 얼마나 시간이 흐른 뒤에 호출될 지를 매개변수로 넣어주면 됩니다.

지금은 3초로 설정하겠습니다.

코드를 저장하고 에디터로 돌아갑니다.

에디터로 돌아온 다음에는 씬에 빈 게임오브젝트를 하나 생성하고 거기에 InvokeTester 컴포넌트를 붙여줍니다.

그 다음 게임을 플레이시켜보면 3초 뒤에 큐브가 스폰되는 모습을 볼 수 있습니다.

이것이 가장 기초적인 인보크 사용 방법입니다.

반복 호출되는 인보크

그 다음 알아볼 것은 반복 호출되는 인보크입니다.

다시 스크립트 에디터로 돌아갑니다.

방금 배운 것처럼 매개변수에 호출할 함수의 이름과 시간만 넣으면 함수가 일정 시간 후에 한 번 호출됩니다.

여기에 Invoke 함수 대신에 InvokeRepeating 함수로 바꾸고 세 번째 매개변수에 1을 넣어줍니다.

이렇게 하면 InvokeRepeating이 호출되고 3초 후에 CreateCube 함수가 호출되며 그 뒤로 1초마다 계속해서 반복 호출됩니다.

코드를 저장하고 에디터로 돌아가서 게임을 실행해보겠습니다.

그러면 3초가 지난 후에 1초마다 계속 새로운 큐브가 생성되는 모습을 볼 수 있습니다.

인보크 멈추기

그 다음에는 동작 중인 인보크를 멈추는 방법을 알아보겠습니다.

다시 스크립트도 돌아갑니다.

인보크를 멈추기 위해서는 CancelInvoke 함수를 사용하면 됩니다.

이 때 매개변수에 아무것도 넣지 않으면 이 게임오브젝트에서 동작하고 있는 모든 인보크들을 멈추게하고 매개변수에 함수 이름을 넣으면 그 함수 이름으로 실행된 인보크들만 멈추게 할 수 있습니다.

그럼 인보크가 멈추는 것을 확인해보기 위해서 코드를 작성하겠습니다.

먼저 CreateCube 함수를 복사해서 큐브 대신 구체를 만들어내는 CreateSphere 함수를 만들어줍니다.

그리고 업데이트 함수에서 키보드 숫자 1을 누르면 CreateCube 함수가 InvokeRepeating 되게 만들어 주고 2를 누르면 CreateSphere 함수가 InvokeRepeating 되게 만들어줍니다.

그리고 숫자 3을 누르면 CreateCube 함수가 CancelInvoke 되고 4를 누르면 CreateSphere 함수가 CancelInvoke 되게 해줍니다.

마지막으로 ESC를 누르면 동작 중인 모든 인보크가 멈추게 만듭니다.

코드를 저장하고 에디터로 돌아가서 게임을 실행합니다.

그리고 1과 2를 누르면 큐브와 구체가 계속해서 생성되는 모습을 볼 수 있습니다.

이 상태에서 3을 누르면 큐브의 생성이 멈추고 4를 누르면 구체의 생성이 멈춥니다.

다시 1과 2를 눌러 큐브와 구체를 생성되게 만든 다음 ESC 키를 누르면 큐브와 구체의 생성이 동시에 멈추는 것을 볼 수 있습니다.

인보크 상태 확인하기

이번에는 인보크가 동작 중인지 확인하는 방법을 알아보겠습니다.

인보크가 동작 중인지 확인하기 위해서는 IsInvoking 함수를 사용하면 됩니다.

이 함수 역시 CancelInvoke 함수와 마찬가지로 매개변수로 함수 이름을 넣으면 그 함수에 대한 인보크가 동작 중인지 확인할 수 있고 매개변수를 사용하지 않으면 아무 인보크나 동작하고 있는지를 체크할 수 있습니다.

이번에는 숫자 5를 누르면 CreateCube 함수에 대한 인보크를 체크하고 6을 누르면 CreateSphere 함수에 대한 인보크를 체크해서 로그를 출력하도록 코드를 작성합니다.

그리고 숫자 7을 누르면 매개변수 없이 인보크를 체크하도록 만듭니다.

코드를 모두 작성한 다음에는 저장하고 에디터로 돌아가서 게임을 실행합니다.

그리고 인보크를 실행하기 전에 5, 6, 7을 순서대로 눌러보면 어떠한 인보크도 동작하고 있지 않음을 로그로 확인할 수 있습니다.

그 다음에 1을 눌러 CreateCube 함수를 인보크로 동작시키고 5, 6, 7을 누르면 CreateCube 인보크 확인 로그와 모든 인보크 확인 로그를 통해서 인보크가 동작하고 있음을 확인할 수 있습니다.

그리고 2를 누르고 CreateSphere 함수까지 인보크로 동작시키고 5, 6, 7을 누르면 모든 인보크가 동작하고 있음을 로그로 확인할 수 있습니다.

이번에는 3을 눌러서 CreateCube 함수의 인보크를 중지시키고 5, 6, 7을 누르면 CreateCube 인보크가 동작하지 않는다는 로그를 볼 수 있습니다.

마지막으로 4를 눌러서 CreateSphere 함수의 인보크를 중지시키고 5, 6, 7을 누르면 모든 인보크가 동작하지 않는것을 로그로 확인할 수 있습니다.

멈추지 않는 인보크

추가로 유니티 엔진에서 게임오브젝트의 Update 함수과 코루틴 같은 기능은 게임오브젝트나 컴포넌트가 비활성화되면 동작을 멈추는 것을 알고 있으실 겁니다.

하지만 인보크 기능은 해당 게임오브젝트나 컴포넌트가 비활성화되어도 동작을 멈추지 않습니다.

인보크를 멈추기 위해서는 반드시 CancelInvoke 함수를 호출하거나 게임오브젝트 자체를 파괴해야 합니다.

하지만 코루틴

이렇게 인보크를 사용하면 원하는 함수를 일정 시간이 지난 후에 호출하거나 원하는 시간 간격으로 호출할 수 있는데 이 기능은 코루틴을 사용해서도 똑같이 구현할 수 있습니다.

그리고 유니티 공식 문서를 보면 성능 향상과 유지보수를 위해서는 코루틴을 사용할 것을 권장하고 있습니다.

우선 성능적인 측면을 보자면 인보크는 함수를 문자열로 된 이름으로 찾아서 사용하고 있습니다.

이렇게 문자열 함수 이름으로 함수를 찾아서 사용하기 위해서는 C#의 리플렉션이라는 기능을 사용하게 되는데 이렇게 문자열 함수 이름으로 리플렉션을 통해서 함수를 동작시키는 과정은 직접 함수를 호출하는 것에 비해서 수 천 배 정도 느리다고 합니다.

물론 컴퓨터의 사양이 많이 상승한 최근에는 유의미한 성능 저하는 당장 일어나지 않겠지만 인보크를 남용하면서 게임을 만들다보면 게임의 사양이 많이 올라갔을 때 최적화를 위해서 인보크를 사용하는 코드를 대부분 갈아엎어야 할 수도 있습니다.

아웃트로

이번 영상에서는 유니티 엔진에서 원하는 함수를 일정 시간이 지난 후에 호출하거나 원하는 시간 간격으로 호출할 수 있게 만들어주는 인보크에 대해서 알아보았습니다.

이상 베르의 게임 개발 유튜브였습니다. 감사합니다.

타임라인

0:00 인트로

0:09 기본 인보크

1:12 반복 호출되는 인보크

1:55 인보크 멈추기

3:22 인보크 상태 확인 하기

4:51 멈추지 않는 인보크

5:14 하지만 코루틴

6:06 아웃트로

 

[유니티 어필리에이트 프로그램]

아래의 링크를 통해 에셋을 구매하시거나 유니티를 구독하시면 수익의 일부가 베르에게 수수료로 지급되어 채널의 운영에 도움이 됩니다.

 

에셋스토어

여러분의 작업에 필요한 베스트 에셋을 찾아보세요. 유니티 에셋스토어가 2D, 3D 모델, SDK, 템플릿, 툴 등 여러분의 콘텐츠 제작에 날개를 달아줄 다양한 에셋을 제공합니다.

assetstore.unity.com

 

Easy 2D, 3D, VR, & AR software for cross-platform development of games and mobile apps. - Unity Store

Have a 2D, 3D, VR, or AR project that needs cross-platform functionality? We can help. Take a look at the easy-to-use Unity Plus real-time dev platform!

store.unity.com

 

Create 2D & 3D Experiences With Unity's Game Engine | Unity Pro - Unity Store

Unity Pro software is a real-time 3D platform for teams who want to design cross-platform, 2D, 3D, VR, AR & mobile experiences with a full suite of advanced tools.

store.unity.com

[투네이션]

 

-

 

toon.at

[Patreon]

 

WER's GAME DEVELOP CHANNEL님이 Game making class videos 창작 중 | Patreon

WER's GAME DEVELOP CHANNEL의 후원자가 되어보세요. 아티스트와 크리에이터를 위한 세계 최대의 멤버십 플랫폼에서 멤버십 전용 콘텐츠와 체험을 즐길 수 있습니다.

www.patreon.com

[디스코드 채널]

 

Join the 베르의 게임 개발 채널 Discord Server!

Check out the 베르의 게임 개발 채널 community on Discord - hang out with 399 other members and enjoy free voice and text chat.

discord.com

 

반응형

유니티 2020 버전 이전에서 제네릭 인수를 사용하는 유니티 이벤트의 복잡한 직렬화 방식이 유니티 2020버전에서 변경되었습니다. 이부분에 대해서 알아봅시다.

 

타임라인

0:00 2020 이전 버전의 유니티 이벤트 Generic Serialization

1:11 유니티 2020에서 바뀐 유니티 이벤트 Generic Serialization

 

[유니티 어필리에이트 프로그램]

아래의 링크를 통해 에셋을 구매하시거나 유니티를 구독하시면 수익의 일부가 베르에게 수수료로 지급되어 채널의 운영에 도움이 됩니다.

 

에셋스토어

여러분의 작업에 필요한 베스트 에셋을 찾아보세요. 유니티 에셋스토어가 2D, 3D 모델, SDK, 템플릿, 툴 등 여러분의 콘텐츠 제작에 날개를 달아줄 다양한 에셋을 제공합니다.

assetstore.unity.com

 

Easy 2D, 3D, VR, & AR software for cross-platform development of games and mobile apps. - Unity Store

Have a 2D, 3D, VR, or AR project that needs cross-platform functionality? We can help. Take a look at the easy-to-use Unity Plus real-time dev platform!

store.unity.com

 

Create 2D & 3D Experiences With Unity's Game Engine | Unity Pro - Unity Store

Unity Pro software is a real-time 3D platform for teams who want to design cross-platform, 2D, 3D, VR, AR & mobile experiences with a full suite of advanced tools.

store.unity.com

[투네이션]

 

-

 

toon.at

[Patreon]

 

WER's GAME DEVELOP CHANNEL님이 Game making class videos 창작 중 | Patreon

WER's GAME DEVELOP CHANNEL의 후원자가 되어보세요. 아티스트와 크리에이터를 위한 세계 최대의 멤버십 플랫폼에서 멤버십 전용 콘텐츠와 체험을 즐길 수 있습니다.

www.patreon.com

[디스코드 채널]

 

Join the 베르의 게임 개발 채널 Discord Server!

Check out the 베르의 게임 개발 채널 community on Discord - hang out with 399 other members and enjoy free voice and text chat.

discord.com

 

반응형

유니티 이벤트와 유니티 액션을 사용을 사용하는 방법을 알아봅시다.

 

타임라인

0:00 유니티 이벤트와 유니티 액션 개요

1:15 유니티 이벤트의 예시(버튼 UI 컴포넌트)

1:49 유니티 이벤트를 사용해서 스크립트에서 원하는 이벤트 구현하기

2:48 유니티 이벤트에 콜백 함수를 등록할 클래스 만들기

3:32 이벤트 기능 테스트

3:48 스크립트에서 콜백 함수 등록하기

4:51 유니티 이벤트에 매개변수 지정하기

5:24 유니티 이벤트의 매개변수 지정하기의 단점과 해결방법

5:50 유니티 액션

 

[유니티 어필리에이트 프로그램]

아래의 링크를 통해 에셋을 구매하시거나 유니티를 구독하시면 수익의 일부가 베르에게 수수료로 지급되어 채널의 운영에 도움이 됩니다.

 

에셋스토어

여러분의 작업에 필요한 베스트 에셋을 찾아보세요. 유니티 에셋스토어가 2D, 3D 모델, SDK, 템플릿, 툴 등 여러분의 콘텐츠 제작에 날개를 달아줄 다양한 에셋을 제공합니다.

assetstore.unity.com

 

Easy 2D, 3D, VR, & AR software for cross-platform development of games and mobile apps. - Unity Store

Have a 2D, 3D, VR, or AR project that needs cross-platform functionality? We can help. Take a look at the easy-to-use Unity Plus real-time dev platform!

store.unity.com

 

Create 2D & 3D Experiences With Unity's Game Engine | Unity Pro - Unity Store

Unity Pro software is a real-time 3D platform for teams who want to design cross-platform, 2D, 3D, VR, AR & mobile experiences with a full suite of advanced tools.

store.unity.com

[투네이션]

 

-

 

toon.at

[Patreon]

 

WER's GAME DEVELOP CHANNEL님이 Game making class videos 창작 중 | Patreon

WER's GAME DEVELOP CHANNEL의 후원자가 되어보세요. 아티스트와 크리에이터를 위한 세계 최대의 멤버십 플랫폼에서 멤버십 전용 콘텐츠와 체험을 즐길 수 있습니다.

www.patreon.com

[디스코드 채널]

 

Join the 베르의 게임 개발 채널 Discord Server!

Check out the 베르의 게임 개발 채널 community on Discord - hang out with 399 other members and enjoy free voice and text chat.

discord.com

 

반응형

+ Recent posts