이전 기록
https://mountain-noroo.tistory.com/52
[언리얼] 학원 5일차 기록
이전 기록 https://mountain-noroo.tistory.com/51 [언리얼] 학원 4일차 기록 이전 기록 https://mountain-noroo.tistory.com/50 [언리얼] 학원 3일차 기록 이전 기록 https://mountain-noroo.tistory.com/49 폰 -> 플레이어 자동 빙
mountain-noroo.tistory.com
세팅의 불편함
유니티에서도 인스펙터에 하나하나 넣어주는 불편함이 있는 것처럼, 지금까지는 디테일 창에서 데이터를 하나하나 세팅해줘야 하는 불편함이 있었다.
그래서 데이터 에셋이라는 것을 만들어 이 불편함을 덜어주었다.
Enum, Struct 생성
데이터 에셋을 구현하기 앞서 비주얼 스튜디오에서 Enum과 Struct를 생성해 주었다.
언리얼에서 소스를 생성하는 것과 달리, 소스 코드의 경로가 이상하게 설정되어 있기 때문에 cpp, h를 생성할 때마다 체크해야 한다.

우선 전역적으로 사용할 헤더를 모두 가지고 있는 global.h 작성하고 enum, struct 헤더를 include 하였다.
이후 생성하는 C++ 클래스에는 이 헤더만 include 해주어도 되도록.
enum

UENUM(BlueprintType): UENUM은 enum을 생성할 때 사용하는 매크로. BlueprintType은 해당 enum을 언리얼 에디터에서도 사용 가능하도록 만든다.
InputAction의 종류들을 정의해 놓는다.
struct

USTRUCT(Atomic, BlueprintType): USTRUCT는 struct를 생성할 때 사용하는 매크로. Atomic은 이 구조체를 직렬화시켜 준다.
InputAction Type과 Action을 매핑해 주는 역할을 할 것이다.
구조체를 만들 때
- 구조체 안에 GENERATED_BODY() 매크로 추가.
- #include "파일이름.generated.h"를 #include 중 제일 마지막에 배치.
아래 문서에 게임플레이 클래스를 만드는 방법이 자세하게 정리되어 있다.
https://docs.unrealengine.com/5.1/ko/gameplay-classes-in-unreal-engine/
게임플레이 클래스
게임플레이 클래스 생성 및 구현을 위한 레퍼런스입니다.
docs.unrealengine.com
작명 규칙
Actor에서 파생되는 클래스: 앞에 A를 붙임
Struct: 앞에 F를 붙임
Enum: 앞에 E를 붙임
데이터 에셋 Data Asset
여러 데이터의 묶음을 에셋화 시켜 하나로 사용하는, 일종의 에셋
캐릭터 클래스 에디터에서 하나하나 세팅하는 번거로움을 덜어준다.

데이터 에셋은 방금 만든, 액션 타입과 액션을 매핑하도록 설계된 IAData 구조체 배열을 갖는다.
TArray: 언리얼에서 제공하는 배열 컨테이너

캐릭터 클래스에서 다른 변수는 모두 없애고 IADataAsset을 추가해 주었다.

SetupPlayerInputComponent함수에서는 데이터 에셋을 순회하며 Type에 따라 맞는 함수를 바인딩해 주는 코드로 교체.
데이터 에셋은 우클릭 -> 기타 -> 데이터 에셋 -> 원하는 데이터 에셋을 선택하는 것으로 생성할 수 있다.
사실상 클래스의 디테일 부분에서 하던 일을 대신에 데이터 에셋에서 하는 것.
로그 출력
UE_LOG(LogTemp, Warning, TEXT("text"));
// UE_LOG(카테고리, 경고 수준, 출력할 문자)
언리얼 로그 매크로는 위와 같은 형태.
경고 수준은 Log, Warning, Error 세 가지가 있으며 다른 색으로 출력된다.
카테고리 추가
DECLARE_LOG_CATEGORY_EXTERN(Player, Log, All);
DEFINE_LOG_CATEGORY(Player);
카테고리를 직접 만들 수 있다.
만든 카테고리를 사용하기 위해서는 DEFINE_LOG_CATEGORY(카테고리)로 등록해주어야 한다.
FString
언리얼에서 제공하는 2바이트 문자형.
Printf함수를 이용해 서식문자를 사용한 문자열을 만들 수 있다.
FString::Printf(TEXT("%s : {%d} : %s"), *FString(__FUNCTION__), __LINE__, String)
__FUNCTION__ : C++ 제공 매크로. 함수 이름 반환. 1바이트 캐릭터로 반환하기 때문에 TEXT(char) 매크로를 이용해 FString으로 변환해 사용하여야 한다.
__LINE__: C++ 제공 매크로. 로그가 출력되는 줄을 반환.
애니메이션 몽타주
https://docs.unrealengine.com/5.1/ko/animation-montage-in-unreal-engine/
애니메이션 몽타주
Animation Montage, 애니메이션 몽타주는 하나의 애셋에 들어있는 애니메이션을 합쳐 선택적으로 재생할 수 있도록 해주는 유연한 툴입니다.
docs.unrealengine.com
총을 쏘는 모션을 넣기 위해서는 상하체에 다른 애니메이션이 블랜딩 될 필요가 있다.
그 과정에서 애니메이션 몽타주를 사용했는데, 하고 보니 몽타주 자체는 블랜딩과 관련이 없는 것 같아 헷갈려 정보를 좀 찾아봤다.
[UE5] Unreal Engine 5 길라잡이 - 12. 애니메이션 몽타주, 델리게이트, 노티파이
애니메이션 몽타주와 함께 언리얼 엔진의 델리게이트, 노티파이 등이 무엇인지 알아보자.
velog.io
"정해진 순서에 따라 실행되는 애니메이션 사이에서 조건에 맞게 애니메이션 재생을 조절하는 기능이다."
이 말이 몽타주의 기능을 간단하게 설명해 주는 것 같다. 마치 피아노 악보와 같이... 애니메이션에 도돌이표를 넣거나 특정 섹션으로 넘어가거나... 하는 기능이라 이해하였다.

섹션: 여러 시퀀스를 추가하고 섹션을 나눌 수 있다.
해당 섹션 재생 다음에 어떤 섹션으로 넘어갈지를 몽타주 섹션 창에서 설정해 준다.
슬롯: 몽타주를 재생할 때는 슬롯을 하나 만들어 놓고, 슬롯 안에 여러 몽타주를 등록할 수 있다.
기본적으로 DefaultGroup 안의 DefaultSlot으로 등록된다.
블랜딩

이렇게 만든 몽타주를 상체, MainPose를 하체로 블렌딩 해야 하는데
본 별로 레이어드 블렌딩노드에서 원하는 본에 블렌딩할 포즈를 매핑하고, Blend Weight를 설정해 주면 된다.
여기서 Blend Weight는 두 번째 포즈 기준이다.
1이면 두 번째 포즈 비율 100퍼센트, 0이면 첫 번째 포즈 비율 100퍼센트라는 뜻.


본은 위 버튼을 눌러 확인 가능.
C++ 코드에서 몽타주 실행하기
protected:
UPROPERTY(EditAnywhere, Category = "Animation")
TSoftObjectPtr<UAnimMontage> FireMontage;
ConstructorHelpers::FObjectFinder<UAnimMontage> montage(TEXT("/Script/Engine.AnimMontage'/Game/BlueprintClass/Player/Animation/AM_Fire.AM_Fire'"));
if (montage.Succeeded())
{
FireMontage = montage.Object;
}
캐릭터 베이스 클래스에 몽타주 포인터 변수를 추가하고,
생성자에서 오브젝트를 참조시켜주었다.
몽타주는 클래스가 아닌 오브젝트기 때문에 FClassFinder가 아니라 FObjectFinder를 사용한다.
Fire 액션 함수
void ACharacter_Base::Fire(const FInputActionInstance& _Instance)
{
bool bToggle = _Instance.GetValue().Get<bool>();
LOG(Player, Warning, TEXT("Fire!"))
if (!IsValid(GetMesh()->GetAnimInstance()) || FireMontage.IsNull())
return;
if (bToggle)
{
GetMesh()->GetAnimInstance()->Montage_Play(FireMontage.LoadSynchronous());
m_IsFire = true;
}
else
{
GetMesh()->GetAnimInstance()->Montage_StopWithBlendOut(0.3f, FireMontage.LoadSynchronous());
m_IsFire = false;
}
}
(이전에 Fire액션을 등록, 함수 바인딩 과정을 거쳐야 한다.)
AnimInstance가 유효하며, FireMontage가 Null이 아닐 때만 실행한다.
입력으로 true(버튼 눌림)가 들어오면 몽타주를 실행시키고
입력으로 false(버튼 해제됨)가 들어오면 몽타주를 블렌드 아웃 시킨다. 서서히 전환 되도록 시간은 0.3초로 설정해준다.
m_IsFire는 애니메이션인스턴스에서 해당 액션이 실행중인지 알 수 있도록 만든 public 변수.
AnimInstance
UPROPERTY(Editanywhere, BlueprintReadWrite, Category = "데이터")
float FireBlendWeight;
// 캐릭터가 총을 쏘는지 확인
IsFire = Character->m_IsFire;
if (IsFire)
{
FireBlendWeight = 1.f;
}
else
{
FireBlendWeight = 0.f;
}
블루프린트에서 weight값을 가져올 수 있도록 BlendWeight 변수를 선언해주며
Update에서 캐릭터의 m_IsFire 변수에 따라 weight값을 조정해준다.
'언리얼 > Assortrack UE5' 카테고리의 다른 글
[언리얼] 학원 8일차: SpawnActor, 싱글톤, 투사체 (0) | 2023.09.06 |
---|---|
[언리얼] 학원 7일차: 애니메이션 노티파이와 파티클, 나이아가라 (1) | 2023.09.05 |
[언리얼] 학원 5일차: Anim Instance를 C++로 구현 (0) | 2023.09.01 |
[언리얼] 학원 4일차: 점프, 착지와 애니메이션 스테이트 머신 (0) | 2023.08.31 |
[언리얼] 학원 3일차: 캐릭터 회전 개선, 이동 애니메이션 (0) | 2023.08.30 |