플레이어 오브젝트를 생성하고 사용할 이미지를 넣어준 후, Sprite 모드를 Multiple로 설정한다.
Sprite Editor View에서 분할을 해주는데 , Column 3 raw 1으로 설정하면아래와 같이 3개로 분할된 것을 확인할 수 있다. 이후 3개의 이미지 중 Player_Idle_0번에 넣어준다.
애니메이션 재생 설정
플레이어 오브젝트에 Animator 컴포넌트를 추가한다.
프로젝트 뷰에서 animator controller asset을 추가하고 player animator이라고 설정하였다.
대기 애니메이션 등록
프로젝트 뷰에서 애니메이션 오브젝트를 생성한 뒤, loop type은 반복 재생을 할지에 대한 여부를 선택할 수 있어서 체크하여 반복재생하도록 설정한다,
animater controller은 Animator 뷰에서 수정 작업을 할 수 있으며, Animator View, Animation View의 내용을 수정할 때에 Project View에 있는 Animator Controller, Animation 파일을 선택하는 것이 아닌 animator controller가 포함된 플레이어 오브젝트를 선택하고 편집해야한다. .
기존에 생성되어 있는 노드들을 배치를 해주고, 후에 생성한 애니메이션 PlayerIdle을 등록한다.
다음으로 애니메이션이 날개짓을 하게끔 편집하도록 한다. 애니메이션 뷰에서 편집을 진행하며 플레이어 오브젝트가 날개짓이 재생할 수 있도록 Player_Idle의 0,1,2,1,0 순으로 배치하였다. 그리고 show sample rate를 이용해서 재생 속도를 조절 할 수 있다.
사망 애니메이션 등록
idle 이미지와 이미지를 같이 분할해준다. 이후, PlayerDie라고 animation asset을 생성하고, Animator 뷰로 가서 PlayerDie 즉, 사망 애니메이션을 추가할 수 있다.
이후에 사망 애니메이션의 애니메이션 설정한다. 따라서 Player 오브젝트를 선택하여 기존에 진행한 PlyerIdle이 아닌 PlayerDie를 등록한다.
상태전이를 이용한 애니메이션 전환
애니메이션들을 코드를 이용해 연결시킬 수 있으며 전환 조건은 animation view에서 설정할 수 있다.
마우스 오른쪽을 눌러 Make Transition이라는 옵션을 선택한다.
Transition은 애니메이션이 전환될 수 있는 길을 열어주는 것으로 이것이 설정되어 있으면 애니메이션 전환이 가능하다. 아래와 같이 설정되면 게임 실행시 전환이 잘 진행되는걸 확인할 수 있으며, 원하는 시점에서 전환도 가능하다.
강의를 시작하기에 앞서서 플레이어의 이동, 점프등 구현을 위해 2D 오브젝트를 생성하여 원하는 위치에 배치한다.
유니티 패키지 파일: 원하는 파일들을 하나로 묶어 다른 프로젝트로 전달할 때 사용
패키지 파일 생성하기 : Project View에서 원하는 파일들을 선택한 후 마우스 오른쪽을 클릭 → Export Package로 저장
패키지 파일 사용하기 : 파일을 적용하고 싶은 프로젝트의 Project View로 패키지 파일을 드래그앤 드롭으로 가져온다.
player 오브젝트는 중력을 받을 수 있도록 rigidbody2d들을 적용시키고 freeze rotation z를 선택하게 되면 이동할 때 z축으로 회전하지 않게 된다. 그리고 충돌 처리를 위해 Capsule Collider 2D를 추가한다.
Rigidbody2D 컴포넌트의 Constraints
Freeze Position: 물리에 의한 이동 중지
Freeze Rotation: 물리에 의한 회전 중지
플레이어 오브젝트 이동(Rigidbody2D)
플레이어 이동을 구현해보도록 movement2D 스크립트를 작성한다.
using UnityEngine;
public class Movement2D : MonoBehaviour
{
[SerializeField]
private float speed = 5.0f; //이동 속도
private Rigidbody2D rigid2D;
private void Awake()
{
rigid2D = GetComponent<Rigidbody2D>();
}
public void Move(float x)
{
//x축 이동은 x*speed로, y축 이동은 기존의 속력 값(현재는 중력)
rigid2D.velocity = new Vector2(x * speed, rigid2D.velocity.y);
}
}
velocity 변수를 설정한다.
그리고 PlayerController 스크립트를 작성하여 플레이어 좌우 방향키값을 입력하게 되면 movement2D에 함수의키값을 적용에 오브젝트가 이동한다.
using UnityEngine;
public class PlayerController : MonoBehaviour
{
private Movement2D movement2D;
private void Awake()
{
movement2D = GetComponent<Movement2D>();
}
private void Update()
{
//left or a = -1 / right or d = 1
float x = Input.GetAxisRaw("Horizontal");
//좌우 이동 방향 제어
movement2D.Move(x);
}
}
플레이어 오브젝트 점프
플레이어 이동을 위한 Move 함수와 마찬가지로 Jump 함수를 추가한다.
Jump함수가 호출되면 y축 +방향으로 속력이 설정된다. 이때 점프의 정도는 jumpforce 변가 결정한다.
Jump함수는 PlayerController안에서 스페이스 바를 눌렀을 때 실행되도록 한다.
using UnityEngine;
public class Movement2D : MonoBehaviour
{
[SerializeField]
private float speed = 5.0f; //이동 속도
[SerializeField]
private float jumpForce = 8.0f; //점프 힘(클수록 높게 점프)
private Rigidbody2D rigid2D;
private void Awake()
{
rigid2D = GetComponent<Rigidbody2D>();
}
public void Move(float x)
{
//x축 이동은 x*speed로, y축 이동은 기존의 속력 값(현재는 중력)
rigid2D.velocity = new Vector2(x * speed, rigid2D.velocity.y);
}
public void Jump()
{
//jumpForce의 크기만큼 윗쪽 방향으로 속력 설정
rigid2D.velocity = Vector2.up * jumpForce;
}
}
위에 코드에서는 아무런 제약없이 무한히 점프할 수 있다.
using UnityEngine;
public class PlayerController : MonoBehaviour
{
private Movement2D movement2D;
private void Awake()
{
movement2D = GetComponent<Movement2D>();
}
private void Update()
{
//left or a = -1 / right or d = 1
float x = Input.GetAxisRaw("Horizontal");
//좌우 이동 방향 제어
movement2D.Move(x);
//플레이어 점프(스페이스 키를 누르면 점프)
if (Input.GetKeyDown(KeyCode.Space))
{
movement2D.Jump();
}
}
}
낮은 점프, 높은 점프
using UnityEngine;
public class Movement2D : MonoBehaviour
{
[SerializeField]
private float speed = 5.0f; //이동 속도
[SerializeField]
private float jumpForce = 8.0f; //점프 힘(클수록 높게 점프)
private Rigidbody2D rigid2D;
[SerializeField]
public bool isLongJump = false; // 낮은/높은 점프 체크
private void Awake()
{
rigid2D = GetComponent<Rigidbody2D>();
}
private void FixedUpdate()
{
//낮은 점프, 높은 점프 구현 위한 중력 계수 조절 Jump Up일 때만 적용)
//중력 계수가 낮은 if문은 높은 점프가 되고, 중력 계수가 높은 else문은 낮은 점프가 됨.
if (isLongJump && rigid2D.velocity.y > 0)
{
rigid2D.gravityScale = 1.0f;
}
else
{
rigid2D.gravityScale = 2.5f;
}
}
public void Move(float x)
{
//x축 이동은 x*speed로, y축 이동은 기존의 속력 값(현재는 중력)
rigid2D.velocity = new Vector2(x * speed, rigid2D.velocity.y);
}
public void Jump()
{
//jumpForce의 크기만큼 윗쪽 방향으로 속력 설정
rigid2D.velocity = Vector2.up * jumpForce;
}
}
using UnityEngine;
public class PlayerController : MonoBehaviour
{
private Movement2D movement2D;
private void Awake()
{
movement2D = GetComponent<Movement2D>();
}
private void Update()
{
//left or a = -1 / right or d = 1
float x = Input.GetAxisRaw("Horizontal");
//좌우 이동 방향 제어
movement2D.Move(x);
//플레이어 점프(스페이스 키를 누르면 점프)
if (Input.GetKeyDown(KeyCode.Space))
{
movement2D.Jump();
}
//스페이스 키를 누르고 있으면 isLongJump=true
if(Input.GetKeyUp(KeyCode.Space))
{
movement2D.isLongJump = true;
}
//스페이스 키를 떼면 isLongJump=false
else if (Input.GetKeyUp(KeyCode.Space))
{
movement2D.isLongJump = false;
}
}
}
스페이스바를 길게 누르냐 짧게 누르냐에 따라 점프의 높이가 달라진다. 길게 눌렀을 때랑 크게 다른 점은 없지만 이중점프가 가능했다..
바닥 판정 및 점프 제어
바닥에 닿아 있을 때만 플레이어가 뛸 수 있도록 설정하는 코드를 작성해보겠다.
플레이어의 발 위치를 알아야 하며, 코드에서 내가 설정한 collider과 맞게 설정해주어야한다.
충돌이 일어나면 isGrounded 변수가 참이 된다.
using System;
using UnityEngine;
public class Movement2D : MonoBehaviour
{
[SerializeField]
private float speed = 5.0f; //이동 속도
[SerializeField]
private float jumpForce = 8.0f; //점프 힘(클수록 높게 점프)
private Rigidbody2D rigid2D;
[SerializeField]
public bool isLongJump = false; // 낮은/높은 점프 체크
[SerializeField]
private LayerMask groundLayer; //바닥 체크를 위한 충돌 레이어
private CapsuleCollider2D capsuleCollider2D; //오브젝트의 충돌 범위 컴포넌트
private bool isGrounded; //바닥 체크 (바닥에 닿아있을 때 true)
private Vector3 footPosition; //발의 위치
private void Awake()
{
rigid2D = GetComponent<Rigidbody2D>();
capsuleCollider2D = GetComponent<CapsuleCollider2D>();
}
private void FixedUpdate()
{
//플레이어 오브젝트의 Collider2D min, center, max 위치 정보
Bounds bounds = capsuleCollider2D.bounds;
//플레이어의 발 위치 설정
footPosition = new Vector2(bounds.center.x, bounds.min.y);
//플레이어의 발 위치에 원을 생성하고, 원이 바닥과 닿아있으면 isGrounded = true
isGrounded = Physics2D.OverlapCircle(footPosition, 0.1f, groundLayer);
//낮은 점프, 높은 점프 구현 위한 중력 계수 조절 Jump Up일 때만 적용)
//중력 계수가 낮은 if문은 높은 점프가 되고, 중력 계수가 높은 else문은 낮은 점프가 됨.
if (isLongJump && rigid2D.velocity.y > 0)
{
rigid2D.gravityScale = 1.0f;
}
else
{
rigid2D.gravityScale = 2.5f;
}
}
private void OnDrawGizmos()
{
Gizmos.color = Color.blue;
Gizmos.DrawSphere(footPosition, 0.1f);
}
public void Move(float x)
{
//x축 이동은 x*speed로, y축 이동은 기존의 속력 값(현재는 중력)
rigid2D.velocity = new Vector2(x * speed, rigid2D.velocity.y);
}
public void Jump()
{
if(isGrounded == true)
{
//jumpForce의 크기만큼 윗쪽 방향으로 속력 설정
rigid2D.velocity = Vector2.up * jumpForce;
}
}
}
땅으로 사용되는 모든 오브젝트의 layer 값을 Ground로 바꿔주고, 플레이어 오브젝트에도 Ground Layer 변수를 Ground로 설정한다. Movement2D에 게임을 실행하면, 땅에 닿아야지 점프가 되는 것을 확인할 수 있다.
최대 점프 횟수 설정
점프하는 횟수 조절을 할 수 있도록 하여 2단,3단 점프가 가능하게끔 코드를 짠다.
using UnityEngine;
public class Movement2D : MonoBehaviour
{
[SerializeField]
private float speed = 5.0f; //이동 속도
[SerializeField]
private float jumpForce = 8.0f; //점프 힘(클수록 높게 점프)
private Rigidbody2D rigid2D;
[SerializeField]
public bool isLongJump = false; // 낮은/높은 점프 체크
[SerializeField]
private LayerMask groundLayer; //바닥 체크를 위한 충돌 레이어
private CapsuleCollider2D capsuleCollider2D; //오브젝트의 충돌 범위 컴포넌트
private bool isGrounded; //바닥 체크 (바닥에 닿아있을 때 true)
private Vector3 footPosition; //발의 위치
[SerializeField]
private int maxJumpCount = 2; //땅을 밟기 전까지 할 수 있는 최대 점프 횟수
private int currentJumpCount = 0; //현재 가능한 점프 횟수
private void Awake()
{
rigid2D = GetComponent<Rigidbody2D>();
capsuleCollider2D = GetComponent<CapsuleCollider2D>();
}
private void FixedUpdate()
{
//플레이어 오브젝트의 Collider2D min, center, max 위치 정보
Bounds bounds = capsuleCollider2D.bounds;
//플레이어의 발 위치 설정
footPosition = new Vector2(bounds.center.x, bounds.min.y);
//플레이어의 발 위치에 원을 생성하고, 원이 바닥과 닿아있으면 isGrounded = true
isGrounded = Physics2D.OverlapCircle(footPosition, 0.1f, groundLayer);
//플레이어의 발이 땅에 닿아 있고, y축 속도가 0이하이면 점프 횟수 초기화
//velocity.y <= 0을 추가하지 않으면 점프키를 누르는 순간에도 초기화가 되어
//최대 점프 횟수를 2로 설정하면 3번까지 점프가 가능하게 된다.
if(isGrounded == true && rigid2D.velocity.y <=0)
{
currentJumpCount = maxJumpCount;
}
//낮은 점프, 높은 점프 구현 위한 중력 계수 조절 Jump Up일 때만 적용)
//중력 계수가 낮은 if문은 높은 점프가 되고, 중력 계수가 높은 else문은 낮은 점프가 됨.
if (isLongJump && rigid2D.velocity.y > 0)
{
rigid2D.gravityScale = 1.0f;
}
else
{
rigid2D.gravityScale = 2.5f;
}
}
private void OnDrawGizmos()
{
Gizmos.color = Color.blue;
Gizmos.DrawSphere(footPosition, 0.1f);
}
public void Move(float x)
{
//x축 이동은 x*speed로, y축 이동은 기존의 속력 값(현재는 중력)
rigid2D.velocity = new Vector2(x * speed, rigid2D.velocity.y);
}
public void Jump()
{
//if(isGrounded == true)
if (currentJumpCount > 0)
{
//jumpForce의 크기만큼 윗쪽 방향으로 속력 설정
rigid2D.velocity = Vector2.up * jumpForce;
//점프 횟수 1 감소
currentJumpCount--;
}
}
}
위에 코드에서 maxJumpCount 변수의 값으로 2번이라 했기 때문에 최대 점프 값이 2번임을 알 수 있다.
오브젝트 마찰력 설정
위에 게임들을 실행하였을 때 마찰력에 의해 벽면에 플레이어가 붙어 버린다. 이것을 조작하려면 프로젝트 뷰에서 physics Meterial 2D를 설정하면 된다.