참고 동영상 링크 - https://www.youtube.com/watch?v=wrtP_yALRb0
[ 1. Setting Up the Unity Editor ]
1. Setting up the Unity Editor
유니티 설치 체크
2. Creating a Project
새 프로젝트 생성
3. Importing the Assets
Package Import >> “2D Beginner: Tutorial Resources”
4. Unity Editor interface
Project Window
Console Window
Hierarchy Window
Scene View
Game View
Inspector Window
GameObject와 Component
5. Toolbar and Navigation UI
Play buttons
Play / Pause /Step
Manipulating objects
Hand Tool / Move Tool / Rotate Tool / Scale Tool / Rect Transform Tool (2D 만을 위한 move,scale,rotate가 가능한 도구)
Rotate, Move,Scale (세가지 기능을 다 할 수 있는 도구)
F 키 / 마우스 더블 클릭
Navigating with the mouse
left
middle + 드래그
right + 드래그 : 3D 모드에서 테스트
6. Layouts
2 by3 / 4 Split / Tall / Wide / Default
본인 Layout 만들어서 저장하기
[ 2. Main Character and First Script ]
1. Create a New Scene
씬 생성 및 저장
2. Import Assets into your Project
루비 다운로드 및 import
루비 import 세팅
Pixel Per Unit : 100이면 pixel 당 1:1 대응으로 스프라이트 이미지가 생성됨
3. Use a Sprite to create a GameObject
루비 Sprite Renderer 확인
[ 부연 설명 ]
[ GameObject 1 ] - GameObject에 대한 간단한 설명
[ 실습 ] Object Empty에서 "Cube Object" 만들기 - GameObject와 Component의 관계를 알 수 있음
Cube 생성 : 목적물
Object Empty : 초기
Mesh Filter
Box Collider
Mesh Renderer
Materials
Element : Default-Diffuse
[ Component 1 ] - Component들이 어떤 것들이 있는지를 간단하게 설명
Cube를 대상으로 설명( Empty Object에서 Cube 만들어 보기)
GameObject는 Component를 모아 놓은 Container
4. Set coordinates for Ruby
Ruby pos (-2,0)
5. Units of distance in Ruby's Adventure: 2D Beginner
Unit : 관념적인 단위
6. Create a New Script
RubyController 스크립트 생성
[부연 설명 ]
[ 실습 ] Console 창에 Start/Update가 실행될 때마다 Console 창에 메시지를 출력할 수 있도록 함
Cube 생성
Script 생성
Start : "Start ... " 출력될 수 있도록
Update : "Update 1" ~ "Update 100" 까지 출력될 수 있도록
7. Explore the Default Script
Start()
Update()
Vector2 position = transform.position;
positoin.x = position.x + 0.1f * horizental;
transform.postion = position;
8. Adjust the Update Function
transform.position.x = transform.position.x + 0.1f; // Error
9. Declare a Variable
10. Move the GameObject
11. Store the GameObject’s new position
12. Review your Changes
Compiling : 컴파일 중임을 알리는 부분
RubyController component 루비에 삽입
play test
13. Structuring Scripts
14. Structuring Scripts: Line Endings
; (세미 콜론) 설명
15. Structuring Scripts: Number Formats
실수 표현 설명(double, float) >> 예> 0.2f
16. Summary
[ 3. Character Controller and Keyboard ]
1. Control Movement with Keyboard Input
2. View the Default Input Settings
Edit > project Settings > Input
Horizental / Vertical 키워드
조이 스틱 : -1 ~ 1 / 키보드 : 1,-1
3. Modify Your Code to Use Axes
4. Declare a New Variable
GetAxis : 이미 정의되어 있는 함수
파라미터 : " " 설명
Dot operators 설명
5. Write the Horizontal Value to the Console
Debug.Log
6. Adjust the Movement Code
7. Test Your Changes
GetAxis : -1 ~ 1 : Smooth 한 입력값(-1 ~ 1)을 받아옴
GetAxisRaw : -1, 0, 1 : 오로지 3가지 값만 표현되서 받아옴
8. Exercise: Add Vertical Movement
Vertical 처리는 과제
9. Review the exercise solution
과제 리뷰
10. Timing and Framerate
QualitySettings.vSyncCount = 0;
수직 동기화 off
QualitySettings : 퍼포먼스를 좌우할 수 있는 품질 세팅을 관리하는 클래스(
Application.targetFrameRate = 10;
초당 프레임을 10으로 설정 (초당 10번의 Update()가 수행됨)
11. Express Ruby’s Movement in Units per Second
void Update()
{
float horizontal = Input.GetAxis("Horizontal");
float vertical = Input.GetAxis("Vertical");
Vector2 position = transform.position;
position.x = position.x + 0.1f * horizontal * Time.deltaTime;
position.y = position.y + 0.1f * vertical * Time.deltaTime;
transform.position = position;
}
Time.deltaTime 설명
12. Review your script changes
주석문 설명
13. Test Your Changes
14. Check Your Script
[ 부연 설명 ]
[transform.position]
Vector2 position = transform.position;
positoin.x = position.x + 0.1f * horizental;
transform.postion = position;
transform.position = transform.position.x + 0.1f * horizental; (x)
네이티브 코드에 랩핑되어 있는 변수로 Vector2(3) 자료형으로만 접근 할 수 있도록 하고 있음
[Vsync]
[ 4. World Design - Tilemaps ]
1. Introduction
Tilemap의 필요성
2. Create a Tilemap
Grid
Timemap
3. Create a Tile
Tile Palette 생성
Window >> 2D >> Tile Palette
Create New pallete
4. Assign a Sprite to FirstTile
5. Add FirstTile to your Palette
brush로 타일 그릴 때, Edit 버튼을 누르고 해야 함
6. Fit your Tile Sprite to the Grid
7. What is a Tileset?
8. Adjust a Tileset
9. Adjust the Tileset’s Sprite Settings
10. Assign your Sprites to Tiles
11. Adjust the Other Tilesets
12. The Tile Palette Toolbar
13. Paint Your Tilemap
14. Change the Order in Layer for your Tilemap
Order in Layer : -10
15. Summary
[ 5. Decorating the World ]
1. Add Decorations
MetalCube 생성
2. How to Fix the Ordering Problem
[부연 설명 ] Sorting Layers
Order in Layer
Navtive 2D Flatform 등장 이후 생긴 옵션
GameObject의 z축의 거리와 관계 없이 Layer 값이 높을 수록(아래쪽에 있을 수록) 화면 앞에 놓이게 됨
'+' Layer 생성 / '-' Layer 삭제
끌기로 Layer 순서 조정 가능
3. Change the Graphics Settings
Edit > Project Settings > Graphics > Transparency Sort Axis ( 0, 1, 0 )
y값에 따라 정렬되어 보일 수 있도록 함
4. Adjusting the Sprite Settings
Sprite Renderer > Sprite Sort Point : Pivot
5. Adjust a Single Sprite Pivot
(Sprite) Import Setting > Pivot : bottom
6. Change Pivots Using the Sprite Editor
Sprite Editor를 이용한 pivot 바꾸기
7. What is a Prefab?
[ 부연 설명]
Pre + fabricate : 미리 제작물을 만들어 놓은 것?
하나의 애셋(Asset)으로 프로젝트 뷰에 저장되어 있는 재사용 가능한 GameObject
Prefab을 Drag & Drop 으로 GameObject의 생성을 가능하게 해 줌
GameObject의 생성 및 관리를 수월하게 해줌
하나의 Resource로 여러 개의 GameObject를 생성하는 만큼 메모리의 효율도 높일 수 있음
Prefab 생성 방법
Project View >> Create >> Prefab
Hierachy View에 존재하는 GameObject를 Drag하여 Project View로 가지고 오는 방법
Prefab의 특징
Prefab에 있는 속성을 바꾸게 되면, 기존에 이 Prefab을 사용하고 있는 모든 GameObject도 속성이 바뀌게 됨
만약 바뀌게 하고 싶지 않으면, GameObject의 이름을 바꿔 주면 됨
Prefab Menu - GameObject의 Inspector에 위치한 메뉴
Select : GameObject와 연결된 Prefab을 표시해 줌
Open : Prefab 만을 작업할 수 있는 창을 열어 줌
Overrides
Revert All : Prefab에 설정된 값으로 다시 되돌림
Apply All : 현재 GameObject의 변경 사항을 Prefab에 적용
8. Create a Prefab
9. Adjust Prefab settings
여러 개의 MetalCube룰 만들어서 테스트
10. Creative Time
Art > Sprites > Environment에 있는 것들로 월드를 구성하자.
pivot을 아래쪽으로 할 것
PPU 설정을 알맞게 조정할 것
다 만든 객체들은 prefab으로 저장할 것
11. Summary
[ 6. World Interactions - Blocking Movement ]
1. What is the Physics System?
자연의 물리 현상을 흉내낸 것
중력, 힘, 마찰력 등의 물리 현상
2. Add a Rigidbody 2D Component
Ruby에 Ridgidbody2D 넣기
Rigidbody 2D
물리 현상에 영향을 받는 컴포넌트로 중력, 공기저항, 회전마찰계수 등의 속성을 가지고 있음
[ 부연설명 ]
[ Rigidbody ]
3. Disable Gravity
Gravity Scale : 0
4. Disable Gravity for the Ruby Prefab
override를 해서 prefab에 적용하기
5. What is a Collider?
충돌체
6. Add Colliders to GameObjects
BoxCollider2D 추가 (Ruby 와 MeltalBox 두 곳다 넣을 것)
부딪혔을 때, 떨림현상 확인
7. Fix Ruby’s Rotation
Rigidbody2D >> Constraints >> Freeze Rotation : z
8. Why is Ruby Jittering?
Transform의 움직임과 Rigidbody의 움직임의 충돌
Rigidbody 체계로 통일해서 움직일 수 있도록 함
Rigidbody의 Position 가 바뀌면 Transform의 Postiton도 바뀜
9. Fix Ruby's Jittering
rigidbody2d.MovePosition(position);
스스로 다른 콜라이더와 충돌하면 진행하지 않음
10. Review your Changes
GetCompont<Rigidbody2D>()
11. Resize the Colliders
적당한 크기로 collider 박스 만들기
12. Add Tilemap Collision
Grid > Tilemap 게임오브젝트 선택 > Tilemap Collider 2D 컴포넌트 추가
녹색 사각형 확인 : 콜라이더가 추가된 것을 확인할 수 있음
Tile 폴더 > collider가 필요없는 모든 Tile들 선택
Inspector : Collider Type > None
녹색 사각형이 Collider가 필요한 Tile에만 생성된 것을 확인할 수 있음
13. Optimize the Tilemap Collider
Grid > Tilemap 게임오브젝트 선택 > Composite Collider 2D 컴포넌트 추가
rigidbody 2D 컴포넌트가 자동으로 생성됨
Tilemap Collider 2D >> Used By Composite 체크
rigidbody 2D 컴포넌트 > BodyType : Static 으로 설정
능동적인 충돌 체크를 하지 않겠다는 의미
이후 Compsite Collider는 자동으로 구현
14. Summary
[ 7. World Interactions - Collectibles ]
1. Add a Health Stat to Ruby
딸기를 먹으면 생명이 하나 증가하는 기능 구현
public int maxHealth = 5;
int currentHealth;
Rigidbody2D rigidbody2d;
// Start is called before the first frame update
void Start()
{
rigidbody2d = GetComponent<Rigidbody2D>();
currentHealth = maxHealth;
}
// Update is called once per frame
void Update()
{
float horizontal = Input.GetAxis("Horizontal");
float vertical = Input.GetAxis("Vertical");
Vector2 position = rigidbody2d.position;
position.x = position.x + 3.0f* horizontal * Time.deltaTime;
position.y = position.y + 3.0f * vertical * Time.deltaTime;
rigidbody2d.MovePosition(position);
}
void ChangeHealth(int amount)
{
currentHealth = Mathf.Clamp(currentHealth + amount, 0, maxHealth);
Debug.Log(currentHealth + "/" + maxHealth);
}
2. Create New Variables
public 키워드 / private
public 변수의 경우 Editor에 노출이 되고 수정이 가능
int
3. Set Full Health at Game Start
4. Add a Function to Change Health
ChangeHealth() : 사용자 정의 함수로 start(), update() 함수와는 다르게 직접 호출해서 사용하게 된다.
void : 반화타입이 void로 아무것도 리턴하는 것이 없음
매개 변수 : 호출하는 쪽에서 전달되어 들어 오는 인자
Mathf.Clamp(currentHealth + amount, 0, maxHealth)
currentHealth+amount값이 0보다 작거나 maxHealth보다는 클 수 없도록 함(0보다 작으면 0, maxHealth보다 크면 maxHealth)
5. Check Your Changes in Unity Editor
public 변수의 경우 Editor에 노출이 되고 수정이 가능
Ruby Controller >> MaxHealth 5 삽입(Inspector에서)
6. Exercise: Expose Another Variable
루비 speed 조절
public float speed = 3.0f;
position.x = position.x + speed * horizontal * Time.deltaTime;
position.y = position.y + speed * vertical * Time.deltaTime;
7. What is a Trigger?
물리 시스템이 캐릭터와 충돌하는지를 확인하는 유니티에서 제공하는 총돌 감지 시스템
8. Create a Collectible Health GameObject
딸기 이미지 , PPU, BoxCollider2D
Is Trigger 체크
9. Create a Collectible Script
HealthCollectible.cs 생성
public class HealthCollectible : MonoBehaviour
{
void OnTriggerEnter2D(Collider2D other)
RubyController controller = other.GetComponent<RubyController>();
if (controller != null)
{
controller.ChangeHealth(1);
Destroy(gameObject);
}
}
OnTiggerEnter2D
[부연 설명 ] -
OnTriggerEnter2D를 루비에게 넣으면?
루비에게 일원화 시키게 되면, 소스 코드가 지저분해 질 수 있다. Collectible 객체들이 다양할 경우 이에 대한 것들을 처리하기 위해 if 문들을 많이 사용해야 할 수 있다.
10. Give Ruby Health
ChangeRubyHealth() 함수를 public으로 해줘야 함 => 12. 에 설명됨
11. Review Your Code
12. Adjust the RubyController Script
루비의 currentHealth를 강제적으로 1 세팅해서 테스트해 봄(Start함수에..)
currentHealth = 1;
13. Check Whether Ruby Needs Health
14. Define a Property in RubyController
ChangeHealth() 함수를 RubyController에 만든 이유는?
RubyController 클래스 내부에서만 currentHealth의 값을 바꿀 수 있게 함
외부에서 접근해서 읽기만 가능하게 하고 있음
currentHealth의 값과 관련된 기능이므로 oop개념을 유지하기 위해서..
Property 문법 - 참고 링크
15. Use the Property in HealthCollectible
16. Summary
[ 8. World Interactions - Damage Zones and Enemies ]
1. Reset Ruby's Health
Add a Damage Zone
Assets>Art>Sprites>Environment : Damageable => GameObjec 생성
BoxCollider2D 추가
IsTrigger 체크
DamageZone 스크립트 생성 및 추가
Damage Zone Solution
OnTriggerStay2D 메소드로 변경 (TriggerEnter/TriggerStay/TiggerExit - [ Trigger & Collision ])
(루비) : rigidbody >> Sleeping Mode >> Never Sleep : 움직임이 없어도 충돌 체크를 할 수 있도록 함
일시적인 무적 상태 유지
RubyController 수정
2. Graphic sidenote
Sprite Render
Draw Mode : Tiled
Tile Mode : Adaptative .
Sprite Import Settings
Sprite Mode : Mesh Type : Full Rect
Rect 툴로 크기 조정
Box Collider2D
Auto Tiling
3. Enemies
상단의 image 다운로드
PPU를 150으로 할 것 (뒤에 적용할 스프라이트들이 150으로 맞춰져 있음)
Name : Enemy
Rigidbody2D 삽입
gravity Scale : 0
contraints > rotation z : 체크
BoxCollider2D 삽입
적절한 크기 조정
EnemyController 스크립트 삽입
4. Back and Forth
EnemeyController 스크립트 수정 (좌우 / 위아래)
EnemeyController 스크립트 수정 ( 시간 흐름에 따른 방향 전환 )
5. Damage
EnemeyController 스크립트 수정
OnCollisionEnter2D 삽입
Enemy를 Prefab으로 만들자
[ 9. Sprite Animation ]
1. Animator
애니메이션을 하기 위해서는 Animator라는 콤포넌트가 필요
Controller는 애니메이션 시퀀스들을 관리하는 콤퍼넌트
Animator 삽입
2. Creating a New Controller
Create > Animator Controller 생성
Name : Robot
3. Animations
Window > Animation > Animation 창 열기
Create (Animation Clip)
Name : RobotLeft.anim
4. Changing a Sprite
Art>Sprites>Characters : MrClockworkSheet 왼쪽 걷는 이미지 삽입
Sample : 4로 수정
Sprite Color 바꾸기, 사이즈 바꾸기, 회전하기 등의 애니메이션이 가능하지만, 여기서는 Sprite가 바뀌는 애니메이션을 구현
5. Create an Animation
RobotRight.anim 처리
Add Property >> Sprite Renderer >> flip X 추가
Top/Down Anim 처리
6. Building the Controller
Layers : 3D 애니메이션 표현에서 있어서 동작을 Blending 하는데 유용함
Parameters : 외부(Script)와 Animator(Controller)와 연결되는 매개체
Animation State Machine : 각 스테이트는 애니메이션 클립을 가지고 있음
블랜드 트리 : 원래 동작을 Blending 하기 위해서 사용하는 도구이지만, 블랜드 트리를 활용하면 파라미터에 따라 쉽게 표현이 가능하다.
7. Blend Tree 사용하기
Animator : 모든 animation state 삭제
Create State > From New Blend Tree
Blend Tree 더블 클릭
Blend Tree 선택 > Inspector
Blend Type : 2D Simple Directional ( 두 개의 파라미터를 받아서 사용 )
Parameters : 아직 선택할 파라미터가 없음
8. Move X 및 Move Y 파라미터
Animator : Parameter 탭
+ 아이콘 클릭
float형의 Move X, Move Y 생성
Blend Tree > Parameters : Move X, Move Y 선택
Motion > + 아이콘 클릭 (4번)
RobotLeft / -0.5 / 0 / 1
RobotRight / 0.5 / 0 / 1
RobotUp / 0 / 0.5 / 1
RobotDown / 0 / -0.5 / 1
9. 파라미터를 애니메이터 컨트롤러로 전달하기
EnemyController.cs 수정
10. 메인 캐릭터의 애니메이션 설정하기
각 State 확인
Transitions 확인
Has Exit Time
Conditions
Parameter
11. RubyController 스크립트 수정
[ 10. World Interactions - Projectile ]
1. Creating the projectile
Art>Sprites>VFX : CogBullet
PPU : 300
BoxCollider2D, Rigidbody2D 추가 (Gravity : 0)
Projectile.cs 생성
2. Physics system
Start()
Launch()
rigidbody2d.AddForce() : 리지드바디(GameObject)에 힘을 가함
움직임을 Force를 통해서 구현(기존에는 Rigidbody.MovePosition으로 강제 이동했음)
OnCollisionEnter2D()
3. Launching the projectile 1
RubyController.cs 수정
Launch()
4. Instantiate
[ Instantiate & Destroy ]
Instantiate : 프리팹(Prefab)에 있는 객체를 생성하는 함수
Destroy : 만든 GameObject를 파괴하는 함수(Hierarchy View에서 사라짐)
Quaternion : 회전 정보를 담는 자료형(Quaternion.identity : 기본 값)
Quaternion.identity : 기본 값으로 회전이 없음을 의미한다고 생각하면 됨
5.Launching the projectile 2
Input.GetKeyDown() : 특정 키를 얻고자 할 때,
Input.GetButtonDown() : Input Manager에서 설정한 특정 키(버튼)을 얻고자 할 때
GetKey(Button)Down Vs GetKey(Button)
(키/버튼) Down이 발생했을 때 이벤트가 한번 발생하거나, Down이 발생하는 동안 이벤트가 지속적으로 발생하는 차이
6. 오류행 해결
Start() => Awake()
Awake() : 객체(GameObject)가 생성될 때 바로 호출
Start() : 객체가 생성되고 다음 프레임에서 실행됨
7. Layers and collisions
Layer 추가 : Character, Projectile
Ruby : Character 레이어로 변경, Projectile : Projectile 레이어로 변경
Edit > Project Settings > Phsics 2D : Layer Collision Matirx
projectile와 player 간에 충돌 체크가 발생하지 않도록 지정
[ Layer ]
GameObject를 계층별로 구분하기 위해 사용하는 태그 /
주로 Cameras에 따라 씬의 일부만 렌더링 하거나, Lights에 따라 씬의 일부만 밝히는 등에 사용
Layer Mask :
특정한 레이어로 지정된 오브젝만 카메라에 노출, 혹은 반대로 제외하는 컬링마스크(Culling Mask)를 설정해서 사용 /
특정 Layer에만 있는 오브젝트만 충돌 처리를 할 수 도 있음
8. Fixing the Robot
EnemyController.cs 수정
9. Conclusion
Projectile.cs 수정
Vector3.Magnitude() : 벡터의 길이를 리턴
transform.postion.magnitude : 정점에서 부터의 거리를 리턴
Vector3.Distance : 점정 간의 거리를 리턴
Vector3.sqrMagnitude() : Magnitude를 제곱한 값 리턴( 엄밀한 의미로 루트 계산을 안한 값을 리턴)
10. Optional : Animating the fixed robot
RobotFix 애니메이션 State 만들기
파라미터 Fixed 생성
Transition 조건 ( Fixed, Has Exit Time X )
EnemyController.cs
animator.SetTrigger("Fixed"); 추가
11. Script
12. Summary
[ 11. Camera - Cinemachine ]
1. Packages
Package Manager를 통해 import
menu : Window >> Package Manager
Cinemachine Package를 사용함
프로젝트에서 카메라 setting 과 moving을 지원
설치가 끝나면 menu에 Cinemachine 메뉴가 생김
2. Cinemachine setup
Cinemachine은 카메라 setting을 통해 여러 카메라들 사이를 오가며 영상 씬을 편집할 수 있음
여기서는 2D에 맞는 간단하게 Camera work를 진행
일정 범위 내의 object들만 화면에 보일 수 있도록 진행
menu : Cinemachine > Create 2D Camera
CM vam1 생성( Cinemachine Virtual Camera 1)
설정이 다른 여러 가상 카메라를 사용하면서 현재 사용할 가상 카메라를 Main Camera(기본 카메라)의 설정으로 복사해서 사용할 수 있도록 함(즉, 내가 원하는 가상 카메라를 Main Camera에 설정함)
3. Camera Modes
Perspective
Orthographic
size : 5 => Unit 5개의 크기로 세팅(즉, 10 Unit(상/하) 을 볼 수 있는 크기)
4. Following the Main Character
메인 캐릭터를 따라다니는 카메라를 만들기 위한 설정
Cinemachine Virtual Camera(Script) : Follow : Ruby(Transform)
맵 외부에 물 길을 추가하기 ...
5.Camera Bounds
맵의 바깥 부분을 보여주지 않도록 하기 위해 Cinemachine Confiner를 사용
Virtual Camera > Extensions : Add Extension : CinemachineConfiner
CinemachineConfiner(컴포넌트)가 생성된 것 확인
Confiner를 사용하기 위해서 Collider2D가 필요함
Create Empty
Name : CameraConfiner
Polygon Collider 2D
Edit : 경계 작업
CinemachineConfiner > Bounding Shape 2D <-- CameraConfiner
실행해 보면 캐릭터가 중앙에서 밀려 나감
6. Bring your Character Back
Confiner 레이어 만들고 Confiner에 할당
Edit>>Project Settings >> Physics 2D
Layer Collision Matrix에서 Confiner와 중돌하는 모든 것들을 Uncheck
[ 12. Visual Styling - Particles ]
1. Preparing the Sprites
고장난 로봇을 표현하기 위해서 연기가 솟아 오르는 이펙트 효과를 줌
Art >> Sprites >> VFX >> ParticleSheet
PPU : 100
Sprite Editor : 4 by 4 slice
2. Smoke effect
menu : GameObject >> Effect >> ParticleSystem
name : SmokeEffect
Texture Sheet Animation 체크
3. Picking Random Sprites Section
Texture Sheet Animation
Mode : Sprites
스프라이트 이미지 두개 넣기
Start Frame : 0~2
Frame over Time : delete key
Shape Section
파티클이 발상하는 모양
Radius : 0 (시작점으로 수렴)
4. Adding Randomness to Particles
Main Section
Start Lifetime : 시작할 때 주어지는 생존 시간
1.5 ~ 3
Start Size : 시작할 때 파티클 크기
0.3 ~ 0.5
Start Speed : 시작할 때 퍼저나가는 파티클 속도
0.5 ~ 1
5. Making Particles Fade Away
사라질 때, 흐려지게 하기
Color over Lifetime Section : 생존 시간동안의 색깔
오른쪽 알파 값 : 0
Size over Lifetime Section : 생존 시간동안의 크기
1 >> 0으로
6. Particle System in code
smokePrefab을 Robot Prefab의 자식 객체로 만듬
7. Fixing the Smoke Movement
Simulation Space : World
GameObject형으로 받지않고, Component형으로 받게 할까?
GetComponent<>를 통해서 필요한 Component를 다시 얻을 필요가 없음
우리가 원하는 특정 Component가 없는 GameObject를 대입하는 것을 미리 방지 가능
public ParticleSystem smokeEffect;
fix() 부분에 smokeEffect.Stop()
Destory(smokeEffect.gameObject)를 하지 않는 이유
일순간에 파티클이 사라지기 때문에 부자연스러움
8. Creativity Time
hit 상황 및 collectibe을 취할 떄
Looping system
Untik Looping
set Duration
set Stop Action
Rurst emission
Emission Section
Rate over Time : 초당 얼마나 많은 파티클을 분사할 것인지
Rate over Distance : 이동 거리당 방출되는 파티클 수 (움직이는 자동차에 적합)
[ 13. Visual Styling - UI - Head-Up Display ]
1. UI Canvas
주인공 캐릭터의 헬스게이지를 표현하기 위해 사용
이미지, 슬라이더, 버튼 등을 만들 수 있고, 이러한 것들은 Canvas 에서 만들어 짐
Canvas : UI 표현을 위해 필요한 GameObject / 게임 Scene과 다른 별도의 Scene 역할
EventSystem : 게임월드와 UI 간의 상호 작용 처리를 위한 GameObject
2. Rect Transform
Rect Transform : UI만을 위한 특별한 형태의 Transform
Canvas Render Mode - 참고 링크
Screen Space - Overlay :
Screen Space - Camera :
World Space :
3. The Canvas Scaler
Canvas Scaler
Constant Pixel/Physical Size
Scale Width Screen Size
Graphic Raycaster :
버튼과 같은 것들이 클릭 되었는지를 알아내기 위해서 사용(여기서는 필요없음)
4. Adding an Image to the UI
Create > UI > Image
자동 생성된 Canvas 확인 / 생성된 흰색 사격형 이미지 확인
5. Editing the UI in the Editor:
Image : Sprite Image <-- Art > Sprites > UI : UIHealthFrame
Set Native SIze 버튼 클릭 (원본 크기)
6. Resizing your image
Rect 툴 선택
크기 조절 : Shift키를 누르고 하면 균등한 형태로 조절 가능
상단 좌측에 배치
Game View 크기를 조절해 보면 원하는 형태로 되지 않음
7. What are Anchors?
상단 좌측으로 Anchor 설정
Pos X, Y가 중앙이 아니라 상단 좌측을 기준으로 하는 값으로 바뀜
Image(GameObject) --> Health로 Name 변경
8. Adding the Portrait
Health(UI GameObject) 밑에 Image 생성
Image : Sprite Image <-- Art > Sprites > UI : CharacterPortrait
Set Native SIze 버튼 클릭 (원본 크기)
이미지 크기 조절
UI의 크기를 좌우로 조절해 보기(해상도크기 말고 UI 크기)
UI 크기의 비율에 따라 크기를 조절되게 해야 함
Anchor 조정 > 오른쪽 하단의 아이콘 선택
Anchor가 아버지 UI의 크기에 딱 맞게 구성됨
각 모서리의 Anchor를 현 Image UI 크기로 재조정
UI의 크기를 좌우로 조절해 보면, 크기에 맞게 조정됨
9. Masking the Health Bar
Mask
10. How to create a Health Bar Mask
Health(UI GameObject) 밑에 Image 생성
Name : Mask
마스크 크기 조절 및 Anchor 크기도 딱 맞게 조절
Pivot 이동(왼쪽 끝으로) - menu아래에 있는 Pivot/Center 툴바에서 Pivot으로 하면 Pivot을 움직일 수 있음
흰색 이미지는 기본적으로 스텐실 역할을 하기 때문에 이미지를 그대로 사용하면 됨
Mask(UI GameObject) 밑에 Image 생성
Name : HealthBar
Image : Sprite Image <-- Art > Sprites > UI : UIHealthBar
Set Native SIze 버튼 클릭 (원본 크기)
이미지 크기 조절
Image(Component) : Image Type : Simple
Alt + Anchor 오른쪽 하단 아이콘
Mask: Mask 컴포넌트 추가
Show Mask Graphic : uncheck
11. Scripting the Health Bar
using UnityEngine.UI;
UnityEngine.UI 바로 밑에 정의된 것들은 사용하겠다는 의미(여기서는 Image 자료형을 위해)
Image.rectTransform.rect.width
Image.rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, originalSize*value);
지정된 축(Vertical, Horizontal)에 계산되어진 사이즈를 적용하여 rect을 수정할 때 사용
12. Referencing
static member
공유 참조 가능
클래스 명으로 접근 가능
Singleton
static member + property 로 구현했음
13. Updating the Health Bar
14. Check Your Scripts
15. Summary
[ 14. World Interactions - Dialogue Raycast ]
1. Creating the Character
스프라이트 이미지들을 한번에 묶어서 올리면, .anim 파일까지 한번에 만들어 줌
Art > Sprites > Character : JambiSheet
PPU : 150
3개의 Sprite를 동시에 Hierarchy 창으로 이동
.anim 생성
BoxCollider2D 추가
Layer : NPC 만들고 설정
Name : Jambi
플레이 테스트
2. Raycasting
Raycast : Ray를 특정 방향으로 발사(cast)해서 앞에 collider가 있는지를 체크
collision
Physics2D.OverlapPoint(All) : 매개 변수로 들어가는 정점을 기준으로 z 값에 있는 Collider (들)을 알려 준다.
Physics2D.Linecast() : 매개변수로 주어지는 두 점 사이에 있는 Collider가 있을 경우 그 Collider의 정보를 알려줌
[ Ray / RayCast ]
Layer 활용
Physics2D.Raycast(rigidbody2d.position + Vector2.up * 0.2f, lookDirection, 1.5f, LayerMask.GetMask("NPC"));
해당 Layer에서만 진행될 수 있도록 진행
3. Dialog UI
말 풍선과 같은 UI 만들기
Jambi : Create > Ui > Canvas
Render Mode : World Space
Canvas RectTransform
x, y : 0 / Width, Height : 300, 200 / Scale x,y : 0.01, 0.01
4. Changing your Scene
Jambi> Canvas : Create > UI > Image
Source Image <--- Assets/Arts/Sprites/UI/UIDialogBox
[ Image Type (Slice-->Simple) 바꿔줘야 함 ]
RectTransform : Alt+ 오른쪽 하단
Sorting Layer 및 Order in Layer 확인
5. Adding text to your Canvas
TextMesh Pro
사용하기 편함 / 비트맵 & SDF 폰트 지원
폰트 애셋을 생성(한글 폰트 애셋 생성)가능
Canvas : Create > UI > Text-TextMeshPro
Text-TextMeshPro mport 클릭
RectTransform : Alt+ 오른쪽 하단
희선으로 되어 있는 텍스터 영역의 크기를 칠판 안쪽에 맞게 좀 더 줄여줌
Text Mesh Pro UGUI
Text : Hey! Help me fix all those broken robots!
Font Size : 32
6. Displaying Dialog
Jambi > Canvas : Un Active
NonPalyerCharacter.cs 추가
7. Check Your Scripts
SetAcive(true/false) : GameObject를 활성화/비활성화를 지정
8. Summary
[ 15. Audio ]
1. Audio Clips, Audio Source and Audio Listener
[ Audio Listener ]
한 Scene에 한개의 Audio Listener가 필요함 (주로 카메라에 attach)
Audio Source가 재생되는 것을 Listen 하는 역할 (공간적 위치에 따른 효과를 사용할 수 있음)
[ Audio Source ]
Audio Clip의 재생을 담당, 음원이 발생하는 위치
Audio Clip : mp3, ogg, wav 파일 등
[ Audio Reverb Zone]
Audio Listener의 위치에 따라 Audio Source의 에코 영역의 설정
2. Background music
Create > Empty Object
Name : BackgroundMusic
Audio Source 추가
Play On Awake 체크
Loop 체크
Mute Audio : Game View에 있는 사운드 버튼
3. One Shot Sound
한번만 play되는 효과음
PlayOneShot() : 인자로 들어오는 Audio Clip을 한번만 플레이
4. After adding an Audio Source to Ruby:
RubyController.cs 수정
sound 재생은 루비가 할 수 있도록 하고 audio source는 Collectible이 제공하게 함(collectible은 파괴될 객체이니까)
HealthCollectibe.cs 수정
5. Exercise
cog 던질 떄, hit 당했을 때, 사운드를 낼 수 있도록 해보기
6. Spatialization
로봇이 왼쪽/오른쪽에 있는지 소리로 구분할 수 있게 하기 위해 공간 사운드를 만들자.
Enemy : bot에 Audio Source 추가
Audio Clip : Robot Walking_Broken
Loop 체크
Spatial Blend : 3D
7. What is the Maximum Distance?
Maximum and Minimum Distance of Sound
Min/Max Distance : 1/10
그런데, 안들린다. Camera에 Listener가 있음(즉, 이미 멀리 있음)
8. Fixing attenuation
카메라에 자식 객체를 만들어서 z 값을 맞춰 줌
Create Empty
Name : Listener
Listener 컴포넌트 추가
pos : 0, 0, 10 ==> 게임 배경 위치에 놓일 수 있도록 위치 조정
또는 루비에게 Listener를 넣어 줌
[ 16. Build, Run, Distribute ]
1. Player Setting
Edit > Project Settings : Player
Company Name
Product Name
멀티 플랫폼 지원
Player
Resolution and Presentation
Fullscreen Mode
Run In Background
Standalone Player Options
Display Resolustion Dialog : 2019.3 버전 부터 삭제
2. Build Your Game
File > Build Settings
Scenes In Build
Bulid > 폴더 생성(실행 파일을 생성할 ...)
----------------------
[ Unity 2D 확장 기능 ]
사이트 둘러보기
[링크1]
PSD Importer package
How to use the PSD Importer package
Making a collection of icons or items
Creating large objects made from separate parts
Animating characters with skeletal animation in 2D Animation
Creating normal and mask maps versions
[ 참고 사이트 ]
[링크2]
다운로드 애셋
2020.2 or 2020 LTS Unity 버전
2D 프로젝트
open Package Manager >> Packages : My Assets >> Download "Dragon Crashers - 2D Sample Project" >> import
Dragon Crashers 메뉴 >> Load Game Menu
포토샵에서 PSB 추출
2D PSD Import 설치하기
PSB import 옵션
Mosaic : PS layer별 스프라이트를 생성해서 Import
Character Rig : PS에서의 각 스프라이트의 위치를 유지한 채 Import
Use Layer Grouping :
(준비) PSB 파일을 PSD 파일로 만들어서 처리해 보기
유니티 - 포토샵 레이어마다 계층적인 오브젝트 생성됨
make a collection of icons or items ( 같은 사이즈의 크기에 맞게 여러 레이어를 사용해서 작업하면 개꿀...)
Animating characters with skeletal animation in 2D Animation
Six characters from one animated mannequin
Creating large objects made from separate parts (조각난 파트들로 부터 큰 오브젝트를 생성 )
스프라이트 셰입
Making frame by frame animation
-------------------------
[ Tag ]
Polygon Collider 2D
[ Package ]
Assets을 다른 프로젝트에서 사용할 수 있도록 Unity3D에서 제공하는 패키지
Package Import 3가지 방법
프로젝트 생성시 import할 수 있음
현재 프로젝트에서 메뉴를 활용하여 import할 수 있음
Assets >> Import Package
Package 파일을 더불 클릭해서 실행
현재 프로젝트가 떠 있는 경우에는 그안에서 만들어짐
떠 있지 않으면 새로운 프로젝트를 만들어서 생성됨(?)
Package 파일이 위치한 경로에 한글이 들어가면 작동하지 않음
Package Export 방법
Package에 포함할 Assets들을 선택한 후 Export Package 메뉴를 통해 생성
[ Script 기초 ]
Unity Reference - http://docs.unity3d.com/Documentation/ScriptReference/30_search.html?q=MonoBehavior
Component <- Behavior <- MonoBehavior
생성된 Script이름과 클래스이름은 일치해야 함
GameObject에 Script(Component) 삽입하여 사용
Overridable Functions
void Start() : 초기화를 위해 오직 한번만 실행되는 함수
void Update() : 매 프레임마다 실행되는 함수
Start/Update 함수는 C# Script 파일을 만들 때, Default로 주어지는 함수
두 함수 모두 사용하지 않아도 되는 가상 함수임
Debug.Log(".....") :
Unity Console 창에 문자를 출력하는 함수
Debugging 용으로 적절하게 사용할 수 있음
[ Script 심화 ]
Overridable Functions 1 - 함수 호출 순서
void Awake() : GameObject가 Active될 때 무조건 한번 호출됨
void OnEnable() : Script가 활성화될 때 호출(비활성화 되었다 다시 활성화되면 다시 호출될 수 있음)
void Start() : GameObject가 Active이고 Script가 활성화(OnEnable인 상태) 될 때 한번만 호출 (즉, 스크립트가 Disable이면 Start()는 호출 안됨) , 또한 Start()가 한번 호출된 상태이면, 호출되지 않음
void Update() : GameObject를 (파이프 라인상에서)3D 공간상에 배치하기 이전에 수행되는 함수
void FixedUpdate() :
Edit >> project setting >> Time에서 호출되는 Time(Fixed Timestep)을 조절할 수 있음
rigidbody.AddForce() 같은 물리 관련 함수들을 쓸 때 주로 사용
void LateUpdate() :
FixedUpdate나 Update가 처리된 이후에 그 값들을 가지고 처리해야 하는 경우가 있을 때 사용
GameObject를 (파이프 라인상에서)3D 공간상에 배치가 다 끝난 이후(Update이후)에 수행되는 함수
카메라 배치와 관련된 명령에 주로 사용
void OnDestroy() : GameObject가 파괴될 때 호출
[ uUI ]
DateTime.Now.Milliseconds : 현재 시간의 1/1000 초 시간대
Random.Range(int a, int b)
a ~ b-1 까지의 랜덤값 반환
Random.Range(float a, float b)
a ~ b 까지의 랜덤 값 반환
Transform.position과 같은 특정 변수는 멤버 변수로 있는 x, y, z 값을 직접 바꿀 수 없고 Vector3 자료형으로 만들어서 position에 바로 대입해야 함
TimeManager
Unity Reference - http://docs.unity3d.com/Documentation/Components/class-TimeManager.html
http://unitykoreawiki.com/index.php?n=KrMain.class-TimeManager
Fixed Timestep :
물리 기반의 게임의 경우 정확한 Time을 기반으로 움직여야 하기 때문에 일정 간격으로 처리되어야 하는 데, 이 일정 간격을 설정하는 곳 ( 프레임 속도와 무관하게 처리됨)
FixedUpdate()함수가 설정된 시간마다 호출됨
Timestep을 작게 하는 경우 과부하가 걸림
Maximum Allowed Timestep : 이 이상을 벗어나면 제대로된 물리 기반의 처리가 안될 수 있음
Time Scale : 1을 기준으로 2이면 두배 빠른 게임진행을 0.5면 두배 느린 진행을 함
Tags : GameObject에 Tag를 붙여 Game 내에서 활용(주로 Scirpt에서 사용함)
예를 들어 다양한 종류의 적 캐릭터들을 하나의 (Enemy라는)Tag로 묶어서 관리하면 일괄적인 처리가 가능
Size : 현재 설정된 Tag들의 개수
Element 0 : 첫번째 태그의 문자열
Element 1 ~
Layer : 일반적으로 카메라(랜더링)와 관련됨
GameObject들을 특정 Layer 그룹으로 설정할 수 있도록 함
카메라의 Culling mask에 선택적으로 Layer를 설정해 놓으면 원하는 GameObject만 화면에 보이게 할 수 있음
여러 개의 카메라를 설치하고 카메라마다 선택적으로 Layer를 설정하면 다양한 형태의 화면 연출이 가능
31개 까지 만들 수 있음