0:00:00.000,0:00:01.650 안녕하세요, 제 이름은 Mark입니다. 0:00:01.650,0:00:07.540 저는 수년동안 Unity같은 소프트웨어를 이용해서[br]저만의 게임을 만들고 싶었습니다. 0:00:07.540,0:00:10.800 Unity는 수많은 타이틀을 만든 강력한 게임 엔진입니다. 0:00:10.800,0:00:13.850 "컵헤드" ,"네온 화이트", "튜닉", 0:00:13.850,0:00:16.835 "아우터 와일즈", "하스스톤", "파이어워치", 0:00:16.835,0:00:18.830 심지어 포켓몬 다이다몬드 리메이크에도 사용되었습니다. 0:00:18.830,0:00:23.753 그런데 저는 길고 여러 챕터가 있는 튜토리얼 영상을 볼 때마다.. 0:00:24.810,0:00:25.890 ..항상 잠이 오더군요. 0:00:25.890,0:00:31.500 저는 다른 사람이 하는걸 보면서 따라하는 것보다[br]직접 시도해보는게 적성에 더 맞더라고요. 0:00:31.500,0:00:36.060 그래서 저는 작년에 실제로 효과가 있는 솔루션을 만들었습니다. 0:00:36.060,0:00:38.476 이 방법은 3가지 단계로 나뉩니다. 0:00:38.476,0:00:41.695 첫째, Unity의 정말 기초적인 것들만 배웁니다. 0:00:41.695,0:00:45.710 둘째, 간단한 연습으로 지금까지 배운 것들을 복습합니다. 0:00:45.710,0:00:49.355 셋째, 나머지 부분은 게임을 만들면서 당신이 원하는 대로 알아봅니다. 0:00:49.355,0:00:50.713 이 방법은 정말로 효과가 있었습니다! 0:00:50.713,0:00:54.632 약 1년 동안, 저는 이 방법으로[br]아이폰 게임을 똑같이 만드는 것부터 시작해서 0:00:54.632,0:00:58.867 현재는 자석을 소재로 한 저만의 퍼즐 플랫포머 게임을 개발하고 있습니다. 0:00:58.867,0:01:03.620 그리고 저는 10만 회 이상 플레이된[br]인터렉티브 비디오 에세이를 출시했습니다. 0:01:03.620,0:01:07.031 그런데 잠깐만요, 어떻게 Unity의 기초적인 것들만 배울 수 있나요? 0:01:07.031,0:01:11.786 소프트웨어가 너무 복잡할 때 가장 기본적인 것들을 어떻게 배울 수 있을까요? 0:01:11.786,0:01:15.763 제가 사용한 방법은,[br]게임을 만들때 무조건 알아야 할 것들의 목록을 적는 것입니다. 0:01:15.763,0:01:17.996 제가 어떤 게임을 만들던 간에 상관없이요. 0:01:17.996,0:01:21.589 예를 들어 어떻게 화면에서 캐릭터가 나타나게 하고 움직일 수 있게 할까요? 0:01:21.589,0:01:24.620 어떻게 물체를 생성시키고 나중에 삭제할 수 있을까요? 0:01:24.620,0:01:29.020 어떻게 충돌, 게임 오버, 애니메이션, 그리고 사운드 효과를 만들까요? 0:01:29.020,0:01:33.540 저는 이 방법들을 긴 튜토리얼을 찾아다니고,[br]Unity 공식 문서를 읽고, 0:01:33.540,0:01:37.420 복잡한 단어들을 검색하고, 수많은 시행착오를 겪으면서 배웠습니다. 0:01:37.420,0:01:41.820 이 영상의 목적은 여러분을 그 번거로움에서 구하는 것입니다. 0:01:41.820,0:01:46.380 이 영상은 제가 Unity를 배울 때 있었다면 좋았을 튜토리얼입니다. 0:01:46.380,0:01:51.227 앞으로 40분동안 우리는 Unity를 사용해서[br]플래피 버드를 만들겁니다. 0:01:51.227,0:01:56.707 우리가 플래피 버드를 만들고 싶어서가 아니라,[br]이 중독적인 아이폰 게임을 다시 만드려면, 0:01:56.707,0:02:02.220 제가 아까전에 말한 물체를 생성하는 것부터,[br]게임 오버를 만드는 방법까지 배울 수 있기 때문입니다. 0:02:02.220,0:02:05.323 이 튜토리얼은 Unity를 하는 데에 필요한 모든 단계를 다룹니다. 0:02:05.323,0:02:08.460 Unity를 설치하는 것부터, Unity의 UI를 이해하고, 0:02:08.460,0:02:14.525 당신의 첫번째 프로그래밍 코드를 작성하고,[br]친구들과 공유할 수 있도록 게임을 내보내기까지. 0:02:14.525,0:02:19.542 그리고 튜토리얼이 끝나면,[br]당신이 계속해서 나머지 부분을 배울 수 있도록 0:02:19.542,0:02:22.749 스스로 할 수 있는 몇가지 구체적인 단계들을 알려드리겠습니다. 0:02:22.749,0:02:26.020 괜찮은 것 같나요? 그렇다면 이제 시작하죠. 0:02:27.010,0:02:34.930 좋아요. 웹사이트에서 Unity를 받는 것부터 시작합시다.[br]Unity Hub를 다운로드하고 설치하세요. 0:02:34.930,0:02:39.020 Unity를 사용하려면 무료 계정이 필요합니다. 0:02:39.020,0:02:42.640 계정을 만든 후,[br]Unity 에디터를 설치할 수 있는 창이 나올 겁니다. 0:02:42.640,0:02:46.311 저는 이 튜토리얼에서 2021.3 버전을 사용하고 있습니다. 0:02:46.311,0:02:50.430 만약 당신이 먼 미래에 이 영상을 보고[br]왜 프로그램이 영상과 다른지 궁금할 수도 있으니까요. 0:02:50.430,0:02:53.833 제가 인터넷이 빠르다고 가정해봅시다. (효과음) 0:02:53.833,0:02:55.561 그러나 아직 끝난 것은 아닙니다. 0:02:55.561,0:03:00.740 설치 메뉴에서 Unity 에디터의 톱니바퀴 아이콘을 누르고[br]'모듈 추가'를 누르세요. 0:03:00.740,0:03:03.523 Microsoft Visual Studio가 선택되어 있는 게 보일 겁니다. 0:03:03.523,0:03:06.721 이것은 우리가 프로그래밍 코드를 작성할 때 사용할 소프트웨어입니다. 0:03:06.721,0:03:10.160 '설치'를 눌러서 Visual Studio를 설치하세요. 0:03:10.160,0:03:15.420 이 화면에서, 아래로 스크롤해서[br]'Unity를 사용한 게임 개발'을 선택하고, 'Unity Hub'는 해제하세요. 0:03:15.420,0:03:18.210 왜냐면 Hub는 이미 설치 되있으니까요. (효과음) 0:03:18.210,0:03:21.577 Visual Studio를 사용하기 위해[br]계정을 만들 필요는 없으므로 이건 생략하세요. 0:03:21.577,0:03:24.177 그리고 지금은 프로그램을 닫으세요. 나중에 실행할 겁니다. 0:03:24.177,0:03:26.110 좋아요. 모든 설치가 끝났습니다. 0:03:26.110,0:03:32.160 이제 Unity Hub에서 '새 프로젝트'를 누르고,[br]'모든 템플릿'을 선택하고 '2D 코어'를 선택합니다. 0:03:32.160,0:03:37.607 2D 코어는 2D 게임을 만드는데[br]적합하도록 설정된 빈 프로젝트입니다. 0:03:37.607,0:03:42.320 프로젝트 이름을 정하고, '프로젝트 생성'을 누르고[br]이제 제대로 시작해봅시다. 0:03:43.570,0:03:48.575 먼저, 우리는 Unity의 기본 UI에 익숙해질 필요가 있습니다. 0:03:48.575,0:03:53.120 다양한 패널들을 살펴보면서, 우리는 화면에 새가 나타나게 할 것입니다. 0:03:53.120,0:04:00.030 이게 Unity의 기본 레이아웃입니다.[br]그리고 이 레이아웃은 4개의 패널로 나뉩니다. 0:04:00.030,0:04:05.720 가장 먼저, 아래에는 '프로젝트 패널'이 있습니다.[br]여기에는 게임에 들어가는 모든 요소가 포함됩니다. 0:04:05.720,0:04:11.288 예를 들면 스프라이트, 사운드 효과, 스크립트, 타일, 폰트 등이 있습니다. 0:04:11.288,0:04:14.998 이중 일부는 Unity에서 직접 원하는 대로 만들 수도 있지만 0:04:14.998,0:04:18.585 그냥 컴퓨터에서 파일을 드래그해서 프로젝트에 넣을 수도 있습니다. 0:04:18.585,0:04:25.434 저는 포토샵에서 새와 파이프 역할을 할 스프라이트를 만들었고[br]이 방법으로 파일을 프로젝트에 넣었습니다. 0:04:25.434,0:04:27.850 저는 여러분이 스프라이트를 직접 만드는 것을 추천하지만[br](그것이 더 재미있지만) 0:04:27.850,0:04:33.052 만약 당신이 만들 수 있는 능력이 없다면[br]설명란의 에셋 다운로드 링크를 확인하세요. 0:04:33.052,0:04:35.620 다음 패널은 '계층 패널'입니다. 0:04:35.620,0:04:41.440 여기에는 현재 '장면'에 있는 것들을 보여주고,[br]'장면'은 대부분의 게임에서 레벨의 역할을 합니다. 0:04:41.440,0:04:43.635 우선 새를 만드는 것부터 시작합시다. 0:04:43.635,0:04:50.620 계층 패널을 우클릭한 후 'Create Empty'를 누르면[br]빈 게임 오브젝트가 생성됩니다. 근데, 그게 뭐죠? 0:04:50.620,0:04:53.894 게임 오브젝트는 본질적으로 투명한 컨테이너입니다. 0:04:53.894,0:04:58.300 이 컨테이너는 위치, 회전, 크기를 조절할 수 있습니다. 0:04:58.300,0:05:03.190 그리고 컨테이너 안에 컴포넌트를 넣어[br]추가적인 기능을 추가할 수 있습니다. 0:05:03.190,0:05:08.908 예를 들어, '스프라이트 렌더러' 컴포넌트를 넣으면[br]게임 오브젝트에 이미지를 넣을 수 있게 됩니다. 0:05:08.908,0:05:13.260 저희 게임의 모든 것들은[br]'컴포넌트가 들어있는 게임 오브젝트'로 구성될 겁니다. 0:05:13.260,0:05:17.140 새, 파이프, 심지어 UI와 카메라도요. 0:05:17.140,0:05:22.680 이 모든 마법은 세 번째 패널인 '인스펙터'에서 이루어지며,[br]인스펙터는 게임 오브젝트를 조작하는 데 사용됩니다. 0:05:22.680,0:05:28.040 빈 게임 오브젝트를 선택한 후,[br]위에서 이름을 변경할 수 있습니다. 0:05:28.040,0:05:35.560 이름은 Bird라고 합시다.[br]그리고 Transform에서 위치, 회전, 크기를 조절할 수 있습니다. 0:05:35.560,0:05:41.020 이제 'Add Component'를 누르고, Rendering을 누르고[br]Sprite Renderer를 선택하세요 0:05:41.020,0:05:43.950 이게 작동하려면, Sprite 칸을 채워야 하는데, 0:05:43.950,0:05:50.215 그냥 프로젝트 패널에서 새 이미지를[br]Sprite 칸에 드래그하면 짜잔, 그래픽이 생겼네요! 0:05:50.215,0:05:55.250 그래픽은 중앙에 있는 장면 패널에 나타납니다. 0:05:55.250,0:05:57.670 씬에서는 현재 씬에 무엇이 있는지 볼 수 있고, 0:05:57.670,0:06:01.790 원한다면 왼쪽의 도구들을 이용하여 오브젝트를 움직이거나[br]크기를 조정하는 등의 작업을 할 수 있습니다. 0:06:01.790,0:06:04.895 이 섹션에는 '게임' 패널이 추가로 있는데, 0:06:04.895,0:06:09.040 여기에서는 게임을 실행할때 메인 카메라에서[br]어떻게 보이는지 확인할 수 있습니다. 0:06:09.040,0:06:13.720 또한 이 드롭다운에서 해상도와 화면비를 설정할 수 있습니다. 0:06:13.720,0:06:19.690 다른 화면에서 어떻게 보이는지 알기 편하게요.[br]저는 1920x1080을 선택하겠습니다. 0:06:19.690,0:06:22.292 아이고, 새가 너무 많은 공간을 차지하네요. 0:06:22.292,0:06:25.654 새의 크기를 줄일 수도 있지만,[br]한번 카메라의 크기를 작게 해봅시다. 0:06:25.654,0:06:29.977 앞서 말했듯이 카메라도 계층 패널 속 게임 오브젝트입니다. 0:06:29.977,0:06:36.420 그리고 카메라에는 우리가 조작할 수 있는 카메라 컴포넌트가 있습니다.[br]'Size'를 변경해서 카메라를 축소할 수 있습니다. 0:06:36.420,0:06:39.420 그리고 한번 배경 색도 바꿔보겠습니다.[br]좋네요. 0:06:39.420,0:06:45.790 이제 위에 있는 플레이 버튼을 누르면 [br]세상에서 가장 지루한 게임을 시작할 수 있습니다. 0:06:45.790,0:06:48.490 음... 네. 이제 덜 지루하게 만들어 봅시다. 0:06:49.790,0:06:51.250 잠깐 되돌아봅시다. 0:06:51.250,0:06:53.918 Unity에는 기본적으로 4개의 패널이 있다. 0:06:53.918,0:06:56.200 프로젝트 패널은 모든 요소가 들어가고, 0:06:56.200,0:06:59.750 계층 패널에서는 현재 레벨의 모든 게임 오브젝트가 나열되고, 0:06:59.750,0:07:02.740 인스펙터 패널에서는 게임 오브젝트의 컴포넌트를 마음대로 변경할 수 있고, 0:07:02.740,0:07:05.307 장면 패널에서는 레벨을 볼 수 있다. 0:07:05.307,0:07:10.800 그리고 게임 오브젝트는 Sprite Renderer같은 [br]컴포넌트를 담을 수 있는 투명한 컨테이너다. 0:07:12.180,0:07:15.900 두번째로, 저희는 더 많은 컴포넌트를 이용하여 0:07:15.900,0:07:19.320 새를 중력에 영향을 받는 물리 오브젝트로 만들고 0:07:19.320,0:07:23.400 코드를 이용하여 스페이스 바를 누를 떄마다 [br]새를 위로 날게 만들겁니다 0:07:23.400,0:07:29.760 이제 새에다가 Rigidbody2D 컴포넌트를 추가합시다. 0:07:29.760,0:07:36.600 이 컴포넌트는 새를 물리 오브젝트로 만들어 줍니다.[br]그래서 Play 버튼을 누르면 새가 화면 밖으로 떨어집니다. 0:07:36.600,0:07:42.279 이 새가 다른 오브젝트와 상호작용하게 만들려면[br]Collider가 필요합니다 0:07:42.279,0:07:43.920 Circle Collider 2D를 추가합시다 0:07:43.920,0:07:49.920 씬을 보면 초록색으로 된 선이 보입니다[br]중심이 약간 안맞기 때문에; 0:07:49.920,0:07:55.260 오프셋을 조절해서 움직이겠습니다[br]여기서 게임 디자인 팁을 주자면 0:07:55.260,0:08:00.720 Collider(판정)를 이미지보다 조금 작게 만들면[br]플레이어가 파이프에 아주 살짝 닿았더라도 0:08:00.720,0:08:05.220 게임 오버가 되지 않기에[br]빡센 느낌이 줄어들게 됩니다 0:08:05.220,0:08:10.920 마지막으로, 스크립트를 추가하겠습니다[br]스크립트를 활용하면 사실상 나만의 컴포넌트를 0:08:10.920,0:08:16.680 만들 수 있게 되지만, 우리가 코드를 이용해서 직접 만들어야 합니다[br]컴포넌트 추가에서 New Script를 선택하고, 0:08:16.680,0:08:21.780 이름은 BirdScript라고 하겠습니다.[br]만든 후, 스크립트를 더블클릭하면 0:08:21.780,0:08:27.000 전에 설치한 Visual Studio가 열릴겁니다 0:08:27.000,0:08:31.020 프로그래밍의 세계에 온걸 환영합니다![br]너무 무섭게 생각하지 마세요; 0:08:31.020,0:08:35.460 천천히 설명해드릴 겁니다.[br]저희는 C#으로 코드를 작성할겁니다 0:08:35.460,0:08:41.340 먼저 Start와 Update, 이 2개에 대해[br]알아보겠습니다 0:08:41.340,0:08:46.620 Start는 (이 스크립트가 활성화 돼있으면) 처음으로 실행되는 코드이고, 0:08:46.620,0:08:52.620 단 한번만 실행됩니다.[br]Update는 (이 스크립트가 활성화 돼있으면) 항상 실행되는 코드이고, 0:08:52.620,0:08:57.360 매 프레임마다 코드가 실행됩니다. 0:08:58.080,0:09:02.820 아무튼, 저희가 코드로 작성할 건[br]- Unity로 다시 돌아가보면 0:09:02.820,0:09:08.340 컴포넌트에 있는 숫자들이나 텍스트를 마음대로 조절할 수 있죠 0:09:08.340,0:09:13.320 저희는 코드를 이용하여[br]게임이 실행되는 동안 이것들을 조절할 겁니다 0:09:13.320,0:09:17.880 간단한 예시를 들자면 0:09:17.880,0:09:24.920 Start에 gameObject(오른쪽 위에 있는걸 의미함)를 치고, [br]점[.]을 치면 리스트가 보일겁니다 0:09:24.920,0:09:25.920 *(리스트가 안보이면, Unity 위에 '창'->'패키지 관리자'->아래로 내려서 'Visual Studio Editor' 선택 후 설치[br]그후 Unity 위에 '편집'->'환경 설정'->'외부 툴'->Visual Studio 선택 후 전부 체크하고 재실행) 0:09:25.920,0:09:30.720 이중 대부분은 인스펙터에 있는걸 나타냅니다[br]예를 들면 정적(isStatic); 0:09:30.720,0:09:38.940 태그, 레이어, 이름이 있죠[br]name을 선택하고, [=] 쓰고, 큰따옴표[" "]로 0:09:38.940,0:09:44.640 새의 이름을 넣으면 됩니다.[br]마지막으로, 명령 끝엔 항상 세미콜론[;]이 있어야 합니다 0:09:45.433,0:09:49.573 그리고 스크립트를 저장하는것도 잊지 마세요 0:09:49.573,0:09:54.360 이제 게임을 실행하면... GameObject의 이름이[br]바뀌였네요. 좋습니다 0:09:55.080,0:09:58.560 네, 이제 그 코드는 지우세요. [br]방금 쓴 코드는 우리가 코드로 0:09:58.560,0:10:03.120 게임과 대화할 수 있다는 걸 알려줍니다[br]저희는 코드를 작성하여 누구와 대화할지 0:10:03.120,0:10:08.280 대상을 정할 수 있고, 대화의 주제도 정하고, 0:10:08.280,0:10:14.160 그 후 명령을 정할 수 있습니다[br]저희는 이 짓을 많이 하게 될겁니다. 0:10:14.880,0:10:19.740 아무튼 저희가 진짜로 해야할 일은,[br]Rigidbody2D 컴포넌트에서 Info 아래에 보면 0:10:19.740,0:10:23.400 Velocity가 회색으로 표시된게 보일겁니다 0:10:23.400,0:10:27.120 저희는 위쪽으로 Velocity를 주는 코드를 작성해서[br]새가 하늘로 날 수 있게 만들겁니다 0:10:27.120,0:10:32.640 문제는, 이 스크립트는 GameObject의 [br]윗부분과 Transform끼리만 대화할 수 있고 0:10:32.640,0:10:37.200 다른 컴포넌트의 존재도 모릅니다 0:10:37.200,0:10:42.480 그래서 이 스크립트에 RigidBody2D를 위한 공간을 만들어야 합니다 0:10:42.480,0:10:48.360 그러면 대화를 할 수 있게 되고 명령을 보낼 수 있게 되며[br]이를 '레퍼런스'라 부릅니다 0:10:48.360,0:10:52.380 Class와 Start 사이에 레퍼런스를 작성할 겁니다: 0:10:52.380,0:10:57.840 public RigidBody2D myRigidBody; 0:11:00.540,0:11:06.480 이제 RigidBody2D를 보관할 공간이 생겼고,[br]다른 Rigidbody2D와 구분하기 위해 0:11:06.480,0:11:12.060 공간의 이름도 정했습니다[br]public으로 정했기 때문에 스크립트 밖에서도 0:11:12.060,0:11:18.240 공간을 건드릴 수 있습니다[br]저장하고 Unity로 돌아가면, 스크립트 컴포넌트에 0:11:18.240,0:11:24.780 RigidBody2D를 위한 공간이 생긴걸 볼 수 있습니다[br]이제 RigidBody2D 컴포넌트를 빈칸에 드래그하면, 0:11:24.780,0:11:28.740 이제 스크립트와 RigidBody간의 통신선이 생겼습니다. 0:11:29.340,0:11:36.300 다시 Visual Studio로 돌아와서, Update에[br]myRigidBody 그리고 점[.]을 치면 0:11:36.300,0:11:40.440 이 많은 대화 주제들을 보세요[br]angularDrag, gravityScale, mass; 0:11:40.440,0:11:45.540 이것들이 전부 RigidBody2D에 있는 속성들입니다[br]우리가 원하는건 velocity죠 0:11:45.540,0:11:51.060 전에 했던 것처럼 [=]을 쓰고, 0:11:51.060,0:11:57.180 여기에서는 Vector라는 2D 공간에서 위치를 나타내는[br]값을 이용할 겁니다 0:11:57.180,0:12:02.400 여기서 Vector는 새가 나는 방향을 나타내는데 사용할겁니다 0:12:02.400,0:12:08.940 저희는 새가 위로 나는걸 원하기 때문에, [br](0,1)이 좋겠네요. 저는 Vector2.up을 이용할 겁니다 0:12:08.940,0:12:14.400 *Vector2.up은 Vector2(0,1)과 같은 의미입니다[br]그리고 힘을 주려면 0:12:14.400,0:12:19.920 Vector에 힘을 곱하면 됩니다[br]힘은 대충 10 정도면 충분할 겁니다 0:12:19.920,0:12:24.720 그리고, 전에 말했지만, Update 안에 있는 코드는 [br]매 프레임마다 실행되기 때문에 0:12:24.720,0:12:31.560 저장하고 플레이 해보면... 영원히 날아갑니다 0:12:31.560,0:12:36.360 하지만 저희가 원하는건 스페이스 바를 누를 때만 [br]새가 날아가게 하는 것이죠 0:12:36.360,0:12:41.040 이제 프로그래밍에서 가장 중요한 요소를 사용할 때입니다:[br]바로 if 입니다. 0:12:41.040,0:12:43.380 if는 마치 관문과도 같습니다 0:12:43.380,0:12:47.640 게임이 특정 조건을 만족하지 못한다면, [br]매 프레임마다 그 코드는 완전히 무시됩니다 0:12:47.640,0:12:52.020 반대로, 관문에 적혀 있는 특정 조건을 만족한다면, 0:12:52.020,0:12:56.700 통과할 수 있게 되고 코드가 실행됩니다. 0:12:56.700,0:13:00.960 저희가 원하는건 "만약 플레이어가 스페이스 바를 누르면,[br]위쪽으로 velocity를 더한다"죠 0:13:00.960,0:13:06.300 if를 적고 괄호 안에 조건을 적으면 됩니다 0:13:06.300,0:13:12.360 여기서는 컴포넌트와 대화하는게 아니라 Unity와 대화하게 됩니다[br]정확히는 Unity의 인풋 시스템이죠 0:13:12.360,0:13:20.160 (Input.GetKeyDown, 그리고 괄호 안에 KeyCode.Space)[br]이렇게 하면 Unity에게 0:13:20.160,0:13:25.200 이 프레임에 스페이스를 눌렀는지 물어볼 수 있습니다[br]그리고 마지막에 ==true 로 마무리합시다 0:13:25.200,0:13:31.020 참고로 등호를 1개[=] 만 사용하면[br]왼쪽에 있는 걸 0:13:31.020,0:13:35.280 오른쪽과 같게 만들라는 의미이고, [br]2개[==]를 사용하면 왼쪽에 있는게 오른쪽에 있는것과 같은지 0:13:35.280,0:13:38.520 여부를 확인하라는 의미입니다.[br]괜찮죠? 0:13:38.520,0:13:43.740 아무튼, "만약 스페이스가 눌리면..." 0:13:43.740,0:13:48.960 그 후는 중괄호{}를 사용해야 합니다.[br]중괄호 안에 위로 velocity를 주는 코드를 쓰면 됩니다 0:13:50.100,0:13:54.240 이제 Update에서 - 매 프레임마다 게임이 관문에 가서 0:13:54.240,0:13:59.340 "스페이스가 눌렸니?"라는 질문을 받은 후, 만약 맞다면[br]코드가 실행되고 새는 날게 되겠죠, 아니라면 0:13:59.340,0:14:02.760 중괄호 안에 있는 코드는 무시하고,[br]다음 프레임에 다시 시도하게 될겁니다 0:14:02.760,0:14:08.160 이제 저장하고 Unity로 돌아와서 플레이해보면, 짜잔: 0:14:08.160,0:14:11.460 이제 스페이스를 누를 때마다 새가 위로 올라가네요 0:14:11.460,0:14:17.340 이제 저희는 Input에 반응하는 캐릭터를 만들었습니다. [br]이것은 게임입니다. 좋아요! 0:14:17.340,0:14:23.100 그런데, 조작감이 좀 쓰레기같네요[br]원작 플래피 버드와는 전혀 다른 느낌입니다 0:14:23.100,0:14:31.860 그러니 숫자를 좀 바꿔볼까요[br]저장, 플레이, 그래도 별로네, 정지, 숫자 번경; 0:14:31.860,0:14:36.540 저장,... 그런데 이건 너무 느리고 바보같네요[br]덜 바보같은 짓을 해봅시다 0:14:36.540,0:14:41.520 먼저, 함수를 만들겁니다. 스크립트의 윗부분의 [br]RigidBody 레퍼런스 바로 밑에 0:14:41.520,0:14:47.160 public float flapStrength를 만듭시다 0:14:47.160,0:14:51.960 float란 부동소수점(floating point number)를 뜻합니다.[br]간단히 말하면 소수점이 있는 숫자라는 의미입니다 0:14:51.960,0:14:57.720 다시 Update로 돌아와서, Vector2.up에 10이 아니라[br]flapStrength를 곱할겁니다 0:14:57.720,0:15:02.040 이제 스크립트 컴포넌트를 보면 새로운 공간이 보일겁니다: 0:15:02.040,0:15:06.900 Flap Strength. 그리고 이건 언제든지 번경할 수 있습니다; 0:15:06.900,0:15:11.340 심지어 플레이 중에도 번경할 수 있습니다[br]참고로 플레이 중 번경한 값은 0:15:11.340,0:15:15.360 저장되지 않기 때문에, [br]게임의 중요한 요소를 다룰 때에도 0:15:15.360,0:15:18.660 아무 숫자나 막 집어넣어도 상관없습니다 0:15:18.660,0:15:22.680 그래서, flapStrength와 RigidBody의 중력 스케일이나 0:15:22.680,0:15:26.700 질량을 적당히 조절하다 보면 언젠가는 [br]좋은 값을 찾을 수 있을 겁니다 0:15:26.700,0:15:29.640 숫자 계속 바꾸기,[br]이게 게임 디자인이죠 0:15:30.300,0:15:31.440 잠깐 되돌아봅시다 0:15:31.440,0:15:36.000 코드를 활용하여 플레이 중에도 컴포넌트의 속성을 바꿀 수 있다. 0:15:36.000,0:15:40.860 스크립트는 기본적으로 gameObject에 있는 다른 컴포넌트들과 [br]대화할 수 없고, 할려면 0:15:40.860,0:15:45.000 원하는 컴포넌트의 레퍼런스(공간)를 만들어야 한다. 0:15:45.000,0:15:49.860 레퍼런스(공간)는 코딩으로 만들고, 빈 공간은 Unity에서[br]드래그 앤 드롭으로 채운다 0:15:50.400,0:15:56.280 Start에 있는 코드는 (스크립트가 존재할 때) 한번만 실행되고[br]Update에 있는 코드는 0:15:56.280,0:16:01.920 매 프레임마다 계속 실행된다. 하지만 if를 사용하여[br]조건 미충족시 코드를 스킵할 수도 있다 0:16:01.920,0:16:04.740 그리고 public을 사용하면[br]*(팁: [SerializeField]를 사용하면 private여도 Unity에서 값 바꿀수 있음) 0:16:04.740,0:16:07.860 Unity의 인스펙터에서 값을 바꿀 수 있다.[br]*(팁: [SerializeField]를 사용하면 private여도 Unity에서 값 바꿀수 있음) 0:16:09.480,0:16:13.680 플래피 버드의 비밀을 하나 말씀드리자면 0:16:13.680,0:16:18.180 새가 파이프를 지나는 것처럼 보이지만 0:16:18.180,0:16:23.640 새는 가만히 있고 파이프가 움직이는 겁니다[br]그래서 이번에는 0:16:23.640,0:16:28.620 파이프 생성, 그리고 파이프를 움직이게 하고 [br]없애는것까지 배울겁니다 0:16:28.620,0:16:32.280 우선 생성할 오브젝트를 만듭시다 0:16:32.280,0:16:35.100 오른쪽에서 왼쪽으로 가는 파이프 2개를요 0:16:35.100,0:16:40.500 빈 오브젝트를 만들고, 이름은 pipe로 합시다[br]일단은 파이프 크기를 맞추기 위해 0:16:40.500,0:16:44.520 새 중앙에 놓겠습니다.[br]그 다음 pipe 안에 빈 오브젝트를 만들고 0:16:44.520,0:16:50.700 이름은 top pipe로 하겠습니다[br]이런 걸 GameObject의 "자식"(child) 이라고 합니다 0:16:50.700,0:16:55.080 자식을 이용하면 GameObejct 여러 개를 한 곳에 모와,[br]"부모"를 움직이면 자식도 함께 움직이게 할 수 있습니다 0:16:55.980,0:17:00.000 새를 만들 때 했었던 짓을 또 하겠습니다[br]이미지를 넣기 위해 Sprite Renderer를 추가하고 0:17:00.900,0:17:06.840 판정을 위해 Box Collider 2D를 넣겠습니다[br]Rigidbody는 필요 없습니다 0:17:06.840,0:17:13.440 물리의 영향을 받을 필요가 없으니까요.[br]파이프를 위로 올리겠습니다 - 단, X좌표는 0으로 하세요 0:17:13.440,0:17:19.020 그 후, 이걸 복사하고[br]이름을 bottom pipe로 바꾼 후, 0:17:19.020,0:17:24.420 180도 회전하고 아래로 내리겠습니다 0:17:24.420,0:17:31.020 여기서 부모 GameObject를 움직여 보면,[br]파이프 2개가 부모를 중심으로 0:17:31.020,0:17:35.400 동시에 움직이는걸 볼 수 있습니다 0:17:35.400,0:17:38.940 이제 움직이게 하기 위해[br]부모에 스크립트를 추가하겠습니다 0:17:40.680,0:17:46.080 우선 이동 속도를 위한 변수를 하나 만듭시다[br]여기에 값을 부여하면, 0:17:46.080,0:17:50.700 Unity에서 그 값이 기본으로 설정됩니다[br]물론 Unity에서 언제든지 바꿀 수 있긴 합니다 0:17:50.700,0:17:56.100 이제 Update에 오브젝트를 움직이는 코드를 작성합시다[br]여기서 0:17:56.100,0:18:03.360 그냥 transform.position.x로 할 수 있다면 좋겠지만[br]아쉽게도 안됩니다 0:18:03.360,0:18:08.580 Vector 전체를 한번에 바꿔야 합니다[br]그리고 이번엔 Vector2 대신 Vector3를 쓸 겁니다 0:18:08.580,0:18:14.760 transform은 값 3개가 필요하기 때문이죠[br]이 게임은 2D이긴 하지만 0:18:14.760,0:18:19.980 Unity는 근본적으로 3D 엔진이기 때문에[br]오브젝트의 Z값도 필요합니다 0:18:20.580,0:18:26.160 아무튼, 움직이게 하려면[br]현재 위치에다가 다른걸 더해야 하기 떄문에 0:18:26.160,0:18:31.200 transform.position = transform.position + 0:18:31.200,0:18:37.320 그 후 괄호 안에 Vector3.left * moveSpeed; 0:18:39.000,0:18:43.500 Unity로 돌아와서, 플레이를 누르면[br]너무 빠르네요 0:18:43.500,0:18:47.520 그냥 moveSpeed에 엄청 작은 값, 0:18:47.520,0:18:53.280 예를 들어 0.001을 넣어도 되긴 하지만[br]문제의 근본적인 원인은 그게 아닙니다 0:18:53.280,0:18:58.860 Update에 있는 코드는 가능한 한 많이 실행됩니다[br]게임 뷰에서 통계를 보면; 0:18:58.860,0:19:03.060 게임이 초당 1000프레임으로 구동되고 있는게 보이네요 0:19:03.060,0:19:07.680 플레이스테이션 5에게 미안해지네요,[br]120프레임? 플래피 버드에겐 잽도 안되는군요 0:19:07.680,0:19:11.880 아무튼 이게 중요한 이유는,[br]컴퓨터 사양에 따라 게임이 다른 속도로 구동될 가능성이 있다는 겁니다 0:19:11.880,0:19:16.440 컴퓨터 사양에 따라 파이프 속도가 달라지면 안돼죠 0:19:16.440,0:19:22.680 시장에 있는 게임에도 이런 실수가 종종 보입니다 -[br]다크 소울 2에선, 무기 내구도가 프레임과 0:19:22.680,0:19:30.660 연관되어 있어서 60프레임에선 30프레임보다[br]내구도가 2배 빨리 닳았습니다 0:19:30.660,0:19:36.420 해결법은 간단합니다[br]그냥 Time.deltaTime을 곱하면 됩니다 0:19:36.420,0:19:41.280 이러면 프레임에 상관 없이 움직임이 일정한 간격으로 발생합니다 0:19:41.280,0:19:44.820 Rigidbody에 이게 없어도 됐던 이유는[br]물리와 관련된 건 타이머가 내장되어 있기 때문이였고, 0:19:44.820,0:19:49.320 그 외 상황에는 필요합니다.[br]이거(혹은 다른거 뭐든지)에 대해 알고 싶다면, 0:19:49.320,0:19:53.580 Unity 사용자 매뉴얼을 확인해보세요[br]정보와 샘플 코드도 있습니다 0:19:53.580,0:19:59.400 아무튼, 이제 파이프가 부드럽게 움직이네요[br]좋습니다 0:19:59.400,0:20:04.560 다음으로, 파이프가 무한히 생성되는 시스템을 만들겠습니다 0:20:04.560,0:20:10.740 우선 계층 구조에 있는 부모 GameObject를 프로젝트에 드래그하세요 0:20:10.740,0:20:16.980 이러면 프리팹이 생성됩니다[br]프리팹은 이 GameObject 전체의 설계도와도 같죠 0:20:16.980,0:20:22.500 그리고 프리팹을 이용하면[br]이 GameObject들의 바리에이션을 만들기 쉬워집니다 0:20:22.500,0:20:26.460 프리팹을 만들었으면, 계층 구조에 있는건 지워도 됩니다. 0:20:26.460,0:20:29.460 이제 새로운 빈 오브젝트를 만들고[br]이름을 PipeSpawner로 지읍시다 0:20:30.720,0:20:36.240 카메라 영역 오른쪽에 놓고,[br]이제 스크립트를 만듭시다 0:20:36.240,0:20:41.820 스크립트에는 매초마다 파이프 프리팹의 새로운 바리에이션을[br]생성하는 코드를 작성할겁니다 - 파이프가 왼쪽으로 움직이는건 0:20:41.820,0:20:46.800 이미 전에 했기 덕분에, 파이프가 생성되면 자동으로 왼쪽으로 움직일겁니다 0:20:47.400,0:20:51.360 방금 전에 만든 프리팹을 소환하는 코드를 작성할겁니다 0:20:51.360,0:20:54.276 일단 프리팹의 레퍼런스부터 만들겠습니다 0:20:54.276,0:20:58.680 여기에 public GameObject pipe; 를 작성합니다 0:20:58.680,0:21:03.840 그 후 Unity에서 빈칸을 드래그로 채울겁니다.[br]이 빈칸은 0:21:03.840,0:21:07.920 컴포넌트로 채우는게 아니라, 프리팹으로 채워야 합니다 0:21:07.920,0:21:11.580 Unity에는 새로운 GameObject를 생성하는 기능이 내장되어 있기에 0:21:11.580,0:21:17.880 그걸 써먹으려면, Instantiate, 그리고 괄호를 열면 0:21:17.880,0:21:22.980 뭔가 자세히 입력하라고 뜨네요[br]화살표를 눌러 이 레시피? 같은걸 넘기다 0:21:22.980,0:21:28.500 보면 - 4번이 좋아보이는군요[br]특정한 좌표와 기울기를 가진 GameObject를 생성한다고 하네요 0:21:28.500,0:21:32.760 생성할 GameObject는 pipe고; 좌표는 0:21:32.760,0:21:37.560 transform.position을 사용하면 이 스크립트가 달린 오브젝트의 0:21:37.560,0:21:42.180 좌표를 구할 수 있기에 그걸 쓰면 되고,[br]기울기는 0:21:42.180,0:21:46.800 같은 원리로 transform.rotation을 쓰면 됩니다 0:21:48.300,0:21:52.740 플레이 해보면, 맙소사 너무 많이 소환되네요 [br]소환은 되는데 0:21:52.740,0:21:55.560 매 프레임마다 소환되고 있습니다 0:21:55.560,0:21:59.760 작당한 간격을 두고 소환되게 만듭시다[br]- Visual Studio로 돌아와서 0:21:59.760,0:22:05.100 타이머를 만들겁니다 0:22:05.100,0:22:10.140 타이머가 끝나면, 코드 실행,[br]타이머, 같은 식으로요 0:22:10.140,0:22:14.520 일단 변수 몇개를 만들어야 합니다[br]spawnRate는 소환 간 간격을 0:22:14.520,0:22:19.560 나타내고, timer는 말 그대로 타이머입니다 0:22:19.560,0:22:22.980 timer는 private로 작성할 겁니다[br]왜냐면 다른 스크립트에서도 timer를 쓰면 혼동이 오니까요 0:22:22.980,0:22:29.400 Update에는, if를 작성할겁니다[br]만약 timer가 spawnRate보다 작다면: 0:22:29.400,0:22:34.980 timer를 1만큼 올릴겁니다[br]그럴려면 0:22:34.980,0:22:39.780 현재 timer에 time.deltaTime을 더하면 됩니다[br]이러면 매 프레임마다 timer가 올라가고 0:22:39.780,0:22:42.600 컴퓨터 사양에 상관없이 타이머가 일정하게 올라갑니다 0:22:42.600,0:22:48.480 이 과정은 += 로 줄일 수 있지만,[br]다른 사람한데 꼽사리 안받으려고 0:22:48.480,0:22:53.040 코드 분량을 이 악물고 줄일 필요는 없습니다 0:22:53.040,0:22:58.440 만약 timer = timer + ~ 가 읽기 더 편하다면[br]그렇게 쓰면 됩니다 0:22:58.440,0:23:01.740 나중에 생각이 바뀌더라도 그냥 바꾸면 되니까요 0:23:01.740,0:23:05.220 아무튼, 제가 전에 if는 관문과도 같단 말을 했었죠 0:23:05.220,0:23:09.540 else를 이용하면 관문 옆에 또다른 관문을 만들 수 있습니다 0:23:09.540,0:23:14.520 즉, if 조건을 만족하지 못하면 else에 있는 조건을 시도합니다 0:23:14.520,0:23:22.560 이제 else 안에 파이프 생성 코드를 쓰고, [br]timer를 0으로 리셋하는 코드도 쓰겠습니다. 이제 매 프레임마다 0:23:22.560,0:23:28.500 timer가 spawnRate보다 작은지 확인하고,[br]만약 맞다면, timer 증가, 아니라면, 즉 0:23:28.500,0:23:33.420 timer가 생성 주기와 같거나 높으면, [br]파이프를 생성하고 timer를 0으로 리셋. 0:23:33.420,0:23:38.820 저장하고 플레이하면 - 잘 되네요[br]근데 한가지 문제점은, 0:23:38.820,0:23:44.100 첫 파이프가 생성될때까지 한참 기다려야 된다는 점입니다[br]파이프가 시작하자마자 나오면 좋을텐데요 0:23:44.100,0:23:49.560 파이프 생성 코드를 Start에 복붙하면,[br]시작하자마자 파이프가 나올겁니다 0:23:49.560,0:23:55.320 그런데 이런 식으로 코드 전체를 복붙하는건 좋은 습관이 아닙니다 0:23:55.320,0:24:00.900 게임을 만들 때는, 똑같거나 비슷한 코드를 온갖곳에 두는건[br]피해야 합니다. 이유를 말하자면, 0:24:00.900,0:24:06.120 예를 들어 파이프 스폰 방식을 바꾸고 싶다고 하면[br]온갖곳에 있는 코드를 전부 일일히 바꿔야 할겁니다 0:24:06.120,0:24:10.260 대신, 그 코드를 새로운 함수(function)에 넣고, [br]그 함수를 실행하면 됩니다 0:24:10.260,0:24:15.180 Update 밑에, 마지막 중꽐호 위에, 0:24:15.180,0:24:21.420 void spawnPipe()라는 함수를 만들고,[br]파이프 생성 코드를 안에 넣으면 되죠 0:24:21.420,0:24:27.720 이제 원래 그게 있던 자리에 spawnPipe()만 넣으면 됩니다 0:24:27.720,0:24:32.340 이제 spawnPipe()라는 코드가 실행될 때마다 [br]아래에 있는 함수가 실행됩니다 0:24:32.340,0:24:37.800 잘 되는지 확인해보면,[br]처음 시작할때 파이프 나오고, 타이머 지날때마다 생성되네요. 좋습니다 0:24:38.760,0:24:44.700 그런데, 파이프가 항상 중간에 나오니[br]게임이 너무 단조롭네요 0:24:44.700,0:24:49.080 파이프의 높이가 랜덤하게 나왔으면 좋겠는데;[br]파이프 생성 코드가 어떻게 되있었는지 기억나시나요? 0:24:49.080,0:24:52.980 오브젝트의 생성 좌표를 지정할 수 있었던거 기억나나요?[br]그 값을 바꿉시다 0:24:52.980,0:24:58.140 현재는 파이프가 항상 같은 좌표에 생성되고 있죠[br] 0:24:58.140,0:25:03.960 X좌표는 같아도 되니 냅두고, Y는... [br]PipeSpawner 위 혹은 아래에 랜덤하게 생성되면 좋겠네요 0:25:03.960,0:25:08.520 우선 heightOffset이라는 public 변수를 만듭시다[br]값은 10정도로 하죠 0:25:08.520,0:25:14.220 그리고 이 안에 lowestPoint라는 float를 만들겁니다[br]함수 안에서 변수를 만들고 있기에, 0:25:14.220,0:25:19.800 이 변수는 이 함수 안에서만 사용 가능합니다 0:25:19.800,0:25:22.200 또한, ??? 0:25:22.200,0:25:29.820 일단 lowestPoint = transform.position.y - heightOffset[br]그리고 0:25:29.820,0:25:36.600 highestPoint도 만들겁니다 [br]lowest와 같지만 - 대신 +를 넣으면 됩니다. 숫자 2개가 만들어졌으니 0:25:37.560,0:25:41.400 이제 파이프 생성 코드에 있던 transform.position을[br]바꾸면 됩니다 0:25:41.400,0:25:47.400 여기에 new Vector3를 입력할겁니다.[br]Vector에 우리만의 숫자를 입력할 때마다 new를 0:25:47.400,0:25:53.700 써야 합니다. 괄호 안에는 x,y,z좌표를 넣을 겁니다.[br]x는, 0:25:53.700,0:25:59.160 PipeSpawner의 x와 같아야 하기에 [br]transform.position.x로 하고 0:25:59.160,0:26:05.160 y는, Random.Range, 괄호 열고 최솟값과 최댓값을 0:26:05.160,0:26:12.300 적으면 됩니다. 바로 lowestPoint와 highestPoint겠죠[br]그리고 z는 0으로 하면 됩니다. 0:26:14.220,0:26:19.560 Unity로 돌아와서 해보면, 좋아요![br]파이프가 두 값 사이에서 랜덤하게 생성되네요 0:26:19.560,0:26:24.780 아, 마지막으로, 파이프가 생성된 후 왼쪽으로 가다가 0:26:24.780,0:26:30.120 ...계속 가네요. - 좋지 않습니다[br]화면 밖에서 아무것도 안하고 [br] 0:26:30.120,0:26:35.100 메모리만 잡아먹고,[br]너무 많이 생성되면 0:26:35.100,0:26:40.140 파이프가 모니터 밖으로 튀어나와[br]책상을 더럽힐 수도 있습니다 0:26:40.140,0:26:45.060 고칠려면, 타이머를 이용해[br]일정한 시간이 지나면 파이프를 삭제하는것도 되지만, 0:26:45.060,0:26:50.700 저희는 파이프의 x좌표를 확인하여[br]일정 좌표를 넘어가면 그 파이프가 삭제되도록 할겁니다 0:26:50.700,0:26:58.260 새를 이용하여 화면 왼쪽의 x좌표를 재겠습니다[br]저는 -45정도네요 0:26:58.260,0:27:06.120 PipeMove 스크립트에서, [br]public float deadZone = -45, 그리고 간단한 if문; 0:27:06.120,0:27:13.020 if (transform.position.x < deadZone){[br]Destroy(gameObject);} 0:27:15.720,0:27:18.840 Unity에서 실행해보면, [br]잘 사라지네요 0:27:18.840,0:27:24.420 딱 한개만 더 합시다 0:27:24.420,0:27:32.880 0:27:32.880,0:27:39.420 0:27:39.420,0:27:44.820 0:27:44.820,0:27:50.280 0:27:51.900,0:27:52.800 0:27:52.800,0:27:55.560 0:27:55.560,0:27:58.980 0:27:58.980,0:28:04.020 0:28:04.020,0:28:08.940 0:28:08.940,0:28:12.660 0:28:12.660,0:28:17.400 0:28:17.400,0:28:21.540 0:28:21.540,0:28:26.520 0:28:26.520,0:28:30.960 0:28:32.400,0:28:35.820 0:28:35.820,0:28:39.360 0:28:39.360,0:28:43.380 0:28:43.380,0:28:47.460 0:28:47.460,0:28:52.560 0:28:52.560,0:28:57.540 0:28:57.540,0:29:01.260 0:29:01.260,0:29:06.600 0:29:06.600,0:29:11.520 0:29:11.520,0:29:16.680 0:29:16.680,0:29:21.660 0:29:21.660,0:29:28.260 0:29:28.260,0:29:34.200 0:29:34.200,0:29:40.140 0:29:40.140,0:29:44.700 0:29:46.620,0:29:49.080 0:29:49.080,0:29:53.280 0:29:53.280,0:29:56.640 0:29:56.640,0:29:59.820 0:29:59.820,0:30:02.940 0:30:03.960,0:30:08.820 0:30:08.820,0:30:13.860 0:30:13.860,0:30:18.180 0:30:18.180,0:30:22.740 0:30:22.740,0:30:27.600 0:30:27.600,0:30:30.360 0:30:30.360,0:30:34.980 0:30:34.980,0:30:40.680 0:30:40.680,0:30:46.320 0:30:46.320,0:30:52.500 0:30:52.500,0:30:58.680 0:30:59.280,0:31:04.680 0:31:04.680,0:31:09.540 0:31:09.540,0:31:16.020 0:31:16.020,0:31:20.460 0:31:20.460,0:31:25.009 0:31:25.740,0:31:30.840 0:31:30.840,0:31:39.240 0:31:39.240,0:31:45.720 0:31:45.720,0:31:51.720 0:31:52.800,0:31:56.580 0:31:56.580,0:32:02.820 0:32:05.340,0:32:10.140 0:32:10.800,0:32:14.460 0:32:15.060,0:32:18.660 0:32:18.660,0:32:23.220 0:32:23.220,0:32:28.380 0:32:28.380,0:32:33.060 0:32:33.060,0:32:37.740 0:32:37.740,0:32:42.000 0:32:42.000,0:32:45.180 0:32:45.180,0:32:50.700 0:32:50.700,0:32:55.920 0:32:55.920,0:33:00.900 0:33:00.900,0:33:06.420 0:33:06.420,0:33:13.920 0:33:13.920,0:33:18.960 0:33:18.960,0:33:25.620 0:33:25.620,0:33:30.060 0:33:30.060,0:33:34.440 0:33:34.440,0:33:41.340 0:33:41.340,0:33:45.840 0:33:45.840,0:33:51.060 0:33:51.060,0:33:56.880 0:33:56.880,0:34:01.320 0:34:01.320,0:34:05.520 0:34:05.520,0:34:08.340 0:34:08.340,0:34:12.720 0:34:12.720,0:34:16.800 0:34:16.800,0:34:23.820 0:34:23.820,0:34:30.060 0:34:30.060,0:34:34.680 0:34:34.680,0:34:37.380 0:34:37.380,0:34:46.740 0:34:46.740,0:34:50.820 0:34:50.820,0:34:54.420 0:34:54.420,0:34:57.900 0:34:57.900,0:35:02.280 0:35:03.480,0:35:09.300 0:35:09.300,0:35:13.800 0:35:13.800,0:35:19.020 0:35:19.020,0:35:22.740 0:35:22.740,0:35:28.200 0:35:28.860,0:35:33.960 0:35:35.400,0:35:41.340 0:35:41.340,0:35:47.340 0:35:47.340,0:35:52.860 0:35:52.860,0:35:57.660 0:35:57.660,0:36:03.900 0:36:03.900,0:36:10.620 0:36:10.620,0:36:15.480 0:36:15.480,0:36:20.400 0:36:22.560,0:36:27.494 0:36:27.494,0:36:33.420 0:36:33.420,0:36:38.520 0:36:39.240,0:36:45.360 0:36:45.360,0:36:50.160 0:36:50.160,0:36:54.900 0:36:54.900,0:36:58.980 0:36:58.980,0:37:03.120 0:37:03.120,0:37:07.440 0:37:07.440,0:37:12.660 0:37:12.660,0:37:14.040 0:37:14.040,0:37:17.880 0:37:17.880,0:37:22.920 0:37:22.920,0:37:25.680 0:37:25.680,0:37:29.760 0:37:29.760,0:37:34.080 0:37:34.080,0:37:36.660 0:37:36.660,0:37:42.300 0:37:42.300,0:37:46.740 0:37:46.740,0:37:50.940 0:37:50.940,0:37:56.580 0:37:56.580,0:37:59.400 0:38:01.020,0:38:06.900 0:38:06.900,0:38:11.340 0:38:11.340,0:38:16.320 0:38:16.980,0:38:21.060 0:38:21.060,0:38:28.440 0:38:30.960,0:38:36.900 0:38:36.900,0:38:41.580 0:38:43.440,0:38:48.000 0:38:48.000,0:38:53.520 0:38:53.520,0:38:58.680 0:38:59.520,0:39:02.100 0:39:02.100,0:39:07.080 0:39:07.080,0:39:12.060 0:39:12.060,0:39:17.580 0:39:17.580,0:39:22.560 0:39:23.940,0:39:30.180 0:39:30.180,0:39:35.460 0:39:35.460,0:39:42.720 0:39:44.580,0:39:48.000 0:39:48.960,0:39:53.340 0:39:57.300,0:40:02.580 0:40:02.580,0:40:07.560 0:40:07.560,0:40:12.000 0:40:13.380,0:40:16.260 0:40:16.260,0:40:22.620 0:40:22.620,0:40:27.750 0:40:27.900,0:40:30.116 0:40:31.467,0:40:38.611 0:40:38.820,0:40:42.300 0:40:42.300,0:40:48.180 0:40:48.180,0:40:52.680 0:40:52.680,0:40:57.720 0:40:57.720,0:41:03.360 0:41:03.360,0:41:10.277 0:41:10.277,0:41:16.440 0:41:16.440,0:41:21.420 0:41:21.420,0:41:28.380 0:41:28.380,0:41:34.320 0:41:34.320,0:41:38.340 0:41:38.940,0:41:44.160 0:41:44.160,0:41:49.080 0:41:49.080,0:41:54.480 0:41:54.480,0:42:01.200 0:42:01.200,0:42:06.360 0:42:06.360,0:42:11.400 0:42:11.400,0:42:17.040 0:42:17.040,0:42:24.360 0:42:24.360,0:42:31.500 0:42:31.500,0:42:35.400 0:42:35.400,0:42:39.960 0:42:39.960,0:42:43.980 0:42:43.980,0:42:48.660 0:42:48.660,0:42:53.700 0:42:53.700,0:42:55.573 0:42:55.573,0:43:00.060 0:43:00.060,0:43:05.220 0:43:05.220,0:43:10.440 0:43:10.440,0:43:15.660 0:43:15.660,0:43:21.420 0:43:21.420,0:43:27.559 0:43:27.559,0:43:31.674 0:43:31.674,0:43:37.260 0:43:37.260,0:43:41.160 0:43:41.160,0:43:43.860 0:43:43.860,0:43:48.360 0:43:48.360,0:43:51.900 0:43:51.900,0:43:55.020 0:43:55.020,0:44:00.300 0:44:00.300,0:44:05.700 0:44:05.700,0:44:11.220 0:44:11.220,0:44:15.600 0:44:15.600,0:44:19.320 0:44:19.320,0:44:22.800 0:44:22.800,0:44:25.740 0:44:25.740,0:44:30.540 0:44:30.540,0:44:35.400 0:44:35.400,0:44:40.620 0:44:40.620,0:44:45.120 0:44:45.120,0:44:48.840 0:44:48.840,0:44:53.280 0:44:53.280,0:44:58.320 0:44:58.320,0:45:03.480 0:45:03.480,0:45:07.500 0:45:07.500,0:45:11.580 0:45:11.580,0:45:15.060 0:45:15.060,0:45:19.200 0:45:19.200,0:45:20.940 0:45:20.940,0:45:25.680 0:45:25.680,0:45:30.600 0:45:30.600,0:45:35.223 0:45:35.223,0:45:38.879 0:45:38.879,0:45:46.366 0:45:46.366,0:45:52.279 0:45:52.279,0:45:54.540 0:45:54.540,0:45:58.680 0:45:58.680,0:46:04.380 0:46:04.380,0:46:10.380 0:46:10.380,0:46:14.040 0:46:14.040,0:46:17.460 0:46:17.460,0:46:22.140 0:46:22.140,0:46:25.440 0:46:25.440,0:46:30.540