Patrick's Devlog

[Unity Project] 메인 캐릭터 이동 본문

Project/Unity Engine

[Unity Project] 메인 캐릭터 이동

Patrick_ 2022. 7. 5. 16:33

개요

간단한 3D RPG 게임을 제작 중에 있다. 막히는 부분이나 정리해야 할 부분은 모두 블로그에 작성할 예정이다. 이번 글에서는 메인 캐릭터의 간단한 움직임을 구현해보았다. 


우선 메인 캐릭터는 Asset Store에서 가져왔다. https://assetstore.unity.com/packages/3d/characters/humanoids/rpg-tiny-hero-duo-pbr-225148 의 링크를 타고가면 사용하고 있는 메인 캐릭터의 에셋을 확인할 수 있다. 

애셋 스토어 무료 RPG 캐릭터

우선은 오른쪽의 여자 캐릭터로 예시를 들고자 한다. 

 

Unity 화면에서 기본 씬에서 Plane과 위의 캐릭터를 등록한다. 

위치는 모두 기본인 0으로 바꾸어주었으며, 메인 카메라를 메인 캐릭터에 넣어 조절한 상태이다. 메인 캐릭터와 바닥을 생성하였으면, 메인 캐릭터에 들어갈 스크립트를 생성해준다. 참고로 여기서 메인 캐릭터에 RigidBody와 Collider까지 넣어주었다. 스크립트 생성이나, Object를 생성하는 기초적인 부분까지는 따로 언급하지 않을 예정이다. 

 

public class MainPlayer : MonoBehaviour
{
    public float charSpeed = 5.0f, jumpHeight = 3.0f; // 캐릭터 속도 및 점프 높이
    private float h, v;
    private Animator animator; // 애니메이션 설정
    private Rigidbody rb;
    private Vector3 moveVector;
    
    ...
}

우선 쓰일 인자들을 정리해준다. charSpeed와 jumpHeight은 Unity 인스펙터 화면에서도 변경할 수 있게끔 하기 위해 public으로 지정하였다. 나머지는 굳이 변경이 필요없는 부분이므로, private를 통해 밖에서는 확인하지 못하게 하였다. 

 

    void Start()
    {
        rb = GetComponent<Rigidbody>();
        animator = GetComponentInChildren<Animator>();
    }

    // Update is called once per frame
    void Update()
    {
        
    }

    private void FixedUpdate() // 이동 관련 함수는 FixedUpdate가 효율이 더 좋다고 함
    {
        Move();
        Jump();
        
    }

MainPlayer 안의 들어있는 함수들이다. 우선 Start에서 RigidBody와 animator의 컴포넌트를 가져온다. 그리고 Update() 함수에서 주기적으로 갱신하는 것이 아닌, FixedUpdate()를 통해 주기적으로 갱신한다. FixedUpdate는 물리적인 부분을 조금 더 중점적으로 다루므로 움직임을 적용할 때 효율이 더 좋다. 이제 이동에 필요한 Move()와 Jump()를 구현한다. 

 

    void Move()
    {
        h = Input.GetAxis("Horizontal"); // 세로축
        v = Input.GetAxis("Vertical"); // 가로축

        moveVector = new Vector3 (h, 0, v).normalized;
        transform.position += moveVector * charSpeed * Time.deltaTime; // 이동 좌표 변경
        animator.SetBool("isWalk", moveVector != Vector3.zero); // 애니메이션 세팅
    }

    void Jump()
    {
        if (Input.GetKey(KeyCode.Space))
        {
            // rigidBody에 힘을 가하는 함수
            // 인자는 차례대로 방향, 힘을 어떤식으로 가할 것인지 표시
            rb.AddForce(Vector3.up * jumpHeight, ForceMode.Impulse);
            animator.SetTrigger("Jump");
        }
    }

Move()에서 GetAxis를 통해 각각의 축들의 범위 값을 가져올 수 있도록한다. GetAxis는 -1.0f에서 1.0f까지 범위를 반환하고, GetAxisRaw를 사용하게 될 경우 -1, 0, 1중 하나를 반환한다. 조금 더 부드러운 움직임을 주기 위해서는 GetAxis가 적합하다. new Vector3을 통해 새로운 위치를 설정한다. 후에 캐릭터의 속도와 deltaTime을 곱해주어 갱신한다. 여기서 deltaTime은 각 컴퓨터마다 처리 속도가 다르므로 프레임당 처리속도를 설정해 모든 컴퓨터에서 처리하는 속도가 동일하도록 보정해주는 역할을 한다. 

 

다음 Jump()에서 스페이스바를 입력하면 if문 안의 내용이 실행되게끔 하였다. 그리고 위의 코드에서 설명했듯이 rigidBody에 힘을 가하여 위로 올라가게끔 AddForce를 통해 구현하였다. AddForce의 두 번째 인자는 힘의 종류라고 생각하면 되는데, 총 네가지의 종류가 존재한다

 - 연속적인 힘 : 자동차 엑셀을 밟아 가속을 넣듯 가속도를 추가해주는 방식이다. 이미 진행되고 있는 것에 사용하기 적합하다. 무게를 적용하려면 ForceMode.Force, 무게를 무시하려면 ForceMode.Acceleration를 사용한다.

 - 순간적인 힘 : 마치 뒤에서 누가 밀듯이 순간적으로 속도를 붙여주는 방식이다. 정지 상태에서 이동을 시작할 때 적합하다. 무게를 적용하려면 ForceMode.Impulse, 무게를 무시하려면 ForceMode.VelocityChange를 사용한다.

 

코드를 다 작성하였으면 애니메이션을 설정한다. Unity의 Animator Controller를 하나 생성해주고, 각각의 행동들을 연결해주고 파라미터들도 설정해주었다. 

애니메이터와 안에 존재하는 파라미터

Entry에서 기본적으로 서있는 Idle를 연결해주었다. isWalk는 bool 타입이고, Jump는 Trigger 타입이다. 여기서 Move를 Idle와 각각 연결하여, Idle -> Move일 때는 isWalk가 true, Move -> Idle일 때는 isWalk를 false로 설정해주었다. 

여기서 Any State는 현재 머물고 있는 State와 상관없이 조건이 충족되면 상태가 발생되는 것이다. 따라서, 스페이스를 선택하면 Trigger를 일으켜 점프를 하게끔 한다. 

아마 프로그래밍을 하시는 분들은 bool 타입은 이미 다 알것이라 생각한다. 하지만 Unity를 잘 건들이지 못한 사람한텐 Trigger가 매우 생소할 것이라 예상한다. Trigger는 한번 실행되면 애니메이션이 종료된 후 다음 애니메이션으로 전환되는 것이다. 말그대로, 방아쇠를 한번 쏘고나면 끝이라는 소리이다. 여기서, 이렇게 애니메이션을 설정해도 움직일 때 애니메이션이 나오지 않는 경우가 있다. 화살표를 선택하면 Has Exit Time이 체크가 되어있을텐데, 이를 풀어줘야 빠르게 애니메이션을 전환할 수 있다. 

화살표 Inspector

이러면 캐릭터 이동의 준비가 모두 끝난다. 아래의 결과물을 한번 살펴보자.

캐릭터 이동의 결과물


이미 예전에 구현했던 부분이라, 조금 더 수월하게 끝낼 수 있다고 생각했었다. 하지만, 애니메이션과 점프 등 결합하려니 살짝 애를 먹었다. 그래도 무사히 구현을 끝마쳤다. 다음에는 카메라의 회전과 적을 해치우는 부분까지 해볼 예정이다. 

참고자료

https://mayquartet.tistory.com/43

 

[Unity] 캐릭터 이동

캐릭터가 움직일 수 있는 땅을 먼저 만들어줍시다. 땅의 재질은 Hierarchy에서 우클릭을 한 후 3D Object > Plane 으로 만들어줍니다. Plane을 생성하셨으면 Plain의 Inspector 창에서 Transform > Position을 0,..

mayquartet.tistory.com

https://asxpyn.tistory.com/39

 

[Unity] Player 방향키로 움직이기 / Animation 설정

Unity를 익히는 전공 수업인 3D스크립트프로그래밍의 팀 프로젝트로 진행한 KATNIP - Astro Cat에서 구현했던 것들을 정리해보려고 한다. Unity를 또 언제 쓸지는 모르지만 까먹기에는 아까운 프로젝트

asxpyn.tistory.com

https://docs.unity3d.com/kr/530/Manual/ExecutionOrder.html

 

이벤트 함수 실행 순서(Execution Order of Event Functions) - Unity 매뉴얼

Unity 이벤트 함수는 사전에 정해진 순서대로 실행됩니다. 실행 순서는 다음과 같습니다.

docs.unity3d.com

https://mayquartet.tistory.com/45

 

[Unity] 캐릭터 점프

이번에는 캐릭터의 점프를 구현해보겠습니다. 먼저 초기 코드입니다. using System.Collections; using System.Collections.Generic; using UnityEngine; public class Player : MonoBehaviour { public float Spe..

mayquartet.tistory.com