기본 콘텐츠로 건너뛰기

250407 C++ 애니메이션

블루프린트 사용하는 이유

유지보수가 쉬움


Animation Blueprint

C++ 클래스 생성에서 All Classes를 클릭하고 AnimInstance를 하나 만든다.


블루프린트에서 Animation Blueprint 생성을 누른다.

Skeleton을 본인이 사용할 것을 골라주고, Parent Class를 생성한 AnimInstance의 이름을 골라 생성해준다.


제대로 생성되었다면, Class Settings - Class Options - Parent Class에 해당 AnimInstance가 들어간 것을 확인할 수 있다.


//메쉬의 애니메이션 설정에 애니메이션 인스턴스 삽입
static ConstructorHelpers::FClassFinder<UAnimInstance> AnimInstance(TEXT("/Game/Blueprints/ABP_Player.ABP_Player_C"));
if (AnimInstance.Class)
{
GetMesh()->SetAnimInstanceClass(AnimInstance.Class);
}

경로를 지정해줄때, Class를 가져올 것이므로 경로 끝에_C를 추가해주자.
아래의 경우에도 동작은 한다.


PlayerAnimInstance.h

PlayerAnimInstance.cpp
NativeInitiallizeAnimation
Owner에 GetOwningActor를 하여 가져올 때 Cast를 통해서 캐릭터형으로 받고 있다.
찾은 Owner에 CharacterMovement를 Owner->GetCharcterMovement()를 통해 Movement에 넣고 있다.
Super::NativeInitializeAnimation();

//Cast ACharacter
Owner = Cast<ACharacter>(GetOwningActor());

//Movement
if (Owner)
{
Movement = Owner->GetCharacterMovement();
}

NativeUpdateAnimation
앞서 찾아온 Movement와 Owner를 이용해서, Velocity, MoveSpeed, isFalling, Angle의 값을 할당해주고 있다.
Super::NativeUpdateAnimation(DeltaSeconds);

//Movement를 가져와서 값 할당
if (Movement)
{
Velocity = Movement->Velocity;
MoveSpeed = Velocity.Size2D();
isFalling = Movement->IsFalling();
Angle = UAnimInstance::CalculateDirection(Velocity, Owner->GetActorRotation());
}




AnimationBlueprint - My Blueprint의 톱니바퀴 버튼을 눌러, Show Inherited Variables 를 눌러준다.



생성한 BlendSpace를 Entry와 연결한다.
플레이어의 MoveSpeed를 BlendSpace의 이동 애니메이션에 사용할 것이라서 연결해준다.

각도값 또한 추가해주기 위해 변수 Angle을 만들어서 넣어준다.
UAnimInstance::CalculateDirection



캐릭터에 무기를 추가하기 위해서, 캐릭터의 스켈레톤 메쉬를 클릭하여 열고, Add Socket을 통해 Weapon Socket을 추가한다. 
다음으로 Add Preview Asset을 통해서, 추가할 Weapon의 위치를 조정해준다.

하지만, 이러한 방식을 사용하면, 상위의 Bone이나 그러한 것들 때문에, Weapon_Socket_R이 영향을 받아서 제대로 된 애니메이션이 나오지 않을 것이다.
무기를 더해줄 때는, 어느 부분까지 영향을 미칠 수 있는 가를 생각해서, Socket을 만들어 넣어야한다.


제대로 된 애니메이션을 위해서 hand_r의 밑에 Socket을 만들고 Preview를 통해서 적절한 각도, 위치로 설정한다.

가능하면 Skeleton에서 해당 작업을 하자. SkeletalMesh에서는 모델링에 영향을 끼칠 수 있다.

스태틱 메쉬를 사용할것이라 include 해준다.

Weapon에 스태틱메쉬를 만들어 WeaponMesh로 이름을 정한다.
SetupAttachment를 통해, 플레이어의 메쉬에 Weapon을 하위로 붙입니다.
ConstructorHelpers::FObjectFinder를 통해, Weapon의 스태틱 메쉬의 위치를 찾습니다.

Succeeded()를 통해 오류를 방지하고, 제대로 가져왔는지 확인합니다.
제대로 가져왔다면, SetStaticMesh로 SM_Weapon에 넣어줍니다.

AttachToComponent를 통해, 플레이어 캐릭터 메쉬의 hand_rSocket에 상대좌표로 붙입니다.

AttachToComponent(붙일 Mesh 이름, 붙일 방식, TEXT("붙일 본/소켓의 이름"));

//무기 추가
SM_Weapon = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("WeaponMesh"));
SM_Weapon->SetupAttachment(GetMesh());
static ConstructorHelpers::FObjectFinder<UStaticMesh> WeaponMesh(TEXT("/Script/Engine.StaticMesh'/Game/Asset/Weapons/FPS_Weapon_Bundle/Weapons/Meshes/AR4/SM_AR4.SM_AR4'"));

//SM_Weapon에 Ar4 추가
if (WeaponMesh.Succeeded())
{
SM_Weapon->SetStaticMesh(WeaponMesh.Object);
}

// hand_rSocket에 SM_Weapon을 추가한다.
SM_Weapon->AttachToComponent(GetMesh(), FAttachmentTransformRules::KeepRelativeTransform, TEXT("hand_rSocket"));


조준 모드 / 총알 발사
InputAction Aim과 Fire를 통해 구현한다.

아래에서 액션을 가져온다.

버튼을 누르는 동안 조준과 조준을 푸는 것을 위해서 다음과 같이 만든다.

ETriggerEvent::Triggered : 매 틱마다
ETriggerEvent::Started : 맨 처음 한 번
ETriggerEvent::Completed : 맨 마지막에 한 번

AnimInstance를 사용하므로, cpp의 상위에 선언해주자.


Montage를 이용한 애니메이션
Montage로 생성하고 싶은 애니메이션 시퀀스를 선택하고,
오른쪽 마우스 버튼 - Create - Create AnimMontage로 생성한다.

C++ 상에서 사용하기 위해서 정의해준다.
여기서 BlueprintReadWrite를 통해, 우리가 원하는 Montage를 할당할 수 있게 된다.
대신에, 이러한 방식의 경우 Montage가 없을 경우,

문제가 발생하므로, 코드 작성시에 Montage가 존재 하는가에 대한 확인이 필요하다.
따라서 코드 작성시에
if (RifleAimMontage)
{
    AnimInstance->MontagePlay(RifleAimMontage);
}



애니메이션 블루 프린트의 Locomotion에 Slot을 하나 만들어서 연결한다.

해당 몽타주는 우리가 만든 Default 슬롯을 통해서 플레이 된다.
몽타주를 재생할 슬롯은 몽타주에서 설정 가능하다.

Montage를 할당한 후에 AnimInstance->Montage_Play(몽타주); 를 통해 플레이 하면, 애니메이션이 재생되기는 하지만, 중간에 끊기거나 제대로 플레이 되지 않을 것이다.
왜냐하면, Montage_Play에 기본 설정시에 1.0f시간 만큼만 재생되기 때문이다.

따라서, Montage의 EndTime의 값을 확인해서
AnimInstance->Montage_Play(재생할 몽타주 , End Time);
이번의 경우는 0.3f로 설정해주었다.

잘못된 애니메이션 시퀀스의 경우는 약간의 노력으로 수정될 수도 있다.
Additive Settings의 Additive Anim Type
Base Pose Animation의 애니메이션 시퀀스 선택
Root Motion Force Root Lock 여부 변경
등을 통해서 잘못되는 경우를 막을 수 있다.



참고🐋🐋🐋🐋🐋

ConstructorHelpers
https://dev.epicgames.com/documentation/ko-kr/unreal-engine/gameplay-classes-in-unreal-engine?application_version=5.5#%EC%83%9D%EC%84%B1%EC%9E%90%EC%8A%A4%ED%83%9C%ED%8B%B1%EB%B0%8F%ED%97%AC%ED%8D%BC

NativeInitializeAnimation
https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Runtime/Engine/Animation/UAnimInstance/NativeInitializeAnimation?application_version=5.5

NativeUpdateAnimation
https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Runtime/Engine/Animation/UAnimInstance/NativeUpdateAnimation?application_version=5.5

GetAnimInstance
https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Runtime/Engine/Components/USkeletalMeshComponent/GetAnimInstance

AttachToComponent
https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Runtime/Engine/GameFramework/AActor/AttachToComponent?application_version=4.27

ETrigger
https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Plugins/EnhancedInput/ETriggerEvent?application_version=5.5

Montage_play
https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Runtime/Engine/Animation/UAnimInstance/Montage_Play

이 블로그의 인기 게시물

250523 PCG 2

PCG Building Volume Sampler를 사용할 경우 Voxel Size를 맞추어주자. 2m길이를 Transform Points로 Offset을 이동시켜 Difference를 통해 메쉬를 생성한다. 사용시에 Pivot의 위치가 중앙이 아니면 제대로 표현되지 않을 것이다. PCG Landscape Landscape 생성후 PCG Volume 생성. Get Landscape Data - Surface Sampler 안보인다면 Generate Surface Sampler 일반 그리드 패턴으로 서피스 데이터에 포인트를 샘플링합니다. 이 노드에는 다음과 같은 옵션이 있습니다. 포인트 규모(Point Extents) : 서피스의 기본 그리드 셀 크기를 정의합니다. 여유(Looseness) : 변형 가능한 셀 크기를 정의합니다. 실제로 셀 크기는 포인트 규모 * (1 + 여유)입니다. 제곱미터당 포인트(Points Per Square Meter) : 유지되는 셀의 비율을 계산합니다. 이 프로퍼티는 그리드가 클 때 과잉을 제한합니다. Looseness : 기본 1. 0일경우 Extent의 길이 만큼, 1일경우 2배가 됨.  Attribute Filter를 생성하고, Material에 해당하는 Layer를 찾아서 이름을 넣어준다. Type을 Float로 하고 Float Value를 설정하면, 해당 머티리얼이 색칠된 정도 0~1에서 Operator에 의해 >(초과) 0.6초과 일 경우만 생성되게 할 수 있다. 값을 1로 하고 Equal을 이용해서 1인 경우만 생성되게 하는 것도 가능하다. plugin Water body lake를 넣으면, 이또한 Spline이라는 것을 알 수 있다. 따라서 Get Spline Data-Spline Sampler를 통해 사용할 수 있다. GetActorData와 Difference를 통해서 Lake내부를 제거해주기 PCG Mesh Mesh Sampler를 쓰기위해 Get Actor Property를 이용하면, 해당 액터가 ...

250604 저장불러오기

SaveGame 블루프린트 생성 Game Instance 생성, Init 오버라이드 AC_Inventory Save Load

250522 Physics2, PCG

Radial Force Actor Force 값을 많이 주어야함. Balloon Mass값과 PhysicsThrust를 이용하거나, Set Physics Linear Velocity를 이용하여 Z축 값을 줄 수 있다. Skeletal Physics Physics Material Friction : 마찰력. 수치가 클수록. 덜 미끄러워짐 Restritution : 복원력. 탄성계수 수치가 높을 수록 bouncy Fracture voronoi : Cluster의 숫자 Show Bone Color 해제해주기 Damage Damage Threshold의 값을 수정하는 것으로 강도 조절 가능. Chaos Cache Actor에서 Chaos Cache Manager를 생성 가능. Record 기능이 존재한다. 일단 생성하면 Chaos Cache Collection을 저장하여 사용할 수 있게된다. Cachos Cache Manager를 Simulate를 누르면 저장되고, 실행을 종료하면 그동안의 변화상황이 저장된다. 저장된 Collection을 가져와서 Sequencer의 StartTime으로 가져와 재생할 수 있다. PCG plugin Spline생성후 포인트 하나 지워 줌 우클릭으로 Spline Generation Panel, Square 생성. 처음 지점 포인트 겹쳐있을 수 있으므로 찾아서 삭제해주기 Get Spline Data => Spline Sampler D키 또는 Debug에 체크를 해주고, Dimension 설정을 해준다. On Interior의 경우, Unbounded에 체크를 하면 내부에도 생기게 된다. Static Mesh Spawner Intersection : 교차점 이 부분은 tag가 Spline과 Overlap되어 닿으면 바꾸어 준다. Difference를 이용해 그외 부분은 채워 넣는다. 길 By Class로 설정해주기 On Spline - Distance Extent Radius 설정해주기 Difference를 통해 제외하기 PCG는 A...