골드메탈 - 언데드 서바이버 따라하기 네 번째 (영상 1 ~ 5 정리 노트)
유니티 게임 개발 무료 강의 - 네 번째 따라하기
강사: 골드메탈 (나무위키 링크)
Unity 에서 찐 유명하신 분!?
강의 링크 (영상이 22 개... 😀)
>>>>> 1 강 정리 노트 >>>>> >>>>> >>>>>
설치부터 설명
C:\Unity Hub 처럼 C 드라이브 루트에 설치 하는 것을 권장
C:\Unity Editor 등도 루트에 설치하는 것을 권장 (한글 파일명에 의한 문제 사전 방지?!)
Unity Hub 3.3.0 + 20213 LTS 버전으로 강의 진행
따라하기는 Unity Hub 3.12.1 + 6000.1.0f1 로 진행
강사님은 2D (URP) 프로젝트를 선택해서 생성하지만, 6 버전에는 대응되는 프로젝트는 Universal 2D 프로젝트
* URP : Universal Render Pipeline
참고로, Gemini 에게 물어보면 가르쳐주기 때문에 상황설명 잘 해주면 알려주니 이용하자
예제 Prompt : 유니티 2021 버전에서 2D 프로젝트와 2D (URP) 프로젝트의 차이점은 무엇인가요? 유니티 6 에서 진행하는 경우에 2D (URP) 에 대응하는 프로젝트는 무엇인가요? 유니티 6에는 유사한 프로젝트로 Universal 2D 와 2D Mobile 과 2D (Built-In Render Pipeline) 이 있습니다.
강의에서는 goldmetal.co.kr 에서 언데드 서바이버 에셋 을 받을 수 있다고 하지만,
공사 중으로 나오고 애셋을 찾을 수가 없는데...
강의 고정 댓글에 유니티 애셋 스토어에 등록되어 있으니 받으라는 댓글과 링크가 있음
Free 이니 내 애셋에 추가하고 Unity Editor 에서 열어서 받으면 됨
하면, 추가됨
강의 노트
아틀라스 : 여러 스프라이트가 하나로 묶인 형태 혹은 스프라이트 시트 (Sprite Sheet)
픽셀 아트 스프라이트 사전 설정 (Sprites/Farmer 0 의 경우)
안 쪽의 사각형 하나가 유닛 하나
Pixel Per Unit : 주 캐릭터의 실제 크기로 설정 (18)
Filter Mode : Point 로 설정 (No Filter)
Compression : None 으로 설정
Sprite Editor 로 잘라서 쓸 수 있도록 Sprite Mode 는 Multiple 로 한다
Automatic 으로 하지 말고, Grid By Cell Size 를 사용하고, Padding 을 1 씩 넣어준다
잘 잘라졌는지 확인하기 위해서 우측 상단에 있는 버튼을 선택해서 알파값만을 보이게 처리
Apply 버튼 옆에 뭔가 했는데... 다 이유가 있네... 😮
용어 노트
트랜스폼 : 위치, 회전, 크기 속성을 관리하는 컴포넌트
Stand 0 sprite 를 화면 중앙에 (X, Y 가 0) 위치하면 잘 안 보이는 상황이 발생하는데,
이 경우에 3D Icons 의 값을 조절해서 크기를 작게 만들면 된다
Player (Stand 0 sprite) 에게 Add Component 를 통해서 기능을 추가한다
Rigidbody 2D : 물리 영향을 받는 컴포넌트 (충돌, 중력 등)
여기서 Gravity Scale 이 1 로 되어 있는데 (중력의 영향을 * 1 만큼 받는다. 원래 설정값의 1 배수만큼 받는다는 의미)기본 값을 볼 수 있는 설정은 아래와 같은 곳에 있다.
Edit - Project Settings 에서 Physics 2D 탭에 Gravity 항목을 보면 된다.
Rigidbody 2D 설정시에 Gravity 값이 1 이면 왜 아래로만 떨어지나 했는데..
이제 이해가 됨 (Y 값에서 - 를 빼서 양수로 만들고 게임을 실행하면 위로 날아감 😀)
용어 노트
콜라이더 : 물리적인 충돌면을 결정하는 컴포넌트
Player 의 그림자를 위한 Shadow sprite 는 추가할때 Hierarchy 에서 chile object 로 추가하도록 한다.
겹치는 문제는 Order in Layer (우선적으로 그리는 순서)
=> Player (5), Shadow (0) 으로 설정하는데, 나중에 추가되는 것을 고려해서 간격을 좀 두고 설정
배경은 Main Camera 의 Background 값 조정
>>>>> 2 강 정리 노트 >>>>> >>>>> >>>>>
스크립트 만들기 시작하는데, Scripts 폴더 대신에 Codes 폴더를 사용하심
최신 버전에서도 동일한 문제가 나오는지는 확실치 않지만
강의 버전에서는 스크립트 생성한 후에 3~5초 기다려주는 것을 권장
키보드 입력 처리
용어 노트
MonoBehaviour : 게임 로직 구성에 필요한 것들을 가진 클래스
Input : 유니티에서 받는 모든 입력을 관리하는 클래스
void Update()
{
inputVec.x = Input.GetAxis("");
}
Axis (축) 의 입력값은 문자열인데, 여기에 들어가는 문자열은 아래에서 볼 수 있다고 한다
Edit - Project Settings... - Input Manager
void Update()
{
float moveSpeed = 10;
//Define the speed at which the object moves.
float horizontalInput = Input.GetAxis("Horizontal");
//Get the value of the Horizontal input axis.
float verticalInput = Input.GetAxis("Vertical");
//Get the value of the Vertical input axis.
transform.Translate(new Vector3(horizontalInput, verticalInput, 0)
* moveSpeed * Time.deltaTime);
//Move the object to XYZ coordinates defined as
//horizontalInput, 0, and verticalInput respectively.
}
Time.deltaTime 은 마지막 프레임 이후 경과된 시간을 나타냄. moveSpeed 변수에 Time.deltaTime을 곱하면 GameObject가 매 프레임마다 일정한 속도로 움직이는 것을 보장
* 프레임 독립적인 (frame independent) 게임을 만드는데 중요한 개념
public class Player : MonoBehaviour
{
public Vector2 inputVec;
// Update is called once per frame
void Update()
{
inputVec.x = Input.GetAxis("Horizontal");
inputVec.y = Input.GetAxis("Vertical");
}
}
Player 에 해당 스크립트를 추가하고, 게임을 실행해서 inputVec 의 x, y 값의 변화를 보자
x 는 -1 에서 1
y 는 -1 에서 1 까지이고, 키를 누르지 않게 되면 0 으로 다시 돌아간다 ✅
나중에 실제 사용하는 코드는 GetAxisRaw() 를 사용하게 되는데,
GetAxisRaw()
=> 정확하고 즉각적인 반응이 필요한 움직임 (스무딩이나 필터링이 적용되지 않음)
반환값: 키보드의 경우 -1, 0, 1
GetAxis()
=> 부드럽고 자연스러운 가속 및 감속 효과
반환값: 키보드 입력의 경우에도 -1 과 1 사이의 부동 소수점
✅게임의 형태, 취향에 따라 결정하면 된다고 함
용어 노트
GetComponent<T> : 오브젝트에서 컴포넌트를 가져오는 함수
T 자리에 컴포넌트 이름 작성
FixedUpdate : 물리 연산 프레임마다 호출되는 생명주기 함수
물리이동 세 가지 방법
첫 번째 : 힘을 준다 = AddForce
두 번째 : 속도를 직접 제어한다 = Velocity
세 번째 : 위치를 옮긴다 = MovePosition (순간이동)
예)
void FixedUpdate()
{
// 1. 힘을 준다
rigid.AddForce(inputVec);
// 2. 속도 제어
// rigid.velocity = inputVec;
rigid.linearVelocity = inputVec;
// 3. 위치 이동
rigid.MovePosition(rigid.position + inputVec);
}
velocity 는 6.1 에서는 absolete (이제 더 이상 쓸 수 없는 / not in use any more) 이기 때문에
linearVelocity 로 바꿔줌
6.1 Manual 에 있는 내용
'Rigidbody2D.velocity' is obsolete: 'Please use Rigidbody2D.linearVelocity instead.
3 번을 이용한 움직임을 만든 코드
normalized : 벡터 값의 크기가 1이 되도록 좌표가 수정된 값
void Update() 에서는 Time.deltaTime 을
void FixedUpdate() 에서는 Time.fixedDeltaTime 을 사용한다
현재까지의 Player.cs
public class Player : MonoBehaviour
{
public Vector2 inputVec;
public float speed;
Rigidbody2D rigid;
// Start is called once before the first execution of Update after the MonoBehaviour is created
void Awake()
{
rigid = GetComponent<Rigidbody2D>();
}
// Update is called once per frame
void Update()
{
inputVec.x = Input.GetAxisRaw("Horizontal");
inputVec.y = Input.GetAxisRaw("Vertical");
}
void FixedUpdate()
{
Vector2 nextVec = inputVec.normalized * speed * Time.fixedDeltaTime;
rigid.MovePosition(rigid.position + nextVec);
}
}
>>>>> 2 강 추가 정리 노트 >>>>> >>>>> >>>>>
Input Manager => 유니티의 오래된 인풋 방식
새로운 Input System 을 이용하는 방법 소개
Window - Package Manager 선택시에 설치된 package 를 검색해보면
6000.1 에서는 이미 설치되어 있음
Player 게임오브젝트에 Player Input Component 를 추가해준다
강의에는 Actions 를 추가하고 있는데, 6000.1 버전에서는 None 이 아니라 InputSystem_Actions 가 이미 할당되어 있어서 추가로 할 일이 없음
using UnityEngine.InputSystem;
public class Player : MonoBehaviour
{
public Vector2 inputVec;
public float speed;
Rigidbody2D rigid;
void Awake()
{
rigid = GetComponent<Rigidbody2D>();
}
void OnMove(InputValue value)
{
inputVec = value.Get<Vector2>();
}
void FixedUpdate()
{
Vector2 nextVec = inputVec * speed * Time.fixedDeltaTime;
rigid.MovePosition(rigid.position + nextVec);
}
}
- UnityEngine.InputSystem 추가
- Behaviour 에 나열된 메소드 중에 OnMove() 를 사용
- InputValue.Get<Vector2>() 에서 이미 normalize 된 값을 넘겨줌
- InputValue.Get<Vector2>() 에서 이미 normalize 된 값을 넘겨줌
>>>>> 3 강 정리 노트 >>>>> >>>>> >>>>>
방향 바라보기
SpriteRender 는 이미지를 반전시키는 Flip 속성이 있다
LateUpdate() : 프레임이 종료 되기 전 실행되는 생명주기 함수
SpriteRenderer spriter;
void Awake()
{
...
spriter = GetComponent<SpriteRenderer>();
}
void LateUpdate()
{
if (inputVec.x != 0) {
spriter.flipX = inputVec.x < 0;
}
}
셀 애니메이션(여러 장의 이미지를 순차적으로 보여주는 방식) 사용
Player 게임 오브젝트에 Run_Player0, Stand_Player0, Dead_Player0 애니메이션을 추가한 후에 보면 Animatior component 가 추가되어 있다
Animator : 애니메이션을 상태로 관리하는 컴포넌트
추가한 애니메이션이 들어 있는 Animations 폴더에 보면 Controller 에 이미 설정되어 있는 Player 라는 Animator Controller 가 추가되어 있다
✅강사님 추천 방식
Player 로 그냥 두는 것보다 AcPlayer 로 이름을 바꿔주면 맨 앞에 위치해서 좋다고 합니다.
애니메이터 설정
처음 추가한 Run_Player0 이 Entry 에서 가르키고 있다
Stand_Player0 으로 바꾸기 위해서는
우클릭으로 메뉴 생성해서 Set as Layer Default State 메뉴를 선택한다
애니메이터에서 Transition 은 상태 이동을 어떻게 할 것인지 설정하는 통로
상태 변경을 위한 조건 Parameters 추가 (float/int/bool/trigger type존재)
파라메터를 각 Transition 의 Condition 에 적용한다
즉시 상태 변경을 위해서
- Has Exit Time 의 경우에 체크 해제
- Transition Duration (s) 는 0.25 에서 0 이나 0.01
Dead animation 처럼 1 번만 실행을 원한다면, Loop Time 을 체크 해제
Player.cs 에 추가되는 코드
Animator anim;
void Awake()
{
...
anim = GetComponent<Animator>();
}
void LateUpdate()
{
anim.SetFloat("Speed", inputVec.magnitude);
... }
주의: 대소문자를 구분해야 한다
magnitude 는 x, y 값에 따른 vector 의 length 를 뜻한다
Player0 에 대한 Animation 추가 후 Animator 설정까지 진행을 했고,
Player1 에 대한 Animation 추가 후에는 AcPlayer Animator 를 재활용하기 위해서 Animator Override Controller 를 이용한다
Player 를 복사해서 Animator 컴포넌트에 있는 Controller 값을 AcPlayer 에서 AcPlayer1 로 교체해주면, 새로운 개릭터와 애니메이션을 볼 수 있다. (Player.cs 코드도 동일하게 재사용)



























댓글
댓글 쓰기