Unity 상하좌우, 정지상태 이동 및 애니메이션 구현

Table of Contents

준비물

Assets

다운로드 링크
https://pixel-boy.itch.io/ninja-adventure-asset-pack

위 사이트에서 다운로드 받은 에셋 중 그린 닌자를 사용


스프라이트 추가

다운로드한 Assets을 드래그 앤 드랍으로 추가할 수 있음


스프라이트 설정

추가한 에셋 중 Walk를 선택하고, Sprite Mode를 multiple로 선택


그다음 Sprite Editor를 클릭 > Slice를 클릭 > Grid By Cell Size를 이미지처럼 설정 후 > Slice 클릭 > Apply 클릭



Walk_0 선택하고, Scene에 드래그 앤 드랍 또는 하이라키에 드래그 앤 드랍 그러면 이미지처럼 Scene 부분에 추가 됨 그리고 하이라키에서 Walk_0의 이름을 Player로 수정 Walk_0 선택 후 F2 누르면 이름 수정 가능


Player Sorting Layer 설정

위에서 추가한 Player를 클릭하면 Inspector창에서 Additional Settings 부분에 Sorting Layer가 있는데 Default로 되어 있음 Add Sorting Layer를 클릭


생성한 Sorting Layer로 값을 수정


패키지 설치

Cinemachine, Input System
Window > Package Manager


Package Manager > Pcakages: Unity Registry 선택 > 패키지 선택후 우측 Install 클릭


설치 후 유니티 재시작


Input Handling 수정

Edit > Project Settings > Player > Other Settings > Active Input Handling* > Both


PlayerActions 생성 및 작성

Input Actions는 Input System 패키지가 설치 되어야 생성할 수 있음


생성된 파일을 더블 클릭



Action Maps 생성, 왼쪽 Actions Maps에 +를 클릭, 더블클릭하면 속성의 이름을 변경할 수 있음


Action Properties > Actions Type > Value > Control Type > Vector 2 Actins > + 클릭 (Add Binding) > Add Up Down Left Right Composite


생성된 Up, Down, Left Right 키 설정 해주기 > 이미지처럼 원하는 Key를 검색 해서 추가하면 됨


설정하고 Actions 위에 Save Asset 클릭하면 저장


C# Class 생성

Player Actions 파일을 클릭하면 Inspector 부분에 Generate C# Class 체크 후 Apply


C# Script 파일 생성

스크립트 파일을 생성하고 이름을 PlayerMovement로 함

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

// 플레이어의 움직임과 애니메이션을 처리하는 스크립트
public class PlayerMovement : MonoBehaviour
{
    [Header("Config")]
    [SerializeField] private float speed; // 플레이어 이동 속도 설정

    // 플레이어 입력 액션과 컴포넌트 참조 변수
    private PlayerActions actions; // 새 입력 시스템을 통해 플레이어 입력을 처리
    private Rigidbody2D rb2D; // 2D 물리 이동을 처리하는 Rigidbody2D 참조
    private Animator animator; // 애니메이터 컴포넌트 참조
    private Vector2 moveDirection; // 플레이어의 이동 방향 벡터

    private void Awake()
    {
        // 컴포넌트 및 입력 액션 초기화
        actions = new PlayerActions(); // PlayerActions 생성 (새 입력 시스템 사용)
        rb2D = GetComponent<Rigidbody2D>(); // Rigidbody2D 컴포넌트 가져오기
    }

    // 매 프레임마다 호출되어 입력을 읽음
    private void Update()
    {
        ReadMovement(); // 이동 입력 처리 및 애니메이션 업데이트
    }

    // 고정된 시간 간격마다 호출되어 물리 이동을 처리
    private void FixedUpdate()
    {
        Move(); // 실제 이동 로직 실행
    }

    // Rigidbody2D를 사용해 플레이어 이동 처리
    private void Move()
    {
        // 현재 위치에서 이동 방향과 속도를 기반으로 새로운 위치로 이동
        rb2D.MovePosition(rb2D.position + moveDirection * (speed * Time.fixedDeltaTime));
    }

    // 입력 값을 읽어 이동 방향과 애니메이션 상태를 설정
    private void ReadMovement()
    {
        // 새 입력 시스템으로 이동 입력 값을 읽어 정규화된 벡터로 저장
        moveDirection = actions.Movement.Move.ReadValue<Vector2>().normalized;

        // 이동 방향이 (0, 0)인 경우 애니메이션 비활성화
        if (moveDirection == Vector2.zero)
        {
            return; // 추가 처리 중단
        }
    }

    // 오브젝트 활성화 시 입력 액션 활성화
    private void OnEnable()
    {
        actions.Enable(); // 입력 시스템 활성화
    }

    // 오브젝트 비활성화 시 입력 액션 비활성화
    private void OnDisable()
    {
        actions.Disable(); // 입력 시스템 비활성화
    }
}


Player 오브젝트에 Component 추가

위에서 작성한 PlayerMovement와 Rigidbody2D를 추가

RigidBody2D 옵션 수정
Gravity Scale > 0
Constratints > Freeze Rotation > Z 체크

PlayerMovement 옵션 수정
Speed > 5

Speed를 0으로 설정하면 당연히 이동하지 않음



상하좌우 애니메이션 추가하기

Animation 탭과 Animator 탭을 활성화
Window > Animation
Window > Animator


anim 파일 생성하기 Animation > Create

Walk_Down.anim 파일을 생성

Sprite Assets을 아래 이미지처럼 드래그하면 해서 프레임 0, 10, 20, 30, 40 5개를 추가
아래 이미지는 이해를 위해 Sprite가 보이게 편집한 이미지임


위 작업을 Left, Right, Up을 추가로 진행


다 진행후 Animator 탭을 보면 아래 이미지처럼 보임


일단 Walk_Down, Left, Right, Up을 제거, 드래그 후 마우스 우 클릭하면 제거할 수 있음


그 다음 Animator 탭에서 마우스 우클릭 후 Create State > From New Blend Tree


생성된 Blend Tree(위 이미지 주황색 버튼)를 더블 클릭하면 아래 이미지처럼 나옴


Parameters에는 기본 파라미터 Blend가 있는데 필요 없기 때문에 클릭하고 Delete버튼을 누르면 제거할 수 있음
그다음 + 를 클릭해 Float 자료형의 변수를 2개 생성


Blend Tree의 Inspector 수정

Blend Type > 2D Simple Directional
Parameters > MoveX, MoveY 아래 이미지처럼 수정


Motions 부분을 + 버튼을 클릭해서 Add Motion Field를 클릭해서 추가


생성 했었던 anim파일을 추가하고 방향을 설정


그다음 PlayerMovement Script 파일을 수정

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

// 플레이어의 움직임과 애니메이션을 처리하는 스크립트
public class PlayerMovement : MonoBehaviour
{
    [Header("Config")]
    [SerializeField] private float speed; // 플레이어 이동 속도 설정

    // 애니메이터 파라미터의 해시 값 생성
    private readonly int moveX = Animator.StringToHash("MoveX"); // x축 이동 값을 전달할 애니메이터 파라미터
    private readonly int moveY = Animator.StringToHash("MoveY"); // y축 이동 값을 전달할 애니메이터 파라미터
    private readonly int moving = Animator.StringToHash("Moving"); // 움직임 상태를 나타내는 애니메이터 파라미터

    // 플레이어 입력 액션과 컴포넌트 참조 변수
    private PlayerActions actions; // 새 입력 시스템을 통해 플레이어 입력을 처리
    private Rigidbody2D rb2D; // 2D 물리 이동을 처리하는 Rigidbody2D 참조
    private Animator animator; // 애니메이터 컴포넌트 참조
    private Vector2 moveDirection; // 플레이어의 이동 방향 벡터

    private void Awake()
    {
        // 컴포넌트 및 입력 액션 초기화
        actions = new PlayerActions(); // PlayerActions 생성 (새 입력 시스템 사용)
        animator = GetComponent<Animator>(); // 애니메이터 컴포넌트 가져오기
        rb2D = GetComponent<Rigidbody2D>(); // Rigidbody2D 컴포넌트 가져오기
    }

    // 매 프레임마다 호출되어 입력을 읽음
    private void Update()
    {
        ReadMovement(); // 이동 입력 처리 및 애니메이션 업데이트
    }

    // 고정된 시간 간격마다 호출되어 물리 이동을 처리
    private void FixedUpdate()
    {
        Move(); // 실제 이동 로직 실행
    }

    // Rigidbody2D를 사용해 플레이어 이동 처리
    private void Move()
    {
        // 현재 위치에서 이동 방향과 속도를 기반으로 새로운 위치로 이동
        rb2D.MovePosition(rb2D.position + moveDirection * (speed * Time.fixedDeltaTime));
    }

    // 입력 값을 읽어 이동 방향과 애니메이션 상태를 설정
    private void ReadMovement()
    {
        // 새 입력 시스템으로 이동 입력 값을 읽어 정규화된 벡터로 저장
        moveDirection = actions.Movement.Move.ReadValue<Vector2>().normalized;

        // 이동 방향이 (0, 0)인 경우 애니메이션 비활성화
        if (moveDirection == Vector2.zero)
        {
            animator.SetBool(moving, false); // 움직임 상태를 false로 설정
            return; // 추가 처리 중단
        }

        // 이동 중이라면 애니메이션 업데이트
        animator.SetBool(moving, true); // 움직임 상태를 true로 설정
        animator.SetFloat(moveX, moveDirection.x); // x축 이동 값을 애니메이터에 전달
        animator.SetFloat(moveY, moveDirection.y); // y축 이동 값을 애니메이터에 전달
    }

    // 오브젝트 활성화 시 입력 액션 활성화
    private void OnEnable()
    {
        actions.Enable(); // 입력 시스템 활성화
    }

    // 오브젝트 비활성화 시 입력 액션 비활성화
    private void OnDisable()
    {
        actions.Disable(); // 입력 시스템 비활성화
    }
}


이제 실행해보면 이동 모션이 잘 보이는 것을 확인할 수 있음, 하지만 정지 상태가 없어서 제자리에서도 계속 걷고 있는것처럼 보임


정지 애니메이션 추가하기

정지 Sprite multiple 설정


위에서 Sprite를 Slice했던 것처럼 정지상태 Sprite도 16, 16으로 Slice함


그다음 위에서 했던 거처럼 상하좌우 정지상태 애니메이션 추가
만약에 Animation탭을 클릭했는데 Anim생성 기능이 없으면 Player오브젝트를 선택


똑같이 기본으로 생성된 Blend Tree 지우고 상하좌우 애니메이션 Blend Tree를 복사 붙여넣기


복사한 Blend Tree에 Idle Animation 적용


Default State를 Idle Tree로 수정 Idle Tree에서 마우스 우클릭 후 Set as Layer Defalut State 클릭


그다음 Parameters에서 Boolean형 Moving 파라미터를 추가


Idle Tree와 Blend Tree를 Make Transition으로 연결 Make Transition은 Tree에서 마우스 우클릭하면 있음


연결된 선을 클릭하고 Inspector 수정 Idle > Blend


Blend > Idle


정지상태에 대한 스크립트는 상하좌우 이동할때 정지상태 또한 작성을 해서 추가로 작성할 필요 없음, 이제 실행해보면 이동키를 누르지 않았을 때는 정지상태로 있음


게임 개발 글은 어떻게 작성을 하는게 좋은지 연구가 필요할 거 같다…



Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x