UI 비법서 (7) 

Button 컴포넌트

 

작성 기준 버전 :: 2019.2

 

[이 포스트의 내용은 유튜브 영상으로도 시청하실 수 있습니다.]

 

아마 게임을 하면서 플레이어와 제일 많은 상호작용을 하는 UI 요소는 바로 버튼일 것이다. 버튼은 마우스의 클릭에 반응해서 지정해둔 기능을 동작하게 하는 UI이다. 이렇게 설명만 들어도 간단해보이는 Button 컴포넌트가 이렇게 영상까지 만들어서 이야기할 필요가 있을까 싶을 것이다.

 

버튼 게임 오브젝트 생성하기

 

하지만 이렇게 간단해보이는 Button 컴포넌트에도 유용하게 사용할 수 있는 팁들이 꽤 있다.

 

 

하이어라키 뷰에 우클릭하고 [UI > Button]을 선택하면 버튼 게임 오브젝트를 생성할 수 있다.

 

 

생성된 버튼 게임 오브젝트에는 Image 컴포넌트와 Button 컴포넌트가 부착되어 있는 것을 볼 수 있다. 거기에 기본적으로 버튼 게임 오브젝트 아래에는 버튼에 글자도 표시되게 Text 컴포넌트가 붙어있는 게임 오브젝트도 자식으로 있는 것을 알 수 있다. 이게 버튼의 제일 기본적인 상태이다.

 

Button 컴포넌트의 프로퍼티

 

그럼 Button 컴포넌트의 프로퍼티들을 하나씩 알아보도록 하자.

 

Interactable

 

첫 번째 프로퍼티는 Interactable이다. Interactable은 버튼이 상호작용 가능한지를 정하는 프로퍼티입니다.

 

 

먼저 Interactabla이 체크된 상태에서 클릭해보면 클릭할 때마다 버튼이 깜빡깜빡하며 버튼과 마우스 사이의 상호작용이 일어나고 있는 것을 확인할 수 있다.

 

 

Interactable을 끄면 먼저 버튼의 색깔이 약간 어두워지고 반투명해지는 것을 볼 수 있다. 그 상태에서 버튼을 클릭해보면 아까와는 다르게 상호작용하면서 발생하는 깜빡임이 나타나지 않는 것을 알 수 있다.

 

이 프로퍼티는 특정한 조건에 따라서 버튼을 활성화/비활성화 하는 기능으로 응용할 수 있다.

 

Transition

 

그다음 프로퍼티는 Transition이다. Transition은 버튼이 각 상호작용 상태에서 어떤 모습으로 보일 것인지를 결정한다.

 

 

버튼의 상호작용 상태로는 먼저 아무런 상호작용도 일어나고 있지 않은 Normal, 마우스가 버튼 위에서 호버링되고 있는 상태인 Highlighted, 버튼을 클릭하고 손을 떼지 않은 상태인 Pressed, 버튼에 클릭을 하고 손을 뗀 상태인 Selected, 버튼이 비활성화된 Disabled. 

 

이렇게 총 5가지가 있다.

 

그리고 선택 가능한 Transition의 종류로는 None, Color Tint, Sprite Swap, Animation이 있다.

 

None

 

None 타입의 트랜지션은 버튼과의 상호작용이 일어나도 아무런 표현을 하지 않는 타입이다.

 

Color Tint

 

버튼을 생성하면 기본 트랜지션으로 설정되는 Color Tint는 버튼에 상호작용을 했을 떄 상태변화를 생상으로 표현하는 것이다.

 

위에서 버튼을 클릭할 때마다 버튼이 깜빡깜빡하던 것을 기억할 것이다. 여기 Pressed를 보면 색깔이 약간 어두운 색으로 되어 있다. 이 Pressed에 설정된 색상이 버튼 이미지에 합쳐져서 버튼을 클릭할 때마다 깜빡거렸던 것이다.

 

Sprite Swap

 

Sprite Swap은 버튼의 상호작용 상태에 따라서 버튼 게임 오브젝트의 Image를 완전히 교체하는 방식이다.

 

 

Transition을 Sprite Swap으로 바꾸면 각 버튼 상호작용 상태에 따라서 색깔을 바꾸던 프로퍼티들이 스프라이트를 넣도록 바뀐 것을 볼 수 있다.

 

Sprite Swap 타입에서는 Normal 상태가 없는 것을 볼 수 있는데 Sprite Swap의 기본 상태는 버튼에 붙은 기본 이미지의 Image Source여서 바꿔넣을 필요가 없기 때문이다.

 

  

버튼 이미지에 기본 이미지를 넣고 Pressed에 버튼이 눌린 이미지를 넣으면 위의 그림과 같이 버튼이 눌리는 듯한 연출이 가능하다.

 

Animation

 

Animation 타입은 버튼의 색깔만 바뀌는 Color Tint나 이미지만 바뀌는 Sprite Swap에 비해서 좀 더 복잡하고 다양한 연출이 필요할 때 사용한다.

 

 

Animation 타입에서 Transition의 하위 프로퍼티는 각 상태에 맞는 이름으로 되어있는데 버튼 애니메이션에 추가될 스테이트와 파라미터의 이름을 지정하는 부분입니다. 이 부분은 따로 손댈 필요가 없다.

 

아래에 있는 Auto Generate Animation 버튼을 누르면 버튼에 대한 애니메이터 컨트롤러를 생성하는 대화상자가 뜬다. 여기서 애니메이터를 생성하면 하면 자동으로 버튼 게임 오브젝트에 애니메이터 컴포넌트가 추가되고 애니메이터에서 필요한 스테이트와 파라미터들이 자동으로 생성된다.

 

버튼 게임 오브젝트를 선택한 상태로 [Ctrl +6] 단축키를 누르면 애니메이션 뷰가 열리는데 개발자는 여기서 각 상태의 애니메이션 키만 잡아주면 된다.

 

 

  

이미지 하나를 버튼의 자식 게임 오브젝트로 만들고 버튼 위에 마우스를 올렸을 때, 이미지를 활성화 시키면서 360도 회전시키는 애니메이션을 만들어보자.

 

 

그 다음 플레이시킨 뒤 버튼에 마우스를 올려보면 버튼 앞에서 사각형이 나타나서 회전하는 것을 볼 수 있다.

 

이런 연출은 확실히 Color Tint나 Sprite Swap으로는 할 수 없는 연출이다. 일반적으로는 Color Tint나 Sprite Swap을 사용하지만 버튼과의 상호작용 연출에서 이런 다양한 연출을 사용하려면 Animation 타입의 Transition을 사용하는 것이 좋다.

 

Navigation

 

그 다음 프로퍼티인 Navigation은 모든 UI 컴포넌트에 있는 것으로 키보드나 패드로 UI를 선택할 때 어떤 순서로 포커스가 넘어갈 것인지를 결정하는 옵션dl다.

 

On Click 이벤트

 

 

On Click()은 버튼을 눌렀을 때 실행될 기능을 넣을 수 있는 On Click 이벤트 리스트이다.

 

public class ButtonTester : MonoBehaviour
{
    public void OnClickButton()
    {
        Debug.Log("Button Click!");
    }
}

 

On Click에 실행될 함수를 이벤트로 등록해주기 위해서는 스크립트에서 public으로 된 함수를 만들면 된다.

 

 

그리고 버튼에 스크립트로 작성한 컴포넌트를 추가하고 On Click 항목의 [+] 버튼을 누른 뒤 비어있는 오브젝트 란에 호출할 함수를 가진 컴포넌트를 넣어주고 호출해야할 함수를 선택해주면 된다.

 

이렇게 함수를 선택해주면 이 버튼이 클릭되었을 때, 이 함수가 실행되게 된다.

 

스크립트에서 On Click 이벤트 등록하기

 

버튼의 응용 기술로는 이렇게 에디터에서 고정으로 이벤트를 등록하지 않고 스크립트에서 동적으로 등록해주는 방법이 있다.

 

using UnityEngine.UI;

public class ButtonTester : MonoBehaviour
{
    Button button;

    public void OnClickButton()
    {
        Debug.Log("Button Click!");
    }

    void Start()
    {
        button = GetComponent<Button>();
        button.onClick.AddListener(OnClickButton);
    }
}

 

스크립트에서 Button 컴포넌트와 같은 UI의 기능을 사용하기 위해서는 UI 네임 스페이스를 using 선언해줘야 한다.

 

그 다음에는 Button 변수를 선언하고 Start 함수에서 GetComponent로 게임 오브젝트에 부착된 Button 컴포넌트를 가져온다. 그리고 button.onClick.AddListener에 함수를 넣어주면 이 함수가 이 버튼을 클릭했을 때 호출되는 이벤트로 등록된다.

 

게임을 플레이해보면 Button 컴포넌트의 On Click에서는 아무런 이벤트가 등록되지 않은 것처럼 보이지만 게임 뷰에서 버튼을 클릭해보면 스크립트에서 버튼의 이벤트로 등록해준 ButtonTester의 OnClickButton 함수가 정상적으로 호출되어 로그를 출력하는 것을 볼 수 있다.

 

버튼 터치 영역 키우기

 

모바일 기기에서 작은 버튼은 터치가 잘 안되거나 잘못 터치할 확률이 높다. 이런 문제를 해결하기 위해서 그냥 버튼의 크기를 키워버릴 수도 있지만 그렇게 하면 디자이너가 지정해준 전체적인 UI 레이아웃이 깨지게 될 것이다. 그러니 실제로 보이는 버튼의 크기는 키우지 않고 버튼의 터치 영역만 키워야 한다.

 

 

우선 버튼의 자식 컴포넌트로 이미지를 하나 추가하고 적당히 버튼을 덮도록 세팅한 다음 투명하게 만들어주면 된다.

 

 

그러면 눈에 보이는 버튼 이미지보다 바깥을 클릭해도 버튼이 무사히 동작하는 것을 볼 수 있다.

 

이것을 응용해서 버튼보다 작은 투명 이미지를 만들고 그 투명 이미지를 제외한 나머지의 Raycast Target을 끄는 방법으로 실제 버튼 이미지보다 작은 영역만 클릭 가능하게 만드는 것도 가능하다.

 

버튼 이미지보다 작은 영역에 터치를 받는 테크닉은 잘 사용되지 않을 것 같지만 버튼 이미지 리소스 외곽에 그림자나 글로우가 들어간 경우에 글로우 영역이나 그림자 영역을 제외하고 실제 버튼 영역에만 클릭을 받기 위해서 사용되는 경우가 종종 있다.

 

[유니티 어필리에이트 프로그램]

아래의 링크를 통해 에셋을 구매하시거나 유니티를 구독하시면 수익의 일부가 베르에게 수수료로 지급되어 채널의 운영에 도움이 됩니다.

 

에셋스토어

여러분의 작업에 필요한 베스트 에셋을 찾아보세요. 유니티 에셋스토어가 2D, 3D 모델, SDK, 템플릿, 툴 등 여러분의 콘텐츠 제작에 날개를 달아줄 다양한 에셋을 제공합니다.

assetstore.unity.com

 

Easy 2D, 3D, VR, & AR software for cross-platform development of games and mobile apps. - Unity Store

Have a 2D, 3D, VR, or AR project that needs cross-platform functionality? We can help. Take a look at the easy-to-use Unity Plus real-time dev platform!

store.unity.com

 

Create 2D & 3D Experiences With Unity's Game Engine | Unity Pro - Unity Store

Unity Pro software is a real-time 3D platform for teams who want to design cross-platform, 2D, 3D, VR, AR & mobile experiences with a full suite of advanced tools.

store.unity.com

[투네이션]

 

-

 

toon.at

[Patreon]

 

WER's GAME DEVELOP CHANNEL님이 Game making class videos 창작 중 | Patreon

WER's GAME DEVELOP CHANNEL의 후원자가 되어보세요. 아티스트와 크리에이터를 위한 세계 최대의 멤버십 플랫폼에서 멤버십 전용 콘텐츠와 체험을 즐길 수 있습니다.

www.patreon.com

[디스코드 채널]

 

Join the 베르의 게임 개발 채널 Discord Server!

Check out the 베르의 게임 개발 채널 community on Discord - hang out with 399 other members and enjoy free voice and text chat.

discord.com

 

반응형

Animation 

애니메이터 컨트롤러의 파라미터 조절하기

 

작성 기준 버전 :: 2019.2

 

[본 포스트는 유튜브 영상으로도 시청하실 수 있습니다]

 

이번 섹션에서는 애니메이터 컨트롤러의 파라미터를 스크립트에서 조절하는 방법을 알아보자.

 

그 이전에 유니티 애니메이션에 대한 기초적인 지식이 필요하다면 해당 링크를 통해서 확인할 수 있다.

 

애니메이션의 기초에 대해서 설명하는 튜토리얼을 통해서 애니메이터 파라미터로 애니메이터 컨트롤러의 흐름을 조절할 수 있다는 것을 이야기했었다.

 

우선 애니메이터 컨트롤러의 파라미터와 트랜지션에 대해서 간단하게 복습해보자.

 

애니메이터 컨트롤러의 파라미터와 트랜지션

 

유니티 애니메이션에 대한 기초를 다루었던 글에서 이야기 했듯이 애니메이터 컨트롤러의 트랜지션은 스테이트와 스테이트 사이를 이어주고, 어느 방향으로 애니메이션이 흘러갈지 결졍하는 것이고, 파라미터는 이 트랜지션이 실행될 조건을 결정하는 변수이다.

 

애니메이터 컨트롤러

 

 

우선 간단한 애니메이터 컨트롤러를 만들기 위해서 씬에 게임 오브젝트를 하나 생성해보자.

 

 

그리고 추가한 게임 오브젝트에 애니메이터 컴포넌트를 부착해준다.

 

 

그 다음 프로젝트 뷰에 우클릭해서 [Create > Animator Controller] 항목을 선택하여 새 애니메이터 컨트롤러를 생성해서 게임 오브젝트에 부착된 Animator 컴포넌트의 Controller 프로퍼티에 할당해주면 된다.

 

 

Controller 프로퍼티를 할당한 다음에는 게임 오브젝트를 선택한 상태에서 상단 메뉴바의 [Window > Animation > Animator] 항목을 선택해서 애니메이터 뷰를 열어보면 비어있는 게임 오브젝트의 애니메이터 컨트롤러를 볼 수 있다.

 

애니메이션 파라미터

 

 

애니메이터 뷰를 열었다면 뷰 제목 바로 아래 있는 파라미터 탭을 클릭한 다음, 플러스 모양의 버튼을 눌러서 위 이미지처럼 각 파라미터들을 하나씩 만들어 보자.

 

이 파라미터들은 앞서 언급했듯이 한 애니메이션에서 다른 애니메이션으로 전환되는 트랜지션이 실행되는 조건의 역할을 한다. 파라미터의 종류는 여기서 볼 수 있듯이 Float은 소수점을 나타내는 실수, Int는 정수, Bool은 참/거짓을 표현하는 논리 변수, Trigget는 신호가 들어오면 트랜지션을 통과시킨 다음에 자동으로 꺼지는 타입의 변수다.

 

애니메이터 트랜지션

 

 

각 파라미터 타입을 테스트하기 위해서 위 이미지와 같이 애니메이터 컨트롤러를 세팅해보자. 스테이트를 모두 만들고 트랜지션을 연결했다면, 트랜지션의 조건을 설정할 차례다.

 

Float in

 

 

먼저 Idle 스테이트에서 Float 스테이트로 들어가는 트랜지션의 조건이다. 트랜지션 화살표를 클릭하면 인스펙터 뷰에서 해당 트랜지션을 수정할 수 있는데, 컨디션(Conditions)의 플러스 버튼을 누르면 이 트랜지션이 동작할 조건을 추가할 수 있다. 우선 조건으로 사용될 변수는 New Float으로 하고 3보다 클 때(Greater), 동작하도록 설정했다.

 

Float out

 

 

그 다음은 Float에서 Idle로 빠져나오는 트랜지션의 조건이다. 컨디션을 추가한 다음, 원래 Greater라고 적혀있는 드롭다운 메뉴를 눌러보면 Less가 있는 것을 볼 수 있다. Less는 정해진 숫자보다 작을 때를 뜻한다. 즉, 3보다 작을 때 Float에서 빠져나가서 Idle로 향하게 된다.

 

참고로, 여기에 왜 같다를 의미하는 Equal이 없는지 궁금할 수도 있다. 이것은 컴퓨터의 고질적인 부동소수점 오차라는 문제 때문이다. 예를 들어 현실적으로는 0.0001을 만 번 더하면 정확히 1이 되어야 하는데, 컴퓨터는 소수점 계산에 문제가 있어서 정확히 1이 되지 않고 1.00001이나 다른 숫자가 되는 경우가 종종 발생한다. 이 때문에 소수점 계산에 정확히 같다라는 것을 사용하기 어렵기 때문에 Equal이 빠져있는 것이다.

 

Int in

 

 

Idle에서 Int로 들어가는 조건을 설정해보자. 컨디션을 추가한 다음 New Float이라는 변수 이름이 적혀있는 드롭다운 메뉴를 선택하면 애니메이터 컨트롤러에 만들어져 있는 파라미터를 찾아서 선택할 수 있다. 그리고 Int형 파라미터는 Float과 다르게 "같다(Equal)"라는 조건을 사용할 수 있다. 파라미터의 값이 1과 같을 때 Idle에서 Int로 들어가게 설정해보자.

 

Int out

 

 

New Int의 값이 1이 아닐 때, Int에서 Idle로 빠져나오게 만든다.

 

Bool in

 

 

Idle에서 Bool로 들어가는 조건은 New Bool이 true일 때로 설정한다. Bool형 파라미터는 true 혹은 false만 설정할 수 있다.

 

Bool out

 

 

New Bool이 false가 되면 Bool에서 Idle로 빠져나오게 만들어 준다.

 

Trigger in

 

 

Idle에서 Trigger로 들어가는 조건은 New Trigger로 넣어준다. 트리거 형식은 아까 이야기했듯이 트리거가 호출되는 순간에 한 번 켜지고, 트리거 조건이 있는 트랜지션을 통과하면 자동으로 꺼지기 때문에 별다른 세부 조건이 없다.

 

Trigger out

 

 

Trigger에서 Idle로 빠져나오는 조건은 따로 만들지 않는다. 참고로 트랜지션을 선택한 다음 볼 수 있는 인스펙터 뷰의 내용 중에서 Has Exit Timer이라는 옵션이 있는데 이 옵션이 켜져있으면 트랜지션의 조건 만족되더라도 지금 실행하는 애니메이션을 끝까지 재생하기 전에는 다음 스테이트로 넘어가지 않는다. 반대로 이 옵션을 꺼두면 지금 실행되는 애니메이션이 아직 재생이 끝나지 않았더라도 트랜지션의 조건이 만족되면 그 애니메이션을 끝내고 곧바로 다음 스테이트로 넘어가게 된다.

 

테스트 해보기

 

애니메이터 컨트롤러 설정이 모두 끝났다면 이제 플레이 버튼을 누르고 게임을 실행해보자.

 

 

그리고 애니메이터 뷰에서 파라미터의 값을 하나씩 변경하면서 테스트 해보자. 파라미터의 값에 따라서 애니메이션의 흐름이 통제되는 것을 확인할 수 있다.

 

스크립트로 애니메이터 파라미터 변경하기

 

다른 섹션에서 트랜스폼 컴포넌트를 다루면서도 이야기 했지만, 이렇게 에디터에서 값을 바꾸는 방법은 실제 게임 내에선 사용할 수 없으며, 게임에서 이 애니메이터 파라미터의 값을 바꿔서 애니메이션의 흐름을 통제하기 위해서는 스크립트에서 이 애니메이터 컨트롤러의 파라미터를 바꿀 수 있어야 한다.

 

public class AnimatorParameterPractice : MonoBehaviour

{

    private Animator animator;

 

    private void Awake()

    {

        animator = GetComponent<Animator>();

    }

}

 

우선 AnimatorParameterPractice라는 이름의 C# 스크립트를 하나 생성하고, animator 멤버 변수를 하나 만든 다음, 게임이 시작되자마자 애니메이터 컨트롤러를 가져올 수 있게 Awake() 함수에서 GetComponent() 함수를 사용해서 게임 오브젝트에 부착된 Animator 컴포넌트를 가져오자.

 

참고로 GetComponent() 함수를 사용하면 지금 이 컴포넌트가 부착되어 있는 게임 오브젝트에 부착된 다른 컴포넌트를 가져올 수 있다. 지금은 Animator 컴포넌트를 가져오기 위해서 뾰족 괄호 안에<> Animator 컴포넌트 클래스 이름을 넣었습니다.

 

애니메이터의 각 파라미터 값 변경 함수

 

애니메이터 클래스 내부에는 애니메이터 안에 설정한 파라미터 값을 변경할 수 있는 함수를 제공한다.

 

Float형 변경하기

 

animator.SetFloat("New Float", 3.1f);

 

애니메이터의 Float형 파라미터의 값을 변경하려면 SetFloat() 함수를 사용하면 된다. 첫 번째 매개변수로 변경하고자 하는 파라미터의 이름을 넣고, 두 번째 매개변수에 값을 넣어준다.

 

Int형 파라미터 값 변경하기

 

animator.SetInteger("New Int"1);

 

Int형 파라미터의 값은 SetInteger() 함수로 변경할 수 있다.

 

Bool형 파라미터 값 변경하기

 

animator.SetBool("New Bool", true);

 

Bool형 파라미터 값은 SetBool() 함수로 변경할 수 있다.

 

Trigger형 파라미터 신호 주기

 

animator.SetTrigger("New Trigger");

 

Trigger형 파라미터는 SetTrigger() 함수를 사용하면 해당 파라미터의 신호가 켜진다.

 

키보드를 누르면 각 파라미터 값 바뀌게 하기

 

void Update()

{

    if (Input.GetKeyDown(KeyCode.F))

    {

        animator.SetFloat("New Float"3.1f);

    }

 

    if (Input.GetKeyUp(KeyCode.F))

    {

        animator.SetFloat("New Float"2.9f);

    }

 

    if (Input.GetKeyDown(KeyCode.I))

    {

        

animator.SetInteger("New Int"

1);

    }

 

    if (Input.GetKeyUp(KeyCode.I))

    {

        

animator.SetInteger("New Int"

, 0);

    }

 

    if (Input.GetKeyDown(KeyCode.B))

    {

        

animator.SetBool("New Bool"

true);

    }

 

    if (Input.GetKeyUp(KeyCode.B))

    {

        animator.SetBool("New Bool"

false

);

    }

 

    if (Input.GetKeyDown(KeyCode.T))

    {

        

animator.SetTrigger("New Trigger");

    }

}

 

AnimatorParameterPractice 클래스의 업데이트 함수에 위와 같은 코드를 작성해서 키보드를 눌렀다 뗄 때, 각 파라미터 값이 바뀌도록 해보자.

 

 

코드를 모두 작성했으면 코드를 저장하고 에디터로 돌아가서 애니메이터 컨트롤러가 붙어있는 게임 오브젝트에 AnimatorParameterPractice 컴포넌트를 부착한 뒤, 애니메이터 뷰를 켜고 플레이 버튼을 누른다. 

 

그리고 게임이 실행되면 지정한 키인 F, I, B T를 눌러보면 키보드를 눌렀다 뗄 때마다 파라미터의 값이 바뀌고 그에 따라 애니메이션의 흐름이 통제되는 것을 볼 수 있다.

 

[유니티 어필리에이트 프로그램]

아래의 링크를 통해 에셋을 구매하시거나 유니티를 구독하시면 수익의 일부가 베르에게 수수료로 지급되어 채널의 운영에 도움이 됩니다.

 

에셋스토어

여러분의 작업에 필요한 베스트 에셋을 찾아보세요. 유니티 에셋스토어가 2D, 3D 모델, SDK, 템플릿, 툴 등 여러분의 콘텐츠 제작에 날개를 달아줄 다양한 에셋을 제공합니다.

assetstore.unity.com

 

Easy 2D, 3D, VR, & AR software for cross-platform development of games and mobile apps. - Unity Store

Have a 2D, 3D, VR, or AR project that needs cross-platform functionality? We can help. Take a look at the easy-to-use Unity Plus real-time dev platform!

store.unity.com

 

Create 2D & 3D Experiences With Unity's Game Engine | Unity Pro - Unity Store

Unity Pro software is a real-time 3D platform for teams who want to design cross-platform, 2D, 3D, VR, AR & mobile experiences with a full suite of advanced tools.

store.unity.com

[투네이션]

 

-

 

toon.at

[Patreon]

 

WER's GAME DEVELOP CHANNEL님이 Game making class videos 창작 중 | Patreon

WER's GAME DEVELOP CHANNEL의 후원자가 되어보세요. 아티스트와 크리에이터를 위한 세계 최대의 멤버십 플랫폼에서 멤버십 전용 콘텐츠와 체험을 즐길 수 있습니다.

www.patreon.com

[디스코드 채널]

 

Join the 베르의 게임 개발 채널 Discord Server!

Check out the 베르의 게임 개발 채널 community on Discord - hang out with 399 other members and enjoy free voice and text chat.

discord.com

 

반응형

Tutorial (7)

 

애니메이션

 

작성 기준 버전 :: 2018.3.2f1

 

[튜토리얼의 내용을 유튜브 영상을 통해서도 확인하실 수 있습니다.]

 

게임에서 캐릭터가 어떠한 동작도 하지 않고 가만히 멈춘 채로 플레이어가 입력하는 대로 움직이가만 한다면 그 게임은 과연 어떤 느낌일까? 아마 그것은 굉장히 기괴한 모습이거나, 게임이 완성되지 못한 느낌일 것이다. 이렇듯이 애니메이션은 게임에 생동감을 불어넣는 중요한 요소이다.

 

메카님(Mecanim)

 

유니티에서 지원하는 애니메이션 시스템을 유니티 측에서는 메카님이라고 이름을 붙였다. 이 메카님 시스템은 기본적인 애니메이션 기능은 물론 애니메이션 레이어, 애니메이션 블렌드, 애니메이션 리타게팅 등의 다양한 기능을 제공한다. 애니메이션과 관련된 고급 기능들은 이후에 다른 섹션을 통해서 알아보도록 하고 이번 섹션에는 메카님 시스템의 기초적인 애니메이션 기능을 알아보도록 하자.

 

 

애니메이션 클립과 애니메이터 컨트롤러(Animation Clip & Animator Controller)

 

유니티의 애니메이션 시스템은 해당 오브젝트가 어떻게 움직여야 하는지에 대한 정보들이 포함된 애니메이션 클립과 플로우 차트와 같은 방식으로 애니메이션 클립들을 구조화하여 현재 어떤 클립이 재생되어야 하고 언제 애니메이션이 변경되어야 하는지 등을 추적하는 상태머신 형태의 애니메이터 컨트롤러로 이루어진다.

 

애니메이터 컨트롤러와 애니메이션 클립의 아이콘 형태는 다음과 같다.

 

 

애니메이션 클립을 만드는 방법은 크게 두 가지가 있다. 첫 번째는 3ds Max나 Maya 같은 외부의 프로그램으로 애니메이션을 만들어서 임포트 하는 것이고, 다른 하나는 유니티에서 직접 애니메이션 키를 잡아서 클립을 만드는 것이다.

 

3ds Max 같은 외부 프로그램에서 애니메이션을 만들어서 임포트하는 방식은 3D 모델링의 애니메이션을 만들고자 할 때 주로 사용하며 유니티 엔진에서 직접 키를 잡아서 애니메이션 클립을 만드는 것은 비교적 간단한 애니메이션이나 UI 애니메이션을 만들고자 할 때 사용하는 빈도가 높다.

 

 

외부에서 만든 애니메이션 임포트하기

 

Practice Animation.zip
다운로드

 

우선은 외부에서 만들어진 애니메이션을 임포트하는 방법을 배워보자. 연습용 애니메이션은 위의 첨부파일을 다운로드 받으면 된다. 다운 받은 압축파일의 압축을 해제하면 BoxMan@Run.FBX, BoxMan@Stand.FBX, BoxMan@Walk.FBX, BoxMan@Attack.FBX 네 개의 FBX 파일이 나올 것이다. 일반적으로 외부의 3D 모델링 프로그램을 통해 만들어진 애니메이션들은 FBX 확장자를 가진 것을 사용한다.

 

 

이렇게 받은 네 개의 파일을 유니티 엔진의 프로젝트 뷰로 드래그&드롭 한다. 그렇게 하면 네 개의 파일이 우리의 프로젝트에 포함되는 것을 확인할 수 있다.

 

 

임포트된 FBX 파일은 프로젝트 뷰에서 파란 직육면체에 종이가 붙은 아이콘으로 표현되며, 그 앞의 작은 삼각형을 클릭해서 접힌 부분을 열면 그 아래에 애니메이션 클립이 포함되어 있는 것을 확인할 수 있다.

 

 

이 FBX 파일을 선택한 상태로 인스펙터 창에서 애니메이션의 이름이나 길이, 반복 여부 등을 수정할 수 있다.

 

 

 

 

 

유니티 엔진에서 직접 애니메이션 클립 만들기

 

 

유니티 엔진에서 직접 애니메이션 클립을 만드는 방법을 배우기 위해서는 우선 씬에 애니메이션 클립을 만들 게임오브젝트 하나를 생성한다.

 

 

그리고 생성된 오브젝트를 선택한다. 

 

 

그 다음에 상단 메뉴바에서 Window>Animation>Animation을 선택하거나 Ctrl+6 단축키를 누르면 애니메이션을 수정할 수 있는 애니메이션 패널이 열린다.

 

 

아직 큐브에는 다른 애니메이션이 없기 때문에 애니메이션 클립을 생성하게 도와주는 Create 버튼만 보인다. 유니티 엔진에서 애니메이션 클립을 직접 만들기 위해서는 이 버튼을 사용하면 된다. 이 버튼을 클릭한다.

 

 

 

 

그러면 애니메이션 클립 생성 및 저장을 위한 대화상자가 뜨는데 CubeRotating.anim 이라는 이름으로 애니메이션 클립을 하나 생성하자.

 

 

애니메이션 클립이 생성되면 애니메이션 창에 타임라인이 표시된다.

 

  

이제 큐브가 회전하는 애니메이션을 추가하기 위해서 Add Property 버튼을 누르고 Transform 항목의 Rotation의 + 버튼을 눌러준다.

 

 

로테이션 프로퍼티가 추가되면 타임라인의 1초 지점을 클릭하고 Rotation.y 값을 360으로 설정한다.

 

 

그 다음 애니메이션 창의 재생 버튼을 눌러보면 화면에 배치된 큐브가 회전하는 것을 확인할 수 있다.

 

유니티 엔진에서 직접 만들어지는 애니메이션 클립은 대부분 이런 과정을 통해서 만들어지며 일반적으로 간단한 애니메이션이나 UI 애니메이션을 만들 때 사용되는 경우가 많다.

 

 

 

 

 

애니메이터 컨트롤러

 

애니메이션 클립에 대해서 설명했으니 이제 애니메이터 컨트롤러에 대해서 이야기할 차례이다. 앞서 이야기 했듯이 애니메이션 클립이 한 동작에 대한 애니메이션이라면 애니메이터 컨트롤러는 여러 애니메이션 클립을 모아서 오브젝트가 어느 시점에 어떤 애니메이션을 어떻게 재생할지 결정하는 역할을 한다.

 

  

애니메이터의 기본적인 구성요소는 스테이트(State), 트랜지션(Transition), 파라미터(Parameter) 이렇게 세 가지이다.

 

 

스테이트(State)

 

 

스테이트는 일반적으로 애니메이터에서 애니메이션 클립을 담고 있는 하나의 상태로, 지금 어느 애니메이션 클립이 재생되어야 하는가를 표현한다.

 

 

스테이트 중 하나를 클릭하여 선택하면 인스펙터 창에서 현재 선택된 스테이트의 정보를 확인하고 수정할 수 있다. 스테이트의 이름을 바꿀 수 있는 것은 물론이고 Motion 프로퍼티에는 현재 스테이트가 재생할 애니메이션 클립을 설정할 수 있고 Speed 프로퍼티를 통해서 애니메이션이 재생될 속도 역시 설정할 수 있다.

 

또한 위 예시 이미지에서 배치된 스테이트들은 애니메이터의 가장 기본적인 스테이트들로 스테이트당 하나의 애니메이션 클립을 담는다. 애니메이션 클립 하나를 담는 스테이트 이외에도 파라미터 값에 따라서 여러 애니메이션을 블랜딩해주는 블랜드 트리나, 여러 스테이트들을 담을 수 있는 서브-스테이트 머신이 있다. 추가적인 내용은 다른 파트에서 다루도록 하겠다.

 

특수한 스테이트

 

예시로 보여진 애니메이터 컨트롤러의 그래프를 보면 일반적인 노드는 회색의 사각형으로 표시되고 있는데, 그 외에 특별한 형태의 노드를 볼 수 있다. 

 

 

첫 번째는 엔트리(Entry)다. 엔트리는 애니메이션이 처음 시작될 때의 진입점을 의미한다.

 

 

이 엔트리에서 제일 처음으로 연결된 노드는 주황색으로 표시되며, 게임오브젝트가 활성화되어 애니메이션이 시작되면 이 주황색으로 표시된 애니메이션부터 재생이 시작된다.

 

 

노드를 기본 스테이트로 만들기 위해서는 기본 스테이트로 만들고자 하는 노드를 우클릭하고 [Set as Layer Default State] 항목을 선택하면 된다.

 

 

두 번째는 모든 스테이트(Any State) 노드이다. 이 노드는 애니메이터가 어떤 애니메이션을 재생하고 있는 상태이던 간에 트랜지션의 조건이 만족되면 무조건 다음 스테이트로 넘어가서 애니메이션을 재생하게 만든다.

 

예를 들어 캐릭터가 걷는 중이든, 가만히 서있는 중이든, 아니면 포션을 마시는 중이었든, 큰 데미지를 입어서 죽으면, 바로 Die 스테이트로 넘어가도록 하는 것이다.

 

 

마지막으로 엑시트(Exit) 노드이다. 엑시트 노드는 애니메이터의 흐름이 한 번 끝났음을 의미하고, 엑시트 노드를 통과하면 엔트리 노드로부터 다시 애니메이터의 흐름이 다시 시작된다.

 

 

파라미터(Parameter)

 

 

애니메이터의 파라미터는 한 애니메이션에서 다른 애니메이션으로 전환되는 조건이 되는 변수의 역할을 한다. Parameters에서 + 버튼을 누르면 추가할 파라미터의 종류를 선택할 수 있다. 파라미터의 종류로는 Float, Int, Bool, Trigger가 있으며 Float는 소수점을 나타낼 수 있는 실수, Int는 정수, Bool는 참/거짓을 표현하는 논리 변수이며, Trigger는 Set되면 True가 되고 해당 Trigger가 걸린 트랜지션을 통과하면 자동으로 False로 바뀌는 타입이다.

 

 

트랜지션(Transition)

 

 

트랜지션은 애니메이터에서 스테이트와 스테이트 사이를 이어주는 것이다. 스테이트 사이를 이어줄 때, 애니메이션이 어느 방향으로 흘러갈지 방향을 정할 수 있다. 그 외에도 트랜지션을 선택하면 인스펙터 창을 통해서 선택된 트랜지션이 실행될 조건이나, 한 스테이트에서 다른 스테이트로 넘어갈 때 애니메이션을 어떻게 블랜딩해줄 것인지 등을 설정할 수 있다.

 


 

이 외의 애니메이션과 관련된 포스트는 애니메이션 카테고리에서 확인할 수 있다.

 

[유니티 어필리에이트 프로그램]

아래의 링크를 통해 에셋을 구매하시거나 유니티를 구독하시면 수익의 일부가 베르에게 수수료로 지급되어 채널의 운영에 도움이 됩니다.

 

에셋스토어

여러분의 작업에 필요한 베스트 에셋을 찾아보세요. 유니티 에셋스토어가 2D, 3D 모델, SDK, 템플릿, 툴 등 여러분의 콘텐츠 제작에 날개를 달아줄 다양한 에셋을 제공합니다.

assetstore.unity.com

 

Easy 2D, 3D, VR, & AR software for cross-platform development of games and mobile apps. - Unity Store

Have a 2D, 3D, VR, or AR project that needs cross-platform functionality? We can help. Take a look at the easy-to-use Unity Plus real-time dev platform!

store.unity.com

 

Create 2D & 3D Experiences With Unity's Game Engine | Unity Pro - Unity Store

Unity Pro software is a real-time 3D platform for teams who want to design cross-platform, 2D, 3D, VR, AR & mobile experiences with a full suite of advanced tools.

store.unity.com

[투네이션]

 

-

 

toon.at

[Patreon]

 

WER's GAME DEVELOP CHANNEL님이 Game making class videos 창작 중 | Patreon

WER's GAME DEVELOP CHANNEL의 후원자가 되어보세요. 아티스트와 크리에이터를 위한 세계 최대의 멤버십 플랫폼에서 멤버십 전용 콘텐츠와 체험을 즐길 수 있습니다.

www.patreon.com

[디스코드 채널]

 

Join the 베르의 게임 개발 채널 Discord Server!

Check out the 베르의 게임 개발 채널 community on Discord - hang out with 399 other members and enjoy free voice and text chat.

discord.com

 

반응형

애니메이션 기초

 

 

이 섹션에서는 언리얼 엔진에서 캐릭터에 애니메이션을 추가하는 방법을 알아볼 것이다.

 

기본 캐릭터 구현

모델링과 애니메이션을 추가하기 이전에 그것들을 사용할 캐릭터 클래스를 구현해보자.

 

우선 새로운 프로젝트를 추가한 뒤 언리얼 에디터의 편집 드롭다운 메뉴에서 프로젝트 세팅 창을 연다.

 

 

그리고 엔진 섹션의 입력에서 입력 매핑을 다음과 같이 설정한다.

 

 

그 다음은 콘텐츠 브라우저 패널에서 신규 추가 버튼을 누르고, 새 C++ 클래스를 선택하여 부모 클래스 선택 창을 연다.

 

그리고 Character 클래스를 부모 클래스로 선택하고 다음을 클릭한다.

 

 

클래스 이름은 AnimTestCharacter로 하자.

 

 

이제 캐릭터를 움직일 함수를 만들고 앞에서 설정한 입력 매핑과 바인딩할 차례다.

 

우선 캐릭터를 움직이기 위한 다음 함수들을 AnimTestCharacter.h의 클래스 안에 선언한다.

 

UFUNCTION()
void MoveForward(float AxisValue);

UFUNCTION()
void MoveRight(float AxisValue);

 

AnimTestCharacter.cpp에서 위 두 함수를 다음과 같이 구현한다.

 

void AAnimTestChararcter::MoveForward(float AxisValue)
{
    AddMovementInput(GetActorForwardVector(), AxisValue);
}

void AAnimTestChararcter::MoveRight(float AxisValue)
{
    AddMovementInput(GetActorRightVector(), AxisValue);
}

 

방금 만든 함수와 입력 매핑을 바인딩하기 위해서, InputComponent를 사용해야하기 때문에, AnimTestCharacter.cpp 상단의 전처리기에 다음 코드를 추가한다.

 

#include "Engine/Classes/Components/InputComponent.h"

 

그 다음엔 SetupInputComponent() 함수에 입력 매핑과 함수를 바인딩하는 코드를 추가한다.

 

InputComponent->BindAxis("MoveForward", this, &AAnimTestChararcter::MoveForward);
InputComponent->BindAxis("MoveRight", this, &AAnimTestChararcter::MoveRight);
InputComponent->BindAxis("Turn", this, &AAnimTestChararcter::AddControllerYawInput);
InputComponent->BindAxis("LookUp", this, &AAnimTestChararcter::AddControllerPitchInput);

 

코드를 모두 작성했다면 변경사항을 저장하고 솔루션 탐색기에서 빌드를 진행한다.

 

 

그리고 에디터로 돌아가서 콘텐츠 브라우저 창에서 Bluprints라는 이름의 새 폴더를 만든 뒤, C++ AnimTestCharacter 클래스에 우클릭하여 AnimTestCharacter 기반 블루프린트 클래스 생성을 클릭하고, BP_AnimTestCharacter 라는 이름으로 블루프린트 클래스를 생성한다.

 

 

이어지는 과정을 수행하기 전에, 캐릭터 모델링을 다운받아 프로젝트에 임포트한다.
TestChar.zip
다운로드

 

TestChar.fbx를 프로젝트에 임포트했다면, BP_AnimTestCharacter를 더블클릭해서 블루프린트 에디터를 열고 컴포넌트 패널에서 Mesh 컴포넌트를 선택한다.

 

 

그리고 디테일 패널에서 Mesh 섹션을 찾아서 없음으로 되어있는 Skeletal Mesh를 방금 임포트한 TestChar로 설정해준다.

 

 

스켈레탈 메시를 TestChar로 설정하고 나서, 뷰포트를 통해 확인하면 다음과 같이 캡슐 콜라이더 크기와도 맞지 않고 방향도 다른 것을 알 수 있다.

 

 

이것을 올바르게 맞추기 위해, 디테일 패널의 트랜스폼 섹션에서 위치 {0.0, 0.0, -90.0}, 회전 {0.0, 0.0, 90.0}, 스케일 {3.0, 3.0, 3.0}으로 설정한다. 설정이 모두 끝났다면 블루프린트를 컴파일하고 저장한 뒤, 블루프린트 에디터를 닫는다.

 

블루프린트를 레벨 에디터에 끌어놓아 배치한다. 그리고 플레이 버튼을 눌러서 PIE 모드로 들어가면 캐릭터에 메시가 추가된 것과 전에 설정한 이동과 카메라 제어가 정상적으로 되는 것을 확인할 수 있다.

 

 

 

하지만 아직 문제는 남아있다. 카메라가 캐릭터의 몸통 한가운데 박혀있기 때문에, 캐릭터의 움직임이 제대로 보이지 않고 부자연스럽다. 이를 해소하기 위해서 새로운 카메라를 배치하고 TPS처럼 구성해보자.

 

 

비주얼 스튜디오로 돌아가서 AnimTestCharacter.h에 다음 멤버 변수를 추가한다.

 

UPROPERTY(VisibleAnywhere)
class USpringArmComponent* TPSCameraSpringArmComponent;

UPROPERTY(VisibleAnywhere)
class UCameraComponent* TPSCameraComponent;

 

그리고 AnimTestCharacter.cpp에서 몇 가지 기능들을 사용하기 위해서 전처리기 리스트에 다음 코드를 추가한다.

 

#include "Engine/Classes/Camera/CameraComponent.h"
#include "Engine/Classes/Components/CapsuleComponent.h"
#include "Engine/Classes/GameFramework/SpringArmComponent.h"

 

다음엔 AAnimTestCharacter::AAnimTestCharacter() 생성자 함수에 스프링 암과 카메라 컴포넌트를 생성하고 세팅하는 코드를 추가한다.

 

TPSCameraSpringArmComponent = CreateDefaultSubobject<USpringArmComponent>(TEXT("ThirdPersonCameraSpringArm"));
TPSCameraSpringArmComponent->SetupAttachment(GetCapsuleComponent());
TPSCameraSpringArmComponent->SetRelativeLocation(FVector(0.0f, 0.0f, BaseEyeHeight));
TPSCameraSpringArmComponent->bUsePawnControlRotation = true;

TPSCameraComponent = CreateDefaultSubobject<UCameraComponent>(TEXT("ThirdPersonCamera"));
TPSCameraComponent->SetupAttachment(TPSCameraSpringArmComponent, USpringArmComponent::SocketName);

 

변경사항을 저장하고 프로젝트를 빌드한 뒤, 에디터로 돌아가서 플레이를 해보면 전처럼 카메라가 캐릭터의 몸 속에 있지 않고, 캐릭터의 등 뒤에 적당히 떨어진 거리에서 카메라가 있음을 확인할 수 있다.

 

 

이제 캐릭터를 추가했고, 그 캐릭터의 애니메이션을 제대로 볼 수 있는 뷰를 완성했으니, 본격적으로 애니메이션을 추가해보자.

 

 

 

 

 

캐릭터 애니메이션 작업
 
캐릭터 애니메이션 파트를 시작하기 전에 필요한 캐릭터 애니메이션을 다운받자.

 

애니메이션을 다운받고 압축을 해제하였다면, 콘텐츠 브라우저에서 Animations 폴더를 만들고 파일 창에 우클릭하여 /Game/Animations 에 임포트를 선택하여, TestChar_Idle, TestChar_Move를 선택한다.

 

 

FBX 임포트 옵션 창이 뜨면 Import Mesh 프로퍼티의 체크를 해제하고 Mesh 섹션의 Skeleton 프로퍼티에 TestChar_Skeleton을 설정해주고 모두 임포트를 선택한다.(Import Mesh 프로퍼티의 체크를 해제하는 경우는 모델링과 애니메이션이 모두 있는데, 그 중에 애니메이션만 임포트하려고 할 때이다.)

 

 

 

 

콘텐츠 브라우저 패널에서 신규 추가 버튼을 클릭하고 애니메이션/애니메이션 블루프린트를 선택한다.

 

 

부모 클래스로는 AnimInstance를 선택하고 타깃 스켈레톤은 TestChar_Skeleton을 선택한다. 애니메이션 블루 프린트의 이름은 TestChar_AnimBP로 하자.

 

 

생성한 애니메이션 블루프린트를 더블클릭해서 애니메이션 블루프린트 에디터를 연다. 그리고 내 블루프린트 패널에서 Boolean 타입의 IsRunning 변수를 추가한다.

 

 

변수를 추가한 뒤에는, 애니메이션 블루프린트의 이벤트 그래프로 이동해 다음과 같이 구성한다.

 

 

이 다음엔 내 블루프린트 패널에서 애님 그래프 더블클릭해서 애님 그래프를 열고 우클릭하여 컨텍스트 메뉴를 열어 스테이트 머신을 추가한다.

 

 

새로 추가한 스테이트 머신의 이름을 TestChar State Machine으로 변경하고 최종 애니메이션 포즈와 연결한다.

 

 

생성한 스테이트 머신을 더블클릭해서 스테이트 머신으로 진입하고 바탕에 우클릭하여 스테이트를 추가한다.

 

 

위와 같은 방법으로 아래 이미지처럼 Idle과 Run 스테이트를 만들고 생성된 Idle 스테이트에 더블클릭한다.

 

 

 

그 다음 스테이트 그래프 바탕에 우클릭해서 TestChar_Idle 애니메이션을 불러온다.

 

 

그 다음 추가한 애니메이션과 출력 애니메이션 포즈 노드와 연결시켜준다. 그리고 이와 같은 작업을 Run 스테이트에서도 똑같이 해준다.

 

 

다시 TestChar State Machine으로 돌아와서 트랜지션을 아래와 같이 구성한다.

 

 

먼저 Idle에서 Run으로 향하는 트랜지션을 더블클릭해서 이벤트 그래프를 다음과 같이 구성한다.

 

 

그리고 Run->Idle 트랜지션은 다음과 같이 구성한다. 이렇게 트랜지션까지 모두 구성했다면 애니메이션 블루프린트를 컴파일, 저장하고 닫는다.

 

 

 

다음엔 BP_AnimTestCharacter 블루프린트 클래스를 더블클릭해서 열고 디테일 패널의 애니메이션 섹션에서 Anim Class 항목을 방금 생성한 TestChar_AnimBP를 설정해준다. 그리고 블루프린트를 컴파일, 저장하고 블루프린트 에디터를 닫는다.

 

 

언리얼 에디터로 돌아가서 플레이 버튼을 누르고 테스트해보면 캐릭터의 애니메이션이 잘 적용된 것을 확인할 수 있다.

 

 

[투네이션]

 

-

 

toon.at

[Patreon]

 

WER's GAME DEVELOP CHANNEL님이 Game making class videos 창작 중 | Patreon

WER's GAME DEVELOP CHANNEL의 후원자가 되어보세요. 아티스트와 크리에이터를 위한 세계 최대의 멤버십 플랫폼에서 멤버십 전용 콘텐츠와 체험을 즐길 수 있습니다.

www.patreon.com

[디스코드 채널]

 

Join the 베르의 게임 개발 채널 Discord Server!

Check out the 베르의 게임 개발 채널 community on Discord - hang out with 399 other members and enjoy free voice and text chat.

discord.com

 

반응형

+ Recent posts