본문 바로가기

유니티

유니티 04.04 3인칭 캐릭터 이동 구현해보기 (Blend Tree)

Historic environment | 3D Historic | Unity Asset Store

 

Historic environment | 3D 역사적 건조물 | Unity Asset Store

Elevate your workflow with the Historic environment asset from VK GameDev. Find this & other 역사적 건조물 options on the Unity Asset Store.

assetstore.unity.com

Stylize Sand Pillar | 3D Exterior | Unity Asset Store

 

Stylize Sand Pillar | 3D 외부소품 | Unity Asset Store

Elevate your workflow with the Stylize Sand Pillar asset from LowlyPoly. Find this & other 외부소품 options on the Unity Asset Store.

assetstore.unity.com

2가지 무료 에셋을 사용하여 실습 했습니다.

 

두 에셋은 Project 창에서 Models 폴더를 따로 생성해서 넣어두었습니다.

 

https://www.mixamo.com/#/

 

Mixamo

 

www.mixamo.com

mixamo에서 마음에 드는 캐릭터에셋을 가져옵니다. 무료로 사용할 수는 있지만 상용화 하면 안된다고 합니다.

저는 당연히 학습용으로 사용할 것이기 때문에 마음에 드는걸로 가져왔습니다.

 

설치 할 때는 포맷을 FBX for Unity로 설정합니다.

그외 설정은 위와 같이 했습니다.

 

나머지 이동에 관련된 애니메이션을 찾아서 가져왔습니다.

idle모션, walk front/back , walk right/left, sprint 까지 가져와서 프로젝트 창으로 넣었습니다.

 

Hierachy에서 Plane(평면)  오브젝트를 아래와 같이 생성 했습니다.

Materials 폴더를 생성하고, 그안에 Floor_M이라는 바닥용 Material 을 생성.

Shader는 Movile/Difuse 로 설정

Assets/Models/Sand Pillar/Textures/stone_floor.png

경로에 있는 stone을 material 용 Texture로 선택 했습니다.

 

해당 Material을 Floor GameObject로 적용

'Floor'의 Material 컴포넌트를 확장해 보면 이렇게 생겼습니다.

Tiling은 물체 전체 크기에 적용할 Material의 무늬를 몇번 반복시킬지 정합니다.

XY는 당연히 방향을 이야기 하고

각각 1,1로 설정한다면 패턴이 1번 나오는 크기로 설정 됩니다.

1,1로 설정한 모습

2,2로 설정한 모습, 이렇게 하면 타일이 축소되어서 총4장이 표현 되네요

10,10으로 표현하자면 이렇습니다.

 

Offset은 사전에 보면 상쇄하다라는 뜻이 있는데 한번 클릭한 상태로 좌우로 드래그해서 밀어보면

마치 대형쇼핑몰에서 계산대에 컨베이어벨트가 밀리듯이 밀려 움직이는 것을 볼 수 있습니다.

offset값을 조정해본 모습

이렇게 밀어내는것으로 어디서 부터 무늬를 시작할 지 정할 수가 있었네요.

 

보통 offset이라는 말은 문서를 인쇄하거나 할 때 보게 되는데

페이지의 공백을 얼마만큼 설정하고 어디부터 자료가 출력되게 할지, 이럴때 보통 쓰더라구요

저는 그래서 여백이나 공백같은 뜻이 있는줄 알았는데 상쇄하다라는 뜻이 있었네요.

 

이제 바닥은 끝

 

가져온 캐릭터 FBX파일을 바닥에 놓습니다.

 

처음 가져온 캐릭터는 mapping이 되어있지 않아서 흰색 마네킹 같은 모습인데요.

 

Material 항목에서 Location 컴포넌트를 Use External Materials(Legacy)로 선택하면 제대로 맵핑이 완료되는걸 볼 수 있었습니다.

 

모델 Rig에 들어가서  Animation Type를 전부 Humanoid로 바꿉니다.

mixamo 에서 가져온 각각 모션별 애니메이션들도 마찬가지로 바꿔주고요

 

이동 관련된 애니메이션은 기본적으로 반복이기 때문에 Loop Time에는 체크 해주고

Root Transform 정보들이 기본 Generic에서 Humanoid로 바뀌면서 방향이 잘 맞지 않게 변경된다고 합니다.

따라서 Original / Feet / Original로 변경

Back into Pose도 전부 체크 해주었습니다.

 

Project 창에서 Animation 폴더를 생성하고 그안에 Animator Controller를 생성해줍니다.

생성한 Animator Controller는 캐릭터 GameObject에 Animator > Controller 항목에 넣어 주고요

 

처음 만들면 이런 모습이죠

Blen Tree를 생성해주었습니다.

선택해서 나오는 Parameters 에 +를 눌러서 float 형태로 추가 해줍니다.

이름은 위와 같이 지었습니다.

이렇게 Blend Tree 항목을 선택한 상태로(파란테두리 활성화 상태)

Inspector 창을 보면

모션들을 추가 할 수 있어요, 아, 먼저 Blend Type를 2D Simple Directional 로 설정해야 합니다.

Add Motion Field 선택

모두 추가 한 모습, Sprint를 제외하고 구성 했습니다.

Pos X Pos Y라고 되어있는건 일반적인 2차원 좌표계를 생각하면 이해가 편했습니다.

Blend Tree는 이런모습인데, 여기서 값을 직접 줘보면서 움직이는 모습도 우측 하단 미리보기에서 볼 수 있었습니다.

 

 

스크립트를 만들었어요.

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

public class MariaCtrl : MonoBehaviour
{
    
    [Header("마리아의 속도")]
    public float moveSpeed = 5f;
    public float TurnSpeed = 90f;

    private Transform tr;
    private float h, v, r;

    void Start()
    {
        tr = GetComponent<Transform>();
    }

    void Update()
    {
        h = Input.GetAxis("Horizontal");
        v = Input.GetAxis("Vertical");
        r = Input.GetAxis("Mouse X");   //마우스를 좌우로 움직일때

        Vector3 moveDir = (h * Vector3.right) + (v * Vector3.forward);
        tr.Translate(moveDir.normalized * Time.deltaTime * moveSpeed);  //normalize = 이동속도를 1로 만들어 줌
        tr.Rotate(Vector3.up * r * Time.deltaTime * TurnSpeed);
        #region 애니메이션 연동

        #endregion
    }
}

 

Input은 Unity에서 클래스로 제공되는데, GetAxis라는 함수가 매개변수로 문자열을 전달 받습니다.

이 문자열이 어떤 문자열들이냐?

상단 메뉴를 보면

Project Settings...로 들어가봅니다.

Input Manager라는 항목이 있어요.

토글버튼을 확장해서 보면

Horizontal 이라는 문자열이 어떤 속성을 가지고 있는지 볼 수 있습니다.

즉, Input.GetAxis("Horizontal"); 이 의미하는 바는 위의 속성을 가진다고 볼 수 있습니다.

다른 Input.GetAxis들도 마찬가지

 

 

Translate() 함수와 Rotate()함수도 자주 쓰니까 정의를 할 필요가 있을것 같아요.

정의를 하려고 좀 찾아봤는데 아직 Vector3에 대해 제대로 개념이 잡히지 않아서 미루기로 했습니다.

 

어쨌든 Rotate함수에서 매개변수로 Vector3 자료형 1개를 전달 받고 있습니다.

 

그리고 처음 언급된Vector3.up은 어떤 축을 회전 시킬 것인지를 이야기 하고 있습니다.

 

X 축을 움직이고 싶은데 왜 Y축과 연관된 Vector3.up이 나오는것일까? 

처음 이 코드를 접했을 때는 이해하기가 힘들었는데요

Vector3.up의 형태가 position 정보로 (0,1,0)을 의미 하고 있기 때문에 이는 일반적인 3차원 좌표계에서  Y축을 의미합니다.

3차원 공간에서 Y축을 회전시키는 것은 곳 X축이 향하는 곳이 계속 바뀐다는 이야기입니다.

 

 

단체로 술을 좀 마셔본 분들은 술게임을 여러개 알고 계실텐데요.

뭐 한 5명이 원을 그리고 둘러앉아서 술게임을 한다고 칠게요.

소주병을 가운데에 놓고 돌려서 멈춘 시점에 소주병이 가리키는 사람에게 장기자랑을 시키는거예요(가혹한 게임입니다.)

우리가 소주병을 돌리는 행위는 X축이 바라보는 방향을 바꾸는 행위죠? X축의 방향이 계속 바뀌어 주어야만

마지막에 누구를 가리키게 될지 알 수 없게 되는거잖아요.

여기서 회전 축이되는건 Y축이예요 Y축을 회전시키는 방법으로 X축이 바라보는 방향을 계속 바꾸게 됩니다.

 

X축의 '방향을 변경' 하기 위해서는 Y축을 회전시켜야 하는겁니다.

 

방향 변경과 회전을 따로 분리해서 생각해야 이해하기가 편해요.

 

저는 지금 X축의 방향을 변경하기 위해 Y축을 회전 시킬 겁니다.

r = Input.GetAxis("Mouse X");   //마우스를 좌우로 움직일때 마다 r의 값이 변한다. -1 에서 1까지 변한다.

r 은 X축의 방향을 결정하게 하고 싶은 파라미터죠. 저는 그것을 마우스 X축 움직임으로 결정하게 하고싶습니다.

tr.Rotate(Vector3.up * r * Time.deltaTime * TurnSpeed); // Y축을 회전시킨다. r만큼 회전 시키고, 시간과 속도에 비례해서 더 많이 회전 시킬 거다.

이렇게 해서 r(X축 마우스 이동)로 Y축을 회전시키는 코드를 만들었어요.

 

 

Vector3 moveDir = (h * Vector3.right) + (v * Vector3.forward);

 

빨간색이 x축, 파란색이 z축입니다.

이동방향을 결정짓는 변수인데, 변수를 초기화 하는데에 조금 오류가 있어요.

좌이동은 (-1, 0, 0) 우이동은 (+1, 0, 0)

하이동은 (0, 0, -1)  상이동은 (0, 0, +1)로 처리 되는데

덧셈연산자로 처리가 되죠

만약 대각선으로 이동하게 되면

우상단 이동이라고 가정 하겠습니다.

(+1, 0, +1)  이동이 되겠죠.

 

y축 x축 둘다 1만큼 이동하면 대각선 이동은 이등변 삼각형이 그려지기 때문에

피타고라스 정리에 따라서 대각선 길이는 √2 가 됩니다. 

 

a²+b² = c² 어휴 기억이 가물가물 하네요.

 

대충 루트2가 1.4 어쩌고 였으니까

대각선으로는 1.4 속도로 이동하게 되는거예요.

 

이를 해결하기 위해 바로 다음행에 이런 코드가 등장합니다.

tr.Translate(moveDir.normalized * Time.deltaTime * moveSpeed); //normalize = 이동속도를 1로 만들어 줌

MoveDir 변수에 점연산자normalized를 붙여서 백터를 1로 정규화 시켜 준 것이예요.

 

https://docs.unity3d.com/ScriptReference/Vector3-normalized.html

 

Unity - Scripting API: Vector3.normalized

When normalized, a vector keeps the same direction but its length is 1.0. Note that the current vector is unchanged and a new normalized vector is returned. If you want to normalize the current vector, use Normalize function. If the vector is too small to

docs.unity3d.com

메뉴얼 첫번째 문장에

Returns this vector with a magnitude of 1 (Read Only).

떡하니 써져 있어서 좋았습니다.

 

그렇게 1로 정규화된 백터값으로, 대각선 이동속도도 균일하게 설정 해준것 까지 오늘 진행했습니다.

'유니티' 카테고리의 다른 글

유니티 10 sky  (0) 2023.02.03
유니티 09 조명  (0) 2023.02.03
유니티 08 FBX파일  (0) 2023.02.02
유니티 07 Terrain  (0) 2023.01.31
유니티 06 Asset Store  (0) 2023.01.31