본문 바로가기
C#

[C#][Unity] 캐릭터 회전 구현하기

by teamnova 2022. 1. 4.
728x90

https://stickode.tistory.com/319?category=937544 

위 링크(유닛 이동에 맞춰 카메라 따라가게 만들기)에 이어서 이번에는 캐릭터를 이동하는 방향에 맞게 회전시켜보도록 하겠습니다.

 

실행 환경

개발 툴: Unity 2019.4.21f1

IDE : vscode

 

캡슐은 회전해도 확인이 어려우니 캐릭터를 추가해보도록 하겠습니다.

지난 글에서 사용했던 에셋 스토어로 이동해서 캐릭터를 가져와보도록 하겠습니다.

왼쪽 위 Scene 오른쪽 탭인 Asset Store 를 선택하신 후 검색창에 Dog Knight PBR Polyart 를 검색해주세요.

 

다운로드 후 import를 선택해주세요.

Import 선택

 

끝나시면 Project 창에 DogKnight 폴더가 생성된걸 볼 수 있습니다.

 

캐릭터는 DogKnight 폴더 - Prefab 폴더에 들어있습니다.

Asset Store 창을 Scene 창으로 바꾸고 DogPolyart 파일을 Capsule 로 드래그 앤 드롭해줍니다.

 

다음으로 캡슐은 보기 안 좋으니 안보이게 만들겠습니다.

캡슐 선택 후 Inspector 창에 있는 MeshRenderer 컴포넌트에 있는 체크를 해제해줍니다.

 

한번 실행 후 이동해 보시면 캐릭터가 공중에 떠있는 것을 볼 수 있습니다.

 

게임을 종료하신 후 Capsule 아래에 있는 DogPolyart 오브젝트의 Position Y 값을 -1 로 바꾸도록 합니다.

 

다시 실행 후 이동해보시면 공중에 떠있지는 않는 것을 볼 수 있습니다.

 

이제 캐릭터를 뛰고 회전시켜보도록 하겠습니다.

먼저 캡슐의 자식 오브젝트인 DogPolyart 를 선택 후 Inpector 창을 보시면 Animator 가 있습니다.

( 유니티 Animator 설명 공식 홈페이지 :  https://docs.unity3d.com/kr/530/Manual/class-Animator.html )

그 중 Controller 에 DogControl 이라는 부분이 보이실텐데 더블 클릭해주세요.

그러면 Animator 설정 화면이 켜지는 것을 볼 수 있습니다.

Animator 설정 화면

 

Animator 설정 화면에서 오늘 사용할 동작은 Idel_Battle 과 RunForwardBattle 두가지입니다.

설정은 아래 오른쪽 화면과 같이 바꿔주세요. Idel_Battle 에서 RunForwardBattle 로 화살표를 추가하는 방법은 Idel_Battle 에서 우클릭 후 Make Transition 클릭, RunFrowardBattle 을 클릭하시면 됩니다. 삭제는 화살표를 클릭 후 키보드 Del를 누르시면 됩니다.

 

다음으로 화면 왼쪽 위에 Scene 아래쪽을 부시면 Layers 와 Parameters 탭이 보이실 겁니다. Parmeters 를 선택해주세요.

 

그리고 검색창 오른쪽에 있는 + 버튼을 누르고 Bool 을 선택해주세요.

이름은 isRun 으로 설정해주세요.

 

그 다음 Idel_Battle 에서 RunForwardBattle 로 가는 화살표를 클릭해주세요.

오른쪽 위 Inspector 창의 스크롤을 내려보시면 Conditions 부분이 있습니다. 거기서 + 버튼을 눌러주세요.

그럼 바로 isRun 이 추가된 것을 볼 수 있습니다.

마지막으로 Has Exit Time 체크를 해제해주세요.

다음으로 RunForwardBattle 에서 Idel_Battle 로 가는 화살표를 눌러주신 후 위와 같이 Conditions 에서 isRun 을 추가해주세요. isRun 의 값은 false 로 변경해주세요.

마지막으로 Has Exit Time 체크를 해제해주세요.

 

그 다음 Project 창에서 MyUnit 스크립트를 실행시켜주세요.

코드는 아래와 같이 만들어주세요.

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

public class MyUnit : MonoBehaviour
{
    public float speed;      // 캐릭터 움직임 스피드
    public CharacterController characterController; // 캐릭터 컨트롤러
    public Vector3 movePoint; // 이동 위치 저장
    public Camera mainCamera; // 메인 카메라
    public Vector3 cameraOffset; // 카메라 
    public Animator animator; // 애니메이터

    private Vector3 unitPlanePosition; // 유닛의 바닥 위치 ( 거리 계산할 때 사용 )

    void Start()
    {
        speed = 4.0f;
        mainCamera = Camera.main;
        characterController = GetComponent<CharacterController>();

        animator = GetComponentInChildren<Animator>();
    }
    
    void Update()
    {
    
        // 좌클릭 이벤트가 들어왔다면
        if (Input.GetMouseButtonUp(0))
        {
            // 카메라에서 레이저를 쏜다.
            Ray ray = mainCamera.ScreenPointToRay(Input.mousePosition);
            // Scence 에서 카메라에서 나오는 레이저 눈으로 확인하기
            Debug.DrawRay(ray.origin, ray.direction * 10f, Color.red, 1f);
    
            // 레이저가 뭔가에 맞았다면
            if (Physics.Raycast(ray, out RaycastHit raycastHit))
            {
                // 맞은 위치를 목적지로 저장
                movePoint = raycastHit.point;
                movePoint.y = 0;
                Debug.Log("movePoint : " + movePoint.ToString());
                Debug.Log("맞은 객체 : " + raycastHit.transform.name);
    
            }
        }

        unitPlanePosition.x = transform.position.x;
        unitPlanePosition.z = transform.position.z;
        // 목적지까지 거리가 0.5f 보다 멀다면
        if (Vector3.Distance(unitPlanePosition, movePoint) > 0.5f)
        {
            // 회전
            Rotation();
            // 이동
            Move();
        }else{

            // 멈춤
            Stop();
        }

        // 매 업데이트 메소드가 실행될 때마다 카메라의 위치를 오브젝트의 위치 + 카메라 오프셋의 위치로 바꾼다.
        mainCamera.transform.position = transform.position + cameraOffset;
    }
    
    void Move()
    {
        // thisUpdatePoint 는 이번 업데이트(프레임) 에서 이동할 포인트를 담는 변수다.
        // 이동할 방향(이동할 곳-현재 위치) 곱하기 속도를 해서 이동할 위치값을 계산한다.
        Vector3 thisUpdatePoint = (movePoint - transform.position).normalized * speed;
        // characterController 는 캐릭터 이동에 사용하는 컴포넌트다.
        // simpleMove 는 자동으로 중력을 계산해서 이동시켜주는 메소드다.
        // 값으로 이동할 포인트를 전달해주면 된다.
        characterController.SimpleMove(thisUpdatePoint);

        animator.SetBool("isRun",true);
    }

    void Stop(){
        animator.SetBool("isRun", false);
    }

    void Rotation()
    {
        Vector3 relativePosition = movePoint - transform.position;

        relativePosition.y = 0;

        Quaternion rotation = Quaternion.LookRotation(relativePosition, Vector3.up);

        transform.rotation = rotation;
    }
}

 

스틱코드를 사용하신다면 아래 링크로 이동해서 즐겨찾기 하신 후 MyUnity.cs 파일을 비우시고 'rotateCharcter' 자동완성을 실행해주세요.

https://stickode.com/detail.html?no=2706 

 

스틱코드

 

stickode.com

 

시연 영상 입니다.