Animation - 2

2023. 12. 28. 21:16·Unreal 공부/Unreal Engine 4 C++ The Ultimate Shooter

무기 발사 기능

InhancedInput을 사용하기 위해 InputAction을 생성해주고 IMC에 등록해 줍니다.

 

이후에 코드를 고쳐줍니다.

 

 ShooterCharacter.h

protected:
	...
	void FireWeapon(const FInputActionValue &Value);

private:
	...
    UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input, meta = (AllowPrivateAccess = "true"))
	class UInputAction *FireAction;

 

 ShooterCharacter.cpp

void AShooterCharacter::FireWeapon(const FInputActionValue &Value)
{
	UE_LOG(LogTemp, Warning, TEXT("Fire Weapon"));
	bool isFire = Value.Get<bool>();
}

void AShooterCharacter::SetupPlayerInputComponent(UInputComponent *PlayerInputComponent)
{
	Super::SetupPlayerInputComponent(PlayerInputComponent);
	check(PlayerInputComponent);

	if (UEnhancedInputComponent *EnhancedInputComponent = CastChecked<UEnhancedInputComponent>(PlayerInputComponent))
	{
		...
        // 단발로 설정하기 위해서 ETriggerEvent::Started 사용
		EnhancedInputComponent->BindAction(FireAction, ETriggerEvent::Started, this, &AShooterCharacter::FireWeapon);
	}
}

 

컴파일 후 IA_Fire를 BP_ShooterCharacter의 Fire Action에 등록합니다.

 

Shooting Sound Effect

Assets 폴더와 Sounds, Gunshots 폴더를 만들고 총성 Sound Wave를 import합니다.

 

이후에 Sound Cue를 만들어줍니다. (AR_Shot)

 

이후 모든 Sound Wave를 선택하고 드래그를 통해 AR_shot에 넣어줍니다.

 

Random 노드를 만들어서 Sound Wave를 연결시켜 줍니다.

 

생성한 SoundCue를 등록하고 실행하기 위한 로직을 ShooterCharacter에 작성해 줍니다.

 

ShooterCharacter.h

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Combat, meta = (AllowPrivateAccess = "true"))
	class USoundCue *FireSound;

 

ShooterCharacter.cpp

#include "Kismet/GameplayStatics.h"
#include "Sound/SoundCue.h"

void AShooterCharacter::FireWeapon(const FInputActionValue &Value)
{
	// UE_LOG(LogTemp, Warning, TEXT("Fire Weapon"));
	bool isFire = Value.Get<bool>();

	if (FireSound)
	{
		UGameplayStatics::PlaySound2D(this, FireSound);
	}
}

 

이후 BP_ShooterCharacter에서 Fire Sound에 AR_Shot을 설정해 줍니다.

 

Shooting Particle

발사 파티클을 만들 소켓을 만들기 위해서 Belica의 스켈레톤 메시를 열어줍니다.

 

Weapon을 우클릭하여 BarrelSocket을 만들어주고 위치를 총구의 앞으로 설정해줍니다.

※ Particle 사용시 Rotation도 고려해야 하기 때문에 X축(빨간색)이 전방을 향하도록 설정해야 합니다.

 

ShooterCharacter를 수정해 줍니다.

 

ShooterCharacter.h

	// Flash spawned at BarrelSocket
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Combat, meta = (AllowPrivateAccess = "true"))
	class UParticleSystem *MuzzleFlash;

 

ShooterCharacter.cpp

#include "Engine/SkeletalMeshSocket.h"

...

void AShooterCharacter::FireWeapon(const FInputActionValue &Value)
{
	...
    
	const USkeletalMeshSocket *BarrelSocket = GetMesh()->GetSocketByName("BarrelSocket");
	if (BarrelSocket)
	{
		const FTransform SocketTransform = BarrelSocket->GetSocketTransform(GetMesh());

		if (MuzzleFlash)
		{
			UGameplayStatics::SpawnEmitterAtLocation(GetWorld(), MuzzleFlash, SocketTransform);
		}
	}
}
  • GetSocketByName() : 정적 메시 구성 요소의 명명된 소켓을 반환합니다.
  • FTransfrom : 사용되는 구조체로, 3D 공간에서 오브젝트의 위치(Position), 회전(Rotation), 그리고 크기(Scale)를 표현합니다. 이 구조체는 게임 개발에서 오브젝트의 3D 변환을 관리하는 데 널리 사용됩니다.
  • GetMesh() : ACharacter 클래스의 인스턴스가 가지고 있는 스켈레탈 메시 컴포넌트(USkeletalMeshComponent)를 반환하는 멤버 함수입니다.
  • USkeletalMeshComponent는 USkinnedMeshComponent를 상속 받습니다.
    • SkinnedMeshComponent는 스켈레탈 메시나 스태틱 메시 등의 3D 모델을 렌더링하기 위한 기본 클래스입니다.
  • USkinnedMeshComponent::GetSocketByName : 소켓을 이름으로 찾아 반환하는 기능을 합니다.
  • BarrelSocket->GetSocketTransform(GetMesh()) : 
    • GetSocketTransform() : 소켓이 속한 메시의 컨텍스트를 기반으로 소켓의 월드 변환을 계산하는 데 필요하며, 이는 소켓의 정확한 위치와 방향을 얻기 위해 중요합니다.
  • UGameplayStatics::SpawnEmitterAtLocation() : 소켓의 위치와 방향에서 시각적 효과(총구 화염)를 생성합니다.

 

이후 P_BelicaMuzzle을 찾아 복사 후 Assets>FX 폴더를 새로만들고 붙여넣은 다음 이름을 수정해 줍니다.

 

기존의 파티클은 3번 생성되는데 이것은 Spawn > Burst > Burst List 가 3개의 Array elements로 이루어져 있는 것들을 1개로 만들어서 수정이 가능합니다.

 

이후에 수정한 Single_burst를 BP_Character에 지정해줍니다.

 

Shooting Animation

Animation Montage를 만들어 줍니다. ( HitFireMontage )

Animation Montage

여러 애니메이션 시퀀스를 하나의 흐름으로 결합하여 복잡한 애니메이션 로직을 구현할 수 있게 해주는 기능입니다.
애니메이션 몽타주로 여러 애니메이션 시퀀스 를 하나의 애셋으로 합칠 수 있으며, 이를 섹션 으로 나누어 그 일부 또는 조합 재생이 가능합니다. 몽타주 안에서 이벤트 를 발동시켜 다양한 로컬 또는 리플리케이트 작업을 할 수 있는데, 예를 들면 사운드 큐나 파티클 이펙트 재생, 탄환 수와 같은 플레이어 값 변경, 심지어 네트워크 게임에서 루트 모션 리플리케이션도, 애니메이션에 루트 모션이 켜진 경우 가능합니다.

 

Primary_Fire_Fast를 찾아서 복사 해줍니다. (_Trimmed를 붙여서 구분되게!)

이후 Primary_Fire_Fast _Trimmed의 9~19 프레임을 제거해줍니다.

 

그 다음 HitFireMontage에서 Primary_Fire_Fast_Trimmed를 올려줍니다.

 

좌측의 Asset Details에서 Blend Option > Blend In > Blend Time = 0 으로 조정해줍니다.

 

새로운 Montage 그룹을 만들어 줍니다.(우클릭, StartFire)

애니메이션 몽타주 그룹(Animation Montage Group)

애니메이션 몽타주 내에서 여러 애니메이션 시퀀스를 관리하고 조직하는 데 사용되는 기능입니다. 애니메이션 몽타주 그룹은 특정 애니메이션 슬롯에 연결되어, 복수의 애니메이션 시퀀스를 그룹화하고 제어하는 데 도움을 줍니다.

 

좌하단의 Anim Slot에서 WeaponFire이라는 슬롯을 만들어 줍니다.

애니메이션 슬롯(Animation Slot)

애니메이션 블루프린트 내에서 복수의 애니메이션 시퀀스를 관리하고, 여러 애니메이션 레이어를 조합하는 데 사용됩니다. 이 슬롯을 통해 개발자는 캐릭터의 다양한 신체 부분에 서로 다른 애니메이션을 적용할 수 있습니다.

애니메이션 슬롯의 주요 사용 사례
다중 애니메이션 레이어링: 애니메이션 슬롯은 캐릭터의 상반신과 하반신에 서로 다른 애니메이션을 동시에 적용하는 데 유용합니다. 예를 들어, 캐릭터가 걷는 동안 상반신으로 무언가를 조작하는 별도의 애니메이션을 재생할 수 있습니다.

애니메이션 몽타주와의 연동 : 애니메이션 몽타주를 사용할 때, 특정 슬롯에 애니메이션을 할당하여, 그 슬롯에만 애니메이션 효과가 적용되도록 할 수 있습니다. 이는 애니메이션 몽타주를 더 세밀하게 제어하는 데 도움을 줍니다.

애니메이션 블렌딩 : 서로 다른 애니메이션 슬롯에 할당된 애니메이션들 사이에서 블렌딩을 수행하여, 부드러운 애니메이션 전환을 만들 수 있습니다.

 

그 다음 기본 그룹을 WeaponFire로 바꿔줍니다.

 

WeaponFire가 사용되고 있는지 확인해야 하는데, 이는 좌상단의 Blueprint 버튼을 눌러서 확인할 수 있습니다.

 

New Save Cached poses를 통해서 Cached 노드를 만들고 이름을 Cached Ground Locomotion으로 변경해줍니다.

 

Use Cached pose ~ 를 통해서 저장된 Cache를 사용할 수 있습니다.

여기에서 추가로 Slot DefaultSlot 노드를 만들어줍니다.

그 다음 Details 패널에서 WeaponFire로 변경해 줍니다. (Montage_Play() 시 ABP가 overriding 됩니다.)

 

 

 

몽타주를 등록하고 실행시키는 것을 CPP로 구현하였다.

 

ShooterCharacter.h

	// Montage for firing the weapon
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Combat, meta = (AllowPrivateAccess = "true"))
	class UAnimMontage *HipFireMontage;

 

ShooterCharacter.cpp

void AShooterCharacter::FireWeapon(const FInputActionValue &Value)
{
	...

	UAnimInstance *AnimInstance = GetMesh()->GetAnimInstance();
	if (AnimInstance && HipFireMontage)
	{
		AnimInstance->Montage_Play(HipFireMontage);
		AnimInstance->Montage_JumpToSection(FName("StartFire"));
	}
}
  • GetAnimInstance() : Mesh의 AnimInstance를 반환합니다.
  • UAnimInstance : 스켈레탈 메시(Skeletal Mesh)에 적용되는 애니메이션의 상태와 동작을 관리하는 클래스입니다.
    • 이 클래스는 애니메이션 블루프린트(Animation Blueprint)의 인스턴스로 사용되며, 애니메이션 로직과 변수, 애니메이션 이벤트 등을 처리합니다.
  • AnimInstance->Montage_Play(HipFireMontage) : 애니메이션 인스턴스를 통해 HipFireMontage라는 애니메이션 몽타주를 재생합니다.
  • AnimInstance->Montage_JumpToSection(FName("StartFire")) : 함수를 사용하여 몽타주 내의 "StartFire"라는 이름의 특정 섹션으로 바로 점프합니다.

 

늘 그렇듯, 이후 BP_ShooterCharacter에서 HipFireMontage 설정을 해줍니다.

 

Blending Shooter Animation

우선 아래와 같이 ABP_Shootercharacter를 만들어 줍니다. (주석 단축키는 드래그 + c 입니다.)

  • Layered blend per bone : 신체 부위에 서로 다른 애니메이션을 적용할 수 있게 해줍니다. 캐릭터의 특정 뼈(bone)를 기준으로 애니메이션을 레이어링(층을 이루어 결합)할 수 있습니다.

Layered blend per bone을 사용하여 상체는 총을 쏘는 Cached Weapon Fire, 하체는 Ground Locomotion으로 하기 위해서 Belica의 Skeleton Mesh에 들어가서 상체에 해당하는 본을 찾는다. (spine_01)

 

ABP로 돌아와서 Layered blend per bone의 Details 패널에서 Layer Setup > Index > Branch Filters의 추가 버튼을 눌러주고, Index[0] > Bone Name을 spine_01으로 설정해 준다.

 

그 다음 주석을 달고 완성해 줍니다.

 

+실수로 Blend between Ground Locomotion and Weapon Fire 주석을 단 부분의 

Use cached pose 'Cached Weapon Fire'과 Use cached pose 'Cached Ground Locomotion'의 위치가 바뀌었으니 아래와 같이 수정해 주세요

수정 후 BP

 

LineTracing for Bullet Hits

ShooterCharacter.cpp 에서 LineTrace를 통해서 Bullet Hits를 구현합니다.

마우스 트리거시 BarrelSocket이 존재할때 총구에서 500m까지 LineTrace로 검사하고 FHitResult에 저장합니다.

 

ShooterCharacter.cpp

void AShooterCharacter::FireWeapon(const FInputActionValue &Value)
{
	...
	const USkeletalMeshSocket *BarrelSocket = GetMesh()->GetSocketByName("BarrelSocket");
	if (BarrelSocket)
	{
		...

		// 새로 작성한 부분
		FHitResult FireHit;
		const FVector Start{SocketTransform.GetLocation()};
		const FQuat Rotation{SocketTransform.GetRotation()};
		const FVector RotationAxis{Rotation.GetAxisX()};
		const FVector End{Start + RotationAxis * 50'000.f};

		GetWorld()->LineTraceSingleByChannel(FireHit, Start, End, ECollisionChannel::ECC_Visibility);
		if (FireHit.bBlockingHit)
		{
			DrawDebugLine(GetWorld(), Start, End, FColor::Red, false, 2.f);
			DrawDebugPoint(GetWorld(), FireHit.Location, 5.f, FColor::Red, false, 2.f);
		}
	}

	...
}
  1. FHitResult 초기화:
    • FHitResult FireHit : 라인 트레이스의 결과를 저장할 FHitResult 구조체를 초기화합니다. 이 구조체는 트레이스가 교차한 오브젝트에 대한 정보를 담습니다.
  2. 시작점과 끝점 계산:
    • const FVector Start{SocketTransform.GetLocation()} : 라인 트레이스의 시작점을 소켓의 위치로 설정합니다.
    • const FQuat Rotation{SocketTransform.GetRotation()} : 소켓의 회전을 가져옵니다.
    • const FVector RotationAxis{Rotation.GetAxisX()} : 회전 축의 X 방향을 계산합니다.
    • const FVector End{Start + RotationAxis * 50'000.f} : 라인 트레이스의 끝점을 계산합니다. 여기서 50,000 단위만큼 소켓의 X 방향으로 뻗어나가는 선을 그립니다.
  3. 라인 트레이스 실행:
    • GetWorld()->LineTraceSingleByChannel(FireHit, Start, End, ECollisionChannel::ECC_Visibility) : 라인 트레이스를 실행하여, 시작점에서 끝점까지 시각적으로 보이는 첫 번째 오브젝트를 탐지합니다.
  4. 트레이스 결과 처리:
    • if (FireHit.bBlockingHit) : 라인 트레이스가 어떤 오브젝트와 충돌했는지 확인합니다.
    • DrawDebugLine : 시작점에서 끝점까지 빨간색 선을 그려서 트레이스 경로를 시각적으로 표시합니다.
    • DrawDebugPoint : 트레이스가 교차한 위치에 빨간색 점을 그려서 충돌 지점을 표시합니다.

'Unreal 공부 > Unreal Engine 4 C++ The Ultimate Shooter' 카테고리의 다른 글

Animation - 5  (1) 2023.12.31
Animation - 4  (1) 2023.12.31
Animation - 3  (1) 2023.12.30
Animation  (0) 2023.12.27
[UE] C++에서 SpringArm과 Camera 구현하기  (1) 2023.12.22
'Unreal 공부/Unreal Engine 4 C++ The Ultimate Shooter' 카테고리의 다른 글
  • Animation - 4
  • Animation - 3
  • Animation
  • [UE] C++에서 SpringArm과 Camera 구현하기
메카인
메카인
  • 메카인
    메카인의 지식창고
    메카인
  • 전체
    오늘
    어제
    • 분류 전체보기
      • 코딩 공부
        • TIL(Today I Learn)
        • TIL
        • 백준(C++)
        • Python
        • 알고리즘
        • 프로젝트 회고
      • C++
        • C++
        • C++ STL
        • C,C++ mCoding yotube
      • 게임개발
        • 언데드서바이벌_골드메탈_클론코딩
        • 3D_골드메탈_클론코딩
        • 유니티_문제해결
        • 게임 수학
      • Unreal 공부
        • UE5 GameDev
        • Unreal Engine 4 C++ The Ult..
      • 교재 문제 풀이
        • 운영체제
      • 정보처리기사
        • 정처기 요약
        • 정처기 오답노트
      • 학교수업
        • 데이터베이스
        • 프로그래밍 언어론
        • 리눅스 시스템
        • 네트워크
      • 일상
        • 주식
        • 독서
      • (비공개 전용)
        • memory
        • Build
        • OOP
        • Smart Pointer
        • lamda
        • 게임 수학
        • 모던 C++
        • 모던 C++ STL
        • 모던 C++ Concurrency, Paralle..
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
    • 글쓰기
    • 블로그 관리
  • 링크

  • 공지사항

    • 공지사항 - 인생과 블로그의 목표
  • 인기 글

  • 태그

  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
메카인
Animation - 2
상단으로

티스토리툴바