
1단계: 화면에 놓일 오브젝트를 모두 나열
-배경은 이미지 한 개가 아니라 나무와 지면 오브젝트를 합쳐 만듦

2단계: 오브젝트를 움직일 수 있는 컨트롤러 스크립트 정함
▪ 움직이는 오브젝트에는 움직임을 제어하는 대본(컨트롤러 스크립트)이 필요함
➡️ 밤송이 컨트롤러 스크립트
3단계: 오브젝트를 자동으로 생성할 수 있는 제너레이터 스크립트 정함
▪ 게임을 플레이할 때 생성될 오브젝트를 찾음
▪ 탭할 때마다 밤송이가 날아가므로 게임 도중에 생성되는 오브젝트는 밤송이
▪ 게임을 플레이할 때 오브젝트를 자동으로 만들려면 오브젝트를 만들 수 있는 공장(제너레이터 스크립트)이 필요함
▪ 여기서는 밤송이 공장을 만들어야 하므로 ➡️ 밤송이 제너레이터 스크립트
4단계: UI 갱신할 수 있도록 감독 스크립트 준비
▪ 씬마다 UI나 게임 진행 상황을 판단하는 감독을 준비
▪ 이번 게임은 UI나 씬이 변경되지 않으므로 감독이 필요하지 않음
❇️ 감독 스크립트는 UI나 씬이 변경될 때 필요하다❕❕
5단계: 스크립트를 만드는 흐름 생각
▪ 4단계까지 이번 게임에 필요한 스크립트를 기술했다면 5단계에서는 각 스크립트를 작성하는 흐름을 좀 더 생각함
▪ 3D 게임도 2D와 마찬가지로 컨트롤러 스크립트 → 제너레이터 스크립트 → 감독 스크립트 순서로 만듦

*작성 필요 스크립트
밤송이 컨트롤러
▪ 화면을 탭하면 카메라에서 가까운 부분부터 탭한 장소를 향해 밤송이가 날아감
▪ 밤송이가 과녁에 닿으면 닿은 장소에서 멈추고 밤송이 주위에 확 퍼지는 눈송이 파티클을표시
밤송이 제너레이터
▪ 화면을 탭할 때마다 밤송이를 한 개씩 생성하는 기능을 구현
▪ 3D 게임은 2D 게임과 만드는 흐름이 비슷함

▪ FBX 파일은 3D 모델을 다루는 표준 형식

▪ 게임 무대를 만듦
▪ 프로젝트를 만들면 다음과 같이 Main Camera가 무대 위의 원점을 향해 배치
▪ 카메라에서 X축은 좌우 방향, Y축은 상하 방향, Z축은 깊이 방향을 나타냄
▪ 3D 게임에서는 게임 공간을 빙글빙글 돌면서 오브젝트를 배치하기 때문에 자신이
어느 쪽을 향하고 있는지 잃기 쉬움
➡️ 이때 길잡이가 되는 것이 Scene 뷰 오른쪽 위에 표시되는 ❇️씬 기즈모
Terrain
▪ 씬 위에 지형을 배치하는 것부터 시작
▪ Terrain은 유니티에 준비된 지형 오브젝트로 Terrain을 사용하면 산이나 강 등 지형을 간단히 색을 칠하듯 만들 수 있음
▪ 지형과 마찬가지로 잔디나 모래 등 재질도 색을 칠하듯 채울 수 있음
▪ 3D 나무나 풀도 색을 칠하듯 심을 수 있음

(가볍게 보기)
- 세 가지 색 화살표 표시
▪ Terrain 방향을 알 수 있도록 세 가지 색 화살표를 표시
▪ Scene 뷰의 왼쪽 위에 있는 이동 도구를 클릭하고 Hierarchy 창에서 Terrain을 선택
▪ Scene 탭 아래의 Center 클릭 → ✅Pivot으로 변경- 시점의 회전
▪ Alt키, 손바닥 도구, 마우스 휠- Terrain의 위치 조정
- 지면의 높낮이 설정 -> Raise or Lower Terrain
▪ 좌표의 위치 관계가 중요하므로 항상 씬 기즈모의 방향을 의식하면서 작업을 진행- 지면에 나무 심기
재질 : 풀, 바위
▪ 밤송이가 과녁에 닿았는지 감지할 수 있도록 과녁에 콜라이더를 적용
✓ 단, 과녁에 딱 맞는 원통형 콜라이더가 없으므로 사각형 콜라이더(Box Collider)를 쓰겠음
▪ 3D 게임에서는 2D가 붙지 않은 것을 사용
▪ 과녁의 머리 부분에 콜라이더가 오도록 매개변수를 조절
▪ 과녁 설정을 마쳤으므로 밤송이를 날려 보겠음
▪ 밤송이를 날리는 흐름은 ‘움직이는 오브젝트를 만드는 방법’에서 설명한 대로
씬에 배치하기 → 스크립트 작성하기 → 스크립트 적용하기 순서

▪ 밤송이를 카메라 전방에서 과녁 방향으로 날려야 하므로 카메라 앞에 배치
-> Position 설정

▪ 스크립트를 만들기 전에 밤송이를 물리 법칙대로 움직이도록 Rigidbody 컴포넌트를 적용
▪ 과녁과 충돌 판정을 할 수 있도록 밤송이에도 Collider 컴포넌트(Sphere Collider)를 적용
▪ Rigidbody와 Collider를 적용했으므로 밤송이는 물리 법칙대로 움직임
➡️ 밤송이가 중력에 따라 낙하
▪ 밤송이를 과녁 방향으로 날리려면 힘을 가해야 함
❇️ Physics를 사용할 때는 좌표를 조작하지 않고 힘을 가해 이동시킴
BamsongiController

▪ 이 스크립트에서는 확장성을 고려해 매개변수에서 지정한 방향으로 힘을 가할 수 있는 Shoot 메서드를 작성
▪ Shoot 메서드에서 AddForce 메서드를 사용해 매개변수 방향으로 힘을 가하고 있음
▪ Start 메서드에서는 밤송이가 화면 안쪽으로 날아가도록
+Z축 방향, +Y축 방향의 벡터를 매개변수로 전달하고 Shoot 메서드를 호출
❇️ Y축 방향으로도 힘을 200 가하는 이유는 밤송이가 과녁에 닿기 전에 중력의 영향을 받아 지면으로 낙하하는 것을 막기 위해서임
▪ Start 메서드에서 Shoot 메서드를 호출하므로 게임 시작과 동시에 날아감
▪ 이대로 두면 밤송이는 과녁에 닿는 순간 땅으로 떨어짐
▪ 과녁에 밤송이를 꽂으려고 물리적인 연산을 할 필요❌
✅ 과녁에 충돌하는 순간 밤송이에 들어가는 힘(중력과 화면 안쪽 방향으로 향하는 힘)을 무효로 만들면 됨
▪ 이번 게임에서는 Physics를 사용하므로 과녁과 밤송이가 충돌하면 오브젝트에 적용된 스크립트의 OnCollisionEnter 메서드가 호출
▪ 이 메서드에서 밤송이에 들어가는 힘을 무시하게 하면 됨

BamsongiController 추가
✓ 닿는 순간 Rigidbody 컴포넌트의 isKinematic을 true로 설정
✓ isKinematic을 true로 하면 오브젝트에 작용하는 힘을 무시하고 밤송이를 정지시킬 수 있음
파티클
▪ 실감 나게 플레이하려면 반응을 연출해 재미를 더해야 함
▪ 파티클을 이용해서 이펙트 추가
▪ 파티클은 우리말로 풀면 입자
▪ 입자를 대량으로 표시해 각 입자의 움직임, 색, 크기를 제어함으로써 물, 연기, 불 등 폭넓은 표현을 할 수 있음
▪ 유니티에서는 파티클을 컴포넌트로 제공하므로 이러한 매개변수를 에디터에서 쉽게 편집할 수 있음
▪ 밤송이가 과녁에 닿는 순간 파티클을 표시
혹시모르니까 암기


파티클 표시 순서
① 오브젝트(밤송이)에 ParticleSystem 컴포넌트를 적용
② ParticleSystem 컴포넌트의 매개변수를 조절해 이펙트를 작성
③ 스크립트에서 파티클이 재생되도록 설정
**
1. 밤송이에 ParticleSystem 컴포넌트 적용
2. 파티클에 Material 설정 (Material 설정 안하면 분홍색 색종이 나옴)
**
-Shape를 Sphere로 바꿈(폭죽처럼 둥근 모양으로 펼치도록)
-방출을 시작할 때 반경을 줄여야 하므로 Radius를 0.01로 설정
-지금은 파티클이 계속해서 방출되지만 간헐적으로 방출되도록 조절
➡️ 파티클 생성 패턴을 조절
➡️ Particle System의 Emission 항목을 설정 : Rate over Time, Time, Count
❇️ Rate는 1초당 생성되는 파티클 수, Bursts는 지정한 시간에 생성되는 파티클 수를 나타냄

▪ Duration은 파티클 방출 시간, Start Lifetime은 파티클 표시 시간
📍파티클이 좀 더 부드럽게 사라지도록 만들겠음(페이드아웃)
▪ 파티클의 크기를 서서히 줄여서 부드럽게 사라지도록 함
▪ 파티클 크기를 시간과 함께 변화시키려면 Particle System 항목에서
Size over Lifetime을 조절
▪ 파티클 크기 변화는 Inspector 창 맨 밑에 있는 Particle System Curves 창에서 조절
▪ 파티클을 서서히 줄일 것이므로 아래쪽 감쇠 곡선 모양을 선택
▪ 파티클이 생성된 후 시간이 흐를수록 파티클 크기가 작아짐
Looping 체크 해제 -> 이번 이펙트는 반복 재생❌
Play On Awake 체크를 해제 -> 과녁에 닿았을 때만 첫 이펙트를 표시
▪ 과녁과 밤송이 "충돌을 감지해 파티클 재생"
☑️ 밤송이가 과녁에 닿는 순간 파티클이 재생되도록 스크립트를 수정
✓ 밤송이가 과녁에 닿는 시점에 OnCollisionEnter가 호출
✓ OnCollisionEnter 메서드에서 GetComponent 메서드를 사용해 ParticleSystem 컴포넌트를 구하고,
ParticleSystem 컴포넌트가 가진 Play 메서드를 호출해 파티클을 재생
화면을 탭할 때마다 밤송이를 생성
공장을 만드는 방법
① 이미 있는 오브젝트를 사용해 프리팹을 만듦
② 제너레이터 스크립트를 만듦
③ 빈 오브젝트에 제너레이터 스크립트를 적용
④ 제너레이터 스크립트에 프리팹을 전달


▪ 밤송이 공장에서는 화면을 탭할 때마다 밤송이를 한 개씩 만듦
BamsongiGenerator

▪ bamsongiPrefab 변수를 선언
✓ 단지 변수를 선언한 것이므로 뒤쪽에서 프리팹 실체를 대입
✓ 아웃렛 접속을 사용해 대입할 수 있도록 public을 붙여 선언
▪ GetMouseButtonDown으로 화면이 탭(클릭)되었는지 확인하고,
탭 되었다면 밤송이 인스턴스를 만듦
▪ 이후, 밤송이 인스턴스를 날리는 방향을 지정
✓ 날리는 방향을 지정하려면 BamsongiController에 구현한 Shoot 메서드의 매개변수에 날리고자 하는 방향의 벡터를 전달
✓ GetComponent 메서드를 사용해 BamsongiController 스크립트를 구한 후 Shoot메서드의 매개변수에 화면 안쪽 방향으로 벡터를 지정
Shoot 메서드의 주석 처리
▪ 지금까지는 BamsongiController의 Start 메서드에서 밤송이 발사 방향을 정했음
▪ 앞으로는 ✅공장에서 밤송이를 생성하는 동시에 발사 방향도 결정하므로
BamsongiController의 Start 메서드에서 Shoot 메서드를 호출하는 부분을 주석으로 처리
▪ 밤송이 공장을 건설할 수 있도록 빈 오브젝트를 만들겠음
▪ Hierarchy 창에서 +를 클릭하고 Create Empty를 선택
▪ GameObject가 생성되면 이름을 BamsongiGenerator로 바꿈
▪ 빈 오브젝트에 제너레이터 스크립트를 적용해 공장 오브젝트를 만들겠음
▪ Project 창에 있는 BamsongiGenerator 스크립트를 Hierarchy 창에 있는 BamsongiGenerator 오브젝트로 드래그&드롭
▪ 밤송이 프리팹을 공장으로 전달해야 함
▪ 스크립트에서 선언한 변수에 오브젝트 실체를 대입하려면 아웃렛 접속을 사용
아웃렛 접속
① 스크립트 쪽에 콘센트 구멍을 만들어야 하므로 스크립트 변수 앞에 public 접근 수식자를 붙임
② public 접근 수식자를 붙인 변수가 Inspector 창에 보임
③ 콘센트 구멍에 대입할 오브젝트를 Inspector 창으로 드래그&드롭
▪ bamsongiPrefab 변수는 이미 public으로 선언했으므로 Inspector 창으로
드래그&드롭하기만 하면 됨
▪ Hierarchy 창에서 BamsongiGenerator를 클릭하고,
Project 창의 bamsongiPrefab을 Inspector 창의 Bamsongi Generator (Script) 항목에 있는 Bamsongi Prefab으로 드래그&드롭
▪ 좀 더 게임 다워지도록 탭한 곳으로 밤송이가 날아가도록 제너레이터 스크립트를 업그레이드해 보자
▪ 탭한 곳을 향해 밤송이를 날리려면 탭한 좌표를 알아야 함
☑️ 탭한 좌표는 Input.mousePosition메서드로 구할 수 있지만
3D에서는 mousePosition 값을 그대로 사용할 수 없음
✅ mousePosition 값이 월드 좌표계 값이 아닌 스크린 좌표계 값(2D)이기 때문임
• 월드 좌표계: ‘게임 세계’에서 오브젝트가 어디에 있는지 나타내는 좌표계
• 스크린 좌표계: ‘게임 화면’의 좌표를 나타낼 때 사용하는 2D 좌표

▪ 유니티에는 ScreenPointToRay 메서드가 준비되어 있음
❇️ 스크린 좌표를 전달하면 ‘카메라’에서 ‘스크린 좌표’로 향하는 월드 좌표계로 벡터를 구할 수 있음

▪ 밤송이 생성과 동시에 ScreenPointToRay 메서드로 얻은 방향으로 밤송이에 힘을 가하면 탭한 방향으로 밤송이가 발사될 것 같음
▪ 이 알고리즘을 BamsongiGenerator 스크립트에 추가
▪ ScreenPointToRay 메서드에 탭 좌표를 전달
▪ ScreenPointToRay 메서드는 카메라에서 탭 좌표로 향하는 벡터에 따른 Ray 클래스를 반환
✓ Ray는 이름 그대로 광선이며, 광원의 좌표(origin)와 광선의 방향(direction)을 멤버 변수로 갖음
✓ ScreenPointToRay 메서드의 반환값으로 얻을 수 있는 Ray는 origin이 Main Camera의 좌표, direction
이 카메라에서 탭한 좌표로 향하는 벡터
✓ direction 방향으로 밤송이를 날리기 때문에 direction 벡터가 가진 normalized 변수를 사용해 길이
가 1인 벡터로 만든 후 힘을 2000 곱함
✓ 길이를 1인 벡터로 해서 direction 벡터 크기에 관계없이 밤송이에 일정한 힘을 가할 수 있음
▪ Ray는 콜라이더가 적용된 오브젝트와 충돌을 감지하는 특징이 있음
✓ 즉, 광선이 오브젝트로 가려지면 그것을 감지할 수 있음