2D RPG – 1. 캐릭터 움직이기

https://www.youtube.com/channel/UC9w-j0OqNzdtOqiYj4lDHmg
유튜브 케이디님 강좌를 참고하였습니다.

1.준비

2D RPG 게임 제작을 진행해 보려고 합니다.
우선 캐릭터의 움직임을 넣어보겠습니다.
이미지는 스프라이트 형태의 이미지가 필요합니다.
스프라이트 이미지란 아래와 같이 움직이는 모양을 타일형태로 배치한것을 말합니다.
sprite

새로운 2D 프로젝트를 생성하고 [Assets] 안에 이미지,사운드,타일등 각종 요소를 넣고줍니다.
유니티 레이아웃도 작업하게 편하게 배치합니다.
위 스프라이트 이미지를 선택한뒤 좌측의 [Inspector] 창에서 옵션을 바꿔주도록 합니다.

[Sprite Mode] [Filter Mode] [Max Size] 등 이미지대로 바꿔준뒤 [Sprite Editor]로 들어갑니다.


위의 옵션대로 이미지를 슬라이스 해주면 자동으로 이미지가 나눠집니다.
나눠진 이미지를 클릭하여 제대로 슬라이스가 되었는지 확인합니다.

슬라이스 된 이미지중 처음 이미지를 [Scene] 화면에 올려놓으면 모든 준비가 끝납니다.

2.캐릭터 움직이기

첫단계는 애니메이션 없이 도트형태로 캐릭터가 움직이도록 작업을 진행합니다.
스크립트 파일을 하나 생성합니다.

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

public class MovingObject : MonoBehaviour
{
    public float speed;
    private Vector3 vector;

    public float runSpeed;
    private float applyRunSpeed;
    private bool applyRunFlag = false;

    public int walkCount;
    private int currentWalkCount;

    private bool canMove = true;

    // Start is called before the first frame update
    void Start()
    {

    }

    IEnumerator MoveCoroutine()
    {
        if (Input.GetKey(KeyCode.LeftShift))
        {
            applyRunSpeed = runSpeed;
            applyRunFlag = true;
        }
        else
        {
            applyRunSpeed = 0;
            applyRunFlag = false;
        }
        vector.Set(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical"), transform.position.z);

        while (currentWalkCount < walkCount)
        {
            if (vector.x != 0)
            {
                transform.Translate(vector.x * (speed + applyRunSpeed), 0, 0);
            }
            else if (vector.y != 0)
            {
                transform.Translate(0, vector.y * (speed + applyRunSpeed), 0);
            }

            if (applyRunFlag)
            {
                currentWalkCount++;
            }
            currentWalkCount++;
            yield return new WaitForSeconds(0.01f);
        }
        currentWalkCount = 0;
        canMove = true;

    }

    // Update is called once per frame
    void Update()
    {
        // 좌측 방향키면 -1, 우측 방향키면 1, 상측 방향키면 1, 하측 방향키면 -1
        // 버튼을 눌렀을 때 실행

        if (canMove)
        {
            if (Input.GetAxisRaw("Horizontal") != 0 || Input.GetAxisRaw("Vertical") != 0)
            {
                canMove = false;
                StartCoroutine(MoveCoroutine());
            }
        }
    }
}

전체소스는 위와 같습니다.
한 영역씩 나누어 살펴보겠습니다.

변수선언 부분

    public float speed; // 움직이는 속도 정의
    private Vector3 vector; // 움직이는 방향 정의

    public float runSpeed; // Shift키 입력시 증가하는 속도
    private float applyRunSpeed; // Shift키 입력시 연산되는 증가 속도
    private bool applyRunFlag = false; // Shift키 입력여부

    public int walkCount; // 방향키 입력시 이동값을 정하기 위한 값
    private int currentWalkCount; // 이동값 리셋을 위한 값

    private bool canMove = true; // 방향키 이동 반복실행 방지를 위한 값

코루틴 부분

    IEnumerator MoveCoroutine()
    {
        // Shift키 입력을 확인하여 스피드 값 할당, 입력 여부를 반환
        if (Input.GetKey(KeyCode.LeftShift))
        {
            applyRunSpeed = runSpeed;
            applyRunFlag = true;
        }
        else
        {
            applyRunSpeed = 0;
            applyRunFlag = false;
        }

        // 변수 vector의 값으로 입력한 방향키 값을 할당 -1 또는 1
        vector.Set(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical"), transform.position.z);

        // walkCount 값만큼 반복하여 객체 이동 walkCount(20) * speed(2.4) = 48px
        // 이동시 Shift키 입력여부 확인하여 Speed 값 추가(2.4)
        while (currentWalkCount < walkCount)
        {
            if (vector.x != 0)
            {
                transform.Translate(vector.x * (speed + applyRunSpeed), 0, 0);
            }
            else if (vector.y != 0)
            {
                transform.Translate(0, vector.y * (speed + applyRunSpeed), 0);
            }

            // Shift키 입력시 동시에 실행하여 +2씩 증가하는 효과
            if (applyRunFlag)
            {
                currentWalkCount++;
            }
            currentWalkCount++;

            // 0.01f의 대기시간을 가지고 while문을 반복
            yield return new WaitForSeconds(0.01f);
        }

        // 변수 리셋
        currentWalkCount = 0;
        canMove = true;

    }

코루틴은 프레임과 상관없이 특정시간동안 작업을 수행할 수 있게 해줍니다.
예를 들자면 게임내의 버프효과를 들 수 있습니다.
update() 문에서 버프효과 여부 및 지속시간을 체크해야하지만 코루틴에서는 버프 적용 -> 10초대기 -> 버프효과 종료 루틴으로 짤 수 있습니다.
다만 짤려는 기능에 따라서 성능이 달라질 수 있으니 확인이 필요합니다.

yield return new WaitForSeconds(0.01f);

위 구문으로 반복문을 반복할 때마다 0.01초씩 딜레이가 됩니다.
이는 컴퓨터의 속도로 인해 객체가 순간이동한 듯한 모션을 자연스럽게 움직이는 형태로 보여지게 해줍니다.

update 함수 부분

        // canMove 변수값에 따라서 작동
        if (canMove)
        {
            // 좌측 방향키면 -1, 우측 방향키면 1, 상측 방향키면 1, 하측 방향키면 -1           
            if (Input.GetAxisRaw("Horizontal") != 0 || Input.GetAxisRaw("Vertical") != 0)
            {
                canMove = false;
                // 코루틴 실행
                StartCoroutine(MoveCoroutine());
            }
        }

완성화면