비헤이비어 트리(Behavior Tree)

 

작성 기준 버전 :: 4.21.1

 

AI는 잠입 액션 게임에서는 수색자가 플레이어를 찾기 위해서 주변을 수색하고, 슈팅 게임에서는 총알이 떨어지면 탄창을 갈고 체력이 부족해지면 회복 아이템을 사용하고 사격을 받으면 엄폐물 뒤로 숨는 등의 게임의 난이도를 적절하게 조절하고 게임의 생명력을 불어넣는 역할을 한다.

 

못 만든 게임은 여러 가지 요소가 플레이어를 거슬리게 만들지만 멍청하게 구는 AI 역시 게임의 재미를 떨어뜨리는 아주 중요한 요소이다. 낮은 난이도라고 AI가 플레이어가 눈 앞에 있어도 멍청하게 서있거나 수 초가 지나서야 반응하거나, 높은 난이도라고 플레이어가 대응할 시간도 없이 죽여버리는 것은 AI를 통한 난이도 조절에 완전히 실패한 경우라고 볼 수 있다. AI를 통한 난이도 조절을 제대로 하기 위해서는 무작정 반응 속도가 빠른 것이 아니라, 플레이어의 심리를 교묘하게 찌르는 전략적인 움직임을 AI가 할 수 있도록 만들어야 한다.

 

앞에서 사설이 길었지만, 이러한 AI를 제작하기 위한 방법으로는 여러 가지가 있다. 간단한 방법으로는 상태 머신(State Machine)부터 어려운 방법으로는 머신 러닝(Machine Learning)까지 말이다. 이러한 여러 가지 기법 중에서 언리얼 엔진은 비헤이비어 트리(Behavior Tree)라는 방식으로 AI 기능을 제공한다.

 

 

언리얼 엔진에서 제공하는 비헤이비어 트리는 블랙보드(BlackBoard)와 비헤이비어 트리(Behavior Tree), 이 두 가지 유형의 에셋의 조합으로 이루어진다.

 

 

블랙보드는 AI의 기억 저장소로 AI가 판단을 내리는데 필요한 데이터들을 저장하는 역할을 하고, 비헤이비어 트리는 블랙보드가 가진 데이터를 토대로 의사결정을 내리고 이를 실행으로 옮기는 역할을 한다.

 

 

비헤이비어 트리 노드의 종류

 

비헤이비터 트리의 노드는 루트(Root), 컴포짓(Composite), 데코레이터(Decorator), 서비스(Service), 태스크(Task). 이렇게 다섯 가지 종류가 있다.

 

 

루트(Root)

 

 

루트 노드는 비헤이비어 트리의 시작점이며, 아래쪽으로 향하는 단 하나의 연결만을 가질 수 있고, 데코레이터나 서비스를 덧붙일 수 없다.

 

 

 

루트 노드 자체에는 별다른 프로퍼티가 없지만, 루트 노드를 선택하면 디테일 패널에서 이 비헤이비어 트리에서 사용할 블랙보드 애셋을 설정할 수 있다.

 

 

컴포짓(Composite)

 

컴포짓 노드는 해당 분기가 실행되는 기본 규칙을 정의한다. 데코레이터를 통해서 분기로 들어가는 조건을 변경하거나, 중간에 실행이 취소되도록 만들거나, 서비스를 덧붙여서 컴포짓 노드의 자손이 실행되는 동안 서비스가 작동되도록 만들 수도 있다.

 

컴포짓 노드는 셀렉터(Selector), 시퀀스(Sequence), 심플 페러렐(Simple Parallel). 세 가지 종류가 있다.

 

셀렉터(Selector)

 

 

셀렉터 노드는 선택기 노드라고도 하며, 자손 노드를 왼쪽에서 오른쪽 순서로 실행하며, 자손 노드 중 하나가 실행에 성공하면 자손의 실행을 멈춘다. 셀렉터의 자손이 실행에 성공하면 셀렉터의 작동은 성공한 것이 되고, 모든 자손의 실행이 실패하면 셀렉터의 작동은 실패한 것이 된다.

 

시퀀스(Sequence)

 

 

시퀀스 노드는 자손 노드를 왼쪽에서 오른쪽 순서로 실행하며, 자손 중 하나가 실패하면 자손의 실행을 멈춘다. 자손 노드가 실행에 실패하면 시퀀스는 실패하며, 모든 자손 노드가 실행에 성공해야 시퀀스가 성공한다.

 

심플 페러렐(Simple Parallel)

 

 

심플 페러렐 노드는 단순 병렬 노드라고도 하며, 전체 노드 트리와 동시에 하나의 태스크를 실행할 수 있다. 예를 들어, 적을 향해 이동하면서 사격한다던지 하는 행동을 할 수 있게 해준다.

 

Finish Mode 설정을 통해서 메인 테스크가 완료되면, 서브 트리를 중단시키고 즉시(Immediate) 노드를 완료시킬지, 아니면 서브 트리를 완료할 때까지 지연(Delayed)시킬지를 설정할 수 있다.

 

 

데코레이터(Decorator)

 

 

데코레이터는 다른 비헤이비어 시스템에서 조건절이라고도 부르는 것으로, 컴포짓이나 태스크에 붙여서 분기나 노드가 실행될 것인지를 정의한다.

 

 

데코레이터의 종류는 기본적으로 16가지가 있고 필요하다면 비헤이비어 트리 에디터의 상단 메뉴 바에서 새 데코레이터 버튼을 클릭해서 커스텀 데코레이터를 추가할 수 있다.

 

기본적인 데코레이터의 종류는 언리얼 엔진 문서 중 비헤이비어 트리 참고서 : 데코레이터에서 확인할 수 있다.

 

 

서비스(Service)

 

 

 

서비스는 컴포짓 노드에 분기가 실행되는 동안 정해진 빈도에 맞춰서 실행된다. 보통 검사를 하고 그 검사를 바탕으로 블랙보드의 내용을 업데이트하는데 사용된다.

 

 

비헤이비어 트리 에디터의 상단 메뉴 바에서 새 서비스 버튼을 클릭해서 커스텀 서비스를 추가할 수 있다. 기본적인 서비스 노드의 종류로는 Default Focus와 Run EQS가 있다.

 

 

태스크(Task)

 

 

태스크는 AI의 이동이나 블랙보드의 값 조정과 같은 작업을 하는 노드로 이 노드에도 데코레이터가 붙을 수 있다.

 

태스크 노드의 종류에는 7가지가 있으며 그 내용은 언리얼 엔진 문서의 비헤이비어 트리 노드 참고서 : 태스크 문서에서 볼 수 있다.

 

 

비헤이비어 트리 에디터의 상단 메뉴 바에서 새 서비스 버튼을 클릭해서 커스텀 태스크를 추가할 수 있다.

 

[투네이션]

 

-

 

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

 

반응형

콜리전과 콜리전 이벤트

 

작성 기준 버전 :: 4.21.1

 

콜리전(Collision)은 언리얼 엔진에서 물리적인 충돌이나 레이 캐스팅 실시간 처리를 해준다. 이러한 물리 시뮬레이션은 Collision Response(콜리전 반응) 및 Trace Response(트레이스 반응) 설정을 통해서 다른 오브젝트 유형과 어떻게 상호작용할지 정의된다.

 

블록(Block), 겹침(Overlap), 무시(Ignore)

 

충돌 작용은 블록(Block), 겹침(Overlap), 무시(Ignore)로 나누어진다.

 

 

블록은 충돌하는 두 오브젝트가 모두 블록이어야 두 오브젝트가 충돌했을 때, 겹치지 않고 서로에게 막히게 된다. 콜리전 옵션 중에 Simulation Generates Hit Event 프로퍼티를 true로 설정하면 이러한 충돌이 발생했을 때 Event Hit을 받아서 블루프린트나 디스트럭터블 액터, 트리거 등에 사용할 수 있고 이를 응용해서 총알에 맞아서 깨지는 유리창 등을 구현할 수 있다.

 

 

겹침은 다른 오브젝트를 통과시키지만, 만약 Generate Overlap Event가 활성화된 상태라면 Overlap Event를 발생시킨다. 이 겹침 이벤트가 발생하려면 두 오브젝트 모두 겹침 이상으로 설정되어 있어야 한다. 만약 한 쪽은 겹침이고 다른 한 쪽이 무시인 상태라면 겹침 이벤트는 발생하지 않는다.

 

 

무시는 모든 오브젝트와 트레이스를 통과시키며 어떠한 이벤트도 발생시키지 않는다.

 

 

콜리전 이벤트

 

콜리전이 발생시키는 이벤트를 다루는 방법에 대해서 배워보자.

 

히트 이벤트(Hit Event)

 

히트 이벤트는 블록 상태인 오브젝트들이 서로 충돌했을 때 발생하는 이벤트로 해당 오브젝트에게 통지된다. 히트 이벤트를 발생하게 하기 위해서는 우선 콜리전의 프로퍼티 중에 Simulation Generates Hit Event를 true로 설정해줘야 한다.

 

우선 히트 이벤트를 받아서 처리하기 위한 클래스를 BlockCollisionActor라는 이름으로 Actor 클래스를 상속받아서 생성하자.

 

 

그리고 비주얼 스튜디오로 가서 BlockCollisionActor.h에 다음 멤버 변수와 함수 선언 코드를 추가한다.

 

protected:
    virtual void NotifyHit(UPrimitiveComponent *MyComp, AActor *Other, UPrimitiveComponent *OtherComp, bool bSelfMoved, FVector HitLocation, FVector HitNormal, FVector NormalImpulse, const FHitResult &Hit) override;

public:   
    UPROPERTY(EditAnywhere)
    class UStaticMeshComponent* BoxMesh;

 

NotifyHit() 함수는 부모 클래스에서 상속받은 것으로 이것을 덮어씌워 작성함으로써 충돌이 발생했을 때 개발자가 원하는 동작을 처리하도록하는 것이 가능해진다. BoxMesh는 다른 물체와 충돌할 메시를 담을 변수이다.

 

그 다음엔 BlockCollisionActor.cpp로 가서 스태틱 메시 컴포넌트를 사용하기 위해서 다음 전처리기를 추가한다.

 

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

 

ABlockCollisionActor::ABlockCollisionActor() 생성자 함수에 다음과 같이 BoxMesh 변수를 초기화하는 코드를 추가한다.

 

ABlockCollisionActor::ABlockCollisionActor()
{
    PrimaryActorTick.bCanEverTick = true;

    BoxMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("BoxMesh"));
    RootComponent = BoxMesh;
}

 

그리고 아까 선언한 NotifyHit() 함수를 다음과 같이 충돌이 발생했을 때 로그를 출력하도록 구현한다.

 

void ABlockCollisionActor::NotifyHit(UPrimitiveComponent *MyComp, AActor *Other, UPrimitiveComponent *OtherComp, bool bSelfMoved, FVector HitLocation, FVector HitNormal, FVector NormalImpulse, const FHitResult &Hit)
{
    UE_LOG(LogTemp, Log, TEXT("NotifyHit"));
}

 

코드 작업이 마무리되었다면 프로젝트를 빌드하고 에디터로 돌아가서 히트 이벤트 테스트를 위한 작업을 진행해보자.

 

먼저 BlockCollisionActor를 레벨에 배치한다.

 

 

BlockCollisionActor의 디테일 패널에서 BoxMesh를 선택하고 비어있는 스태틱 메시 프로퍼티에 모드 패널의 큐브 스태틱 메시를 드래그래서 넣는다.

 

 

그 다음 디테일 패널에서 Collision 카테고리를 찾아서 Simulation Generates Hit Event를 체크해준다.

 

 

BlockCollisionActor 배치가 끝났다면 BlockCollisionActor와 충돌할 액터를 추가해준다. 모드 패널에서 구체 메시 하나를 BlockCollisionActor 위에 배치한다.

 

 

그 다음 배치한 구체의 모빌리티를 무버블로 하고, Physics 카테고리에서 Simulate Physics를 체크해준다.

 

 

다음 이미지와 같이 세팅이 모두 끝났다면 플레이 버튼을 눌러보자.

 

 

그러면 공이 떨어져서 상자에 맞는 순간 NotifyHit 로그가 출력되는 것을 볼 수 있다.

 

 

 

 

 

 

겹침 이벤트(Overlap Event)

 

겹침 이벤트는 겹침으로 설정된 오브젝트에 겹침이나 블록으로 설정된 다른 오브젝트가 겹쳐지면 발생하는 이벤트이다. 겹침 이벤트를 발생시키기 위해서는 Collision 카테고리에서 Generate Overlap Event를 true로 설정해줘야 한다.

 

겹침 이벤트를 처리할 클래스를 OverlapCollisionActor라는 이름으로 Actor 클래스를 상속해서 생성한다.

 

 

OverlapCollisionActor.h에 다음 멤버 변수와 함수 선언 코드를 추가한다.

 

protected:
    virtual void NotifyActorBeginOverlap(AActor *OtherActor) override;
    virtual void NotifyActorEndOverlap(AActor *OtherActor) override;

public:   
    UPROPERTY(EditAnywhere)
        class UStaticMeshComponent* BoxMesh;

 

NotifyActorBeginOverlap() 함수는 겹침이 시작되었을 때 실행되는 함수이고 NotifyActorEndOverlap() 함수는 겹침이 끝났을 때 실행되는 함수이다. 이 두함수를 통해서 우리는 언제 겹침이 시작되었는지, 언제 겹침이 끝났는지를 알 수 있다.

 

BoxMesh는 사실 큰 필요는 없지만 구체가 통과해서 지나갔음을 보여주기 위해서 추가한다. 하지만 만약 스태틱 메시를 사용하지 않을 것이라면 BoxComponent나 SphereComponent, CapsuleComponent 같은 콜리전 컴포넌트를 사용해야 한다.

 

그 다음엔 OverlapCollisionActor.cpp로 가서 스태틱 메시 컴포넌트를 사용하기 위해 다음 전처리기를 추가한다.

 

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

 

AOverlapCollisionActor::AOverlapCollisionActor() 생성자 함수에 BoxMesh를 초기화하는 코드를 추가한다.

 

AOverlapCollisionActor::AOverlapCollisionActor()
{
    PrimaryActorTick.bCanEverTick = true;

    BoxMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("BoxMesh"));
    RootComponent = BoxMesh;
}

 

그리고 NotifyActorBeginOverlap() 함수와 NotifyActorEndOverlap() 함수를 구현한다.

 

void AOverlapCollisionActor::NotifyActorBeginOverlap(AActor * OtherActor)
{
    UE_LOG(LogTemp, Log, TEXT("NotifyActorBeginOverlap"));
}

void AOverlapCollisionActor::NotifyActorEndOverlap(AActor * OtherActor)
{
    UE_LOG(LogTemp, Log, TEXT("NotifyActorEndOverlap"));
}

 

코드 수정이 끝나면 솔루션 탐색기에서 프로젝트를 빌드하고 에디터로 돌아가서 겹침 이벤트를 테스트하기 위한 작업을 한다.

 

우선 아까 전에 배치한 BlockCollisionActor보다 높은 공중에 구체가 통과해서 지나갈 수 있게 OverlapCollisionActor를 배치한다.

 

 

배치된 OverlapCollisionActor를 선택하고 디테일 패널에서 BoxMesh 컴포넌트를 선택한 다음에 비어있는 스태틱 메시에 모드에서 큐브 메시를 드래그 해서 할당해준다.

 

 

그 다음 Collision 카테고리에서 Generate Overlap Event를 체크해주고 Collision Preset을 OverlapAll로 설정한다.

 

 

마지막으로 구체를 선택한 다음 디테일 패널의 Collision 카테고리에서 Generate Overlap Event가 체크되어 있지 않다면 체크를 해준다. 겹침 이벤트가 발생하려면 겹치는 양 오브젝트에 모두 Generate Overlap Event가 true여야 한다.

 

 

플레이 버튼을 눌러보면 구체가 OverlapCollisionActor를 통과하면서 겹침이 시작되면 NotifyActorBeginOverlap 로그가 출력되고, 겹침이 끝나면 NotifyActorEndOverlap 로그가 출력되는 것을 확인할 수 있다.

 

 

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

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

 

에셋스토어

여러분의 작업에 필요한 베스트 에셋을 찾아보세요. 유니티 에셋스토어가 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