이번 포스팅에서는 Animator 의 BlendTree 기능을 이용한 2D 캐릭터의 점프 애니메이션 구현 방법에 대해 알아보도록 하겠습니다. 본 포스팅은 아래의 포스팅에 이어서 작성하는 글입니다.
▶ 준비사항
에셋: SunnyLand 무료 에셋 (여기를 클릭해서 받으시면 됩니다.)
▶ 애니메이션
애니메이션과 관련된 내용은 간단하게 다른 포스팅에서 다룬 적이 있습니다. 이전 포스팅에서는 Animation 을 이용해 점프 구현을 위해 anim 파일 생성, 타임라인별 sprite 설정 및 position 값 변경을 다루었습니다. 여기서는 Asset Store 에서 다운로드 받은 에셋에 이미 포함되어 있는 animation 파일을 활용하는 법과 필요한 animation 을 만들어서 추가해 사용하는 법 모두 다루도록 하겠습니다.
▷ Player 객체에 Animation Controller 생성
- Player 객체를 선택하고 Inspector 창에서 [Add Component > Miscellaneous] 에 있는 Animator 를 추가합니다.
- Project 창에 있는 Assets 폴더에 AnimController 폴더를 생성합니다.
- AnimController 폴더 안에서 마우스 우클릭 [Create > Animator Controller] 를 선택하고 이름을 Player 로 변경합니다.
- 생성한 Player animator controller 를 Player 객체에 있는 Animator 의 Controller 항목에 드래그 해줍니다.
- 위 그림에서 밑에 있는 animator controller 인 Player 를 더블 클릭하면 아래와 같은 Animator 창이 나타납니다.
▷ Idle 애니메이션 만들기
Idle 애니메이션은 SunnyLand 에셋에 이미 포함되어 있기 때문에 여기서는 연결해서 사용하는 방법에 대해 알아보도록 하겠습니다.
- 우선 Project 창에서 경로 [Assets > SunnyLand Artwork > Sprites > player > idle] 로 이동합니다.
- Animator 창에서 마우스 우클릭 [Create State > Empty] 를 선택해 New State 를 생성하고 선택합니다.
- 아래의 그림과 같이 Project 창에 있는 idle-Animation 을 Inspector 창에 있는 Motion 에 연결하고 이름을 Idle 로 변경합니다.
여기까지 진행하시고 Play 버튼을 누르면 캐릭터와 꼬리가 살짝살짝 움직이는 애니메이션을 볼 수 있습니다.
▷ Run 애니메이션 만들기
Run animation 은 위에서 진행한 idle 과 똑같기 때문에 간략하게 설명하겠습니다.
- Project 창에서 경로 [Assets > SunnyLand Artwork > Sprites > player > run] 으로 이동합니다.
- Animator 창에서 마우스 우클릭 [Create State > Empty] 를 선택해 New State 를 생성하고 선택합니다.
- Project 창에 있는 run-Animation 을 Inspector 창에 있는 Motion 에 연결하고 이름을 Run 으로 변경합니다.
여기까지 진행하면 Animator 창에 다음과 같이 두 개의 State 가 생성되어 있을 것입니다.
캐릭터의 이동을 Rigidbody2D 를 이용해 하고 있기 때문에 캐릭터를 이동하면 rigidbody2d 의 속성인 velocity 의 x 값이 0 이 아닌 값이 되고 가만히 있으면 x 값이 0 이 됩니다. 이 특성을 이용해 가만히 있으면 Idle 애니메이션이 플레이되고 움직이면 Run 애니메이션이 플레이 되도록 만들어 보겠습니다.
▷ Run <-> Idle 애니메이션 사이의 Transition 만들기
- 우선 위 이미지와 같이 Parameters 탭을 클릭 하고 아래 테두리 + 부분을 클릭하면 나오는 팝업창에서 Float 을 선택합니다. 생성된 파라미터의 이름을 New Float 에서 MoveSpeed 로 변경합니다.
- Idle 을 선택하고 마우스 우클릭 [Make Transition] 을 선택한 다음 Run 을 선택합니다.
- Run 을 선택하고 마우스 우클릭 [Make Transition] 을 선택한 다음 Idle 을 선택합니다.
- 우선 Idle -> Run Transition 을 다음과 같이 설정해 줍니다.
- 위 그림의 왼쪽 테두리에 있는 Idle -> Run 방향의 화살표를 클릭합니다.
- Inspector 창에 나타나는 속성을 위의 그림과 같이 설정해 줍니다.
- Has Exit Time 체크 해제
- Transition Duration 0 으로 변경
- Conditions 에서 + 클릭 후 위의 그림과 같이 설정
- 위 설정의 의미는 MoveSpeed 의 값이 0 보다 크면 Run 애니메이션으로 transition 한다는 의미입니다.
- Run -> Idle Transition 을 다음과 같이 설정합니다.
- 차이점은 MoveSpeed 의 조건 값이 Less 0.5 부분입니다. 이 의미는 MoveSpeed 의 값이 0.5 미만이면 Idle 애니메이션으로 transition 하라는 의미입니다.
▷ BlendTree 를 이용한 Jump 애니메이션 만들기
- 우선 새 파라미터 2개를 생성합니다.
- Bool 타입의 IsGround
- Float 타입의 JumpBlend
- 이제 Player 객체를 선택하고 Animation 창에서 아래의 그림과 같이 붉은 테두리 부분을 클릭하고 [Create New Clip...] 을 선택합니다.
- 이름을 JumpUp.anim 으로 변경하고 저장합니다.
- Project 창에서 [Assets > SunnyLand Artwork > Sprites > player > jump] 에 있는 "player-jump-1" 를 Animation 창의 타임라인 0 에 드래그 합니다.
- 다시 위와 같은 방법으로 [Create New Clip...] 을 선택하고 이름을 JumpDown.anim 으로 저장합니다.
- Project 창에서 [Assets > SunnyLand Artwork > Sprites > player > jump] 에 있는 "player-fall" 를 Animation 창의 타임라인 0 에 드래그 합니다.
- Jump 를 선택하고 마우스 우클릭 [Create new BlendTree in State] 를 선택하고 Jump state 를 더블 클릭합니다.
- Blend Tree 를 선택하고 마우스 우클릭 [Add Motion] 을 2회 합니다.
- 다시 Animator 창으로 돌아와 마우스 우클릭 [Create State > Empty] 로 New State 를 만들고 이름을 Inspector 창에서 Jump 로 변경합니다.
- Jump 를 선택하고 마우스 우클릭 [Create new BlendTree in State] 를 선택하고 더블클릭합니다.
- Blend Tree 를 선택하고 마우스 우클릭 [Add Motion] 을 2회 합니다.
- 먼저 Inspector 창에서 Parameter 를 위의 그림과 같이 JumpBlend 로 변경합니다.
- 그림과 같이 animation 파일을 Motion 에 각각 드래그하여 설정해 줍니다.
- Automate Thresholds 를 체크 해제하고 Motion 에 있는 Threshold 를 -1, 1 로 설정합니다.
▷ Idle ↔ Jump 와 Run → Jump Transition 만들기
- 우선 Idle → Jump 의 설정을 다음과 같이 해줍니다.
- Jump → Idle transition 의 설정을 다음과 같이 해줍니다.
- Run → Jump transition 의 설정을 다음과 같이 해줍니다.
▶ Player 스크립트 수정
Player 스크립트를 다음과 같이 수정합니다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player : MonoBehaviour
{
Rigidbody2D rig;
Animator anim;
BoxCollider2D collider;
public float moveSpeed;
public float maxSpeed;
public float jumpPower;
// Start is called before the first frame update
void Start()
{
rig = GetComponent<Rigidbody2D>();
anim = GetComponent<Animator>();
collider = GetComponent<BoxCollider2D>();
}
// Update is called once per frame
void Update()
{
// 왼쪽 화살표를 누르고 있는 경우
if (Input.GetKey(KeyCode.LeftArrow))
{
// 물체에 왼쪽 방향으로 물리적 힘을 가해줍니다. 즉, 왼쪽으로 이동 시킵니다.
rig.AddForce(Vector2.left * moveSpeed, ForceMode2D.Impulse);
// velocity 는 물체의 속도입니다. 일정 속도에 도달하면 더 이상 빨라지지 않게합니다.
rig.velocity = new Vector2(Mathf.Max(rig.velocity.x, -maxSpeed), rig.velocity.y);
// scale 값을 이용해 캐릭터가 이동 방향을 바라보게 합니다.
transform.localScale = new Vector3(-1f, 1f, 1f);
}
else if (Input.GetKey(KeyCode.RightArrow)) // 오른쪽 화살표를 누르고 있는 경우
{
rig.AddForce(Vector2.right * moveSpeed, ForceMode2D.Impulse);
rig.velocity = new Vector2(Mathf.Min(rig.velocity.x, maxSpeed), rig.velocity.y);
transform.localScale = new Vector3(1f, 1f, 1f);
}
else if (Input.GetKeyUp(KeyCode.LeftArrow) || Input.GetKeyUp(KeyCode.RightArrow)) // 이동 키를 뗀 경우
{
// x 속도를 줄여 이동 방향으로 아주 살짝만 움직이고 거의 바로 멈추게 합니다.
rig.velocity = new Vector3(rig.velocity.normalized.x, rig.velocity.y);
}
// 스페이스바를 누르면 점프합니다.
if (Input.GetKeyDown(KeyCode.Space))
{
if (IsGrounded())
{
rig.AddForce(Vector2.up * jumpPower, ForceMode2D.Impulse);
}
}
var vel_norm = rig.velocity.normalized;
anim.SetBool("IsGround", vel_norm.y == 0);
// vel_norm.x 의 값은 왼쪽으로 가면 -1 로 오른쪽으로 가면 1 로 변화합니다.
// Animator 설정에서 Idle 상태에서 MoveSpeed 값이 0 보다 크면 Run
// Run 상태에서 MoveSpeed 값이 0.5 보다 작으면 Idle 로 Transtion 됩니다.
// 따라서 방향성을 없애기 위해 절대값을 취하는 것입니다.
anim.SetFloat("MoveSpeed", Mathf.Abs(vel_norm.x));
if (vel_norm.y != 0) anim.SetFloat("JumpBlend", rig.velocity.normalized.y);
}
// Ground 체크
bool IsGrounded()
{
// Collider 의 가로크기를 이용해 캐릭터의 발쪽에 Box 모양으로 충돌 체크를 합니다.
var ray = Physics2D.BoxCast(
collider.bounds.center,
new Vector2(collider.bounds.size.x, 0.2f),
0f,
Vector2.down,
0.35f,
1 << LayerMask.NameToLayer("Ground"));
Debug.Log(ray);
return ray.collider != null;
}
}
완성되었습니다. Play 하고 캐릭터를 움직이고 점프를 해보면 지금까지 설정한대로 애니메이션이 상태에 따라 나타나는 것을 볼 수 있습니다.
'게임 프로그래밍 > 유니티 활용' 카테고리의 다른 글
[유니티 활용] StateMachine 과 몬스터 AI (2) | 2022.12.26 |
---|---|
[유니티 활용] 부드러운 카메라 이동과 경계 값 설정 (0) | 2022.12.25 |
[유니티 활용] Platform Effector 2D 를 이용한 관통 플랫폼 만들기 (1) | 2022.12.22 |
[유니티 활용] Rigidbody2d 를 이용한 캐릭터의 이동과 점프 (4) | 2022.12.21 |
[유니티 활용] Xor 와 Base64Encoding 을 이용한 초 간단 암호화 및 복호화 (4) | 2022.12.20 |
댓글