1. 총기 반동 구현
가장 쉬운 방법은 PlayerController의 AddPitchInput과 AddYawInput을 사용하는 방식이다.
- CalculateRecoilValue 함수는 Current Weapon이 가진 변수를 가져와서 캐릭터 변수에 저장하는 동작을 하는 함수이다.
void APlayerCharacter::Recoil()
{
APlayerCharacterController* PlayerCharacterController = Cast<APlayerCharacterController>(GetController());
if (PlayerCharacterController)
{
CalculateRecoilValue();
float PitchRecoil = FMath::RandRange(MinPitchRecoil, MaxPitchRecoil);
float YawRecoil = FMath::RandRange(MinYawRecoil, MaxYawRecoil);
PlayerCharacterController->AddPitchInput(-PitchRecoil);
PlayerCharacterController->AddYawInput(YawRecoil);
}
}
2. 데칼 구현
총을 쏜 부분에 데칼을 통해 이펙트를 주는 것을 구현해 보았다.
2 -1. 데칼 머티리얼
- 먼저 데칼 머티리얼을 만들어야 한다.
- 아래의 머티리얼 설정을 해준 후
- texture sample에 우리가 가져온 이미지를 넣어 베이스 컬러와 오파시티에 연결해주면 된다.
2 - 2. 데칼 스폰
- 무기 클래스는 UMaterialInterface* BulletDecal; 변수를 가지고 있어야 한다.
- 이후 생성자에서 해당 값 세팅을 해준다.
static ConstructorHelpers::FObjectFinder<UMaterialInterface>DecalAsset(TEXT("/Game/HJ/Material/M_Bullet.M_Bullet"));
if (DecalAsset.Succeeded())
{
BulletDecal = DecalAsset.Object;
}
- 마지막으로 SpawnDecalAtLocation 함수를 사용하면 된다.
- 주의할 것
- MakeRotFromX 함수를 사용하려면 #include "Kismet/KismetMathLibrary.h" 해야한다.
- 이 함수는 벡터를 X축으로 설정하여 해당 벡터 방향을 가리키는 회전값을 생성하는 함수이다.
- 데칼이 총이 닿은 면과 같은 방향으로 생성되도록 하기 위해 사용하였다.
- SetFadeScreenSize를 통해 데칼이 멀리서 보이지 않는 문제를 해결해준다.
- MakeRotFromX 함수를 사용하려면 #include "Kismet/KismetMathLibrary.h" 해야한다.
UGameplayStatics::SpawnDecalAtLocation(GetWorld(), BulletDecal, FVector(5.f, 5.f, 5.f),
HitResult.Location, UKismetMathLibrary::MakeRotFromX(HitResult.ImpactNormal), 4.f)->SetFadeScreenSize(0.f);
3. 탄피 구현
액터를 상속받은 AWeaponShell이라는 클래스를 만들어 준 후 Spawn Actor를 통해서 구현하였다.
3 - 1. 액터 만들기
- 캐릭터와 충돌이 없도록 SetCollisionResponseToChannel 함수를 통해 무시하도록 설정
- 해당 Mesh의 Scale을 지정해주어야 게임에서 보인다!
- SetWorldScale3D를 하지 않으면 게임 내에서 보이지 않음
AWeaponShell::AWeaponShell()
{
PrimaryActorTick.bCanEverTick = false;
ShellMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Static Mesh"));
RootComponent = ShellMesh;
ShellMesh->SetSimulatePhysics(true);
ShellMesh->SetCollisionResponseToChannel(ECC_Pawn, ECR_Ignore);
static ConstructorHelpers::FObjectFinder<UStaticMesh> ShellMeshAsset(TEXT("/Game/HJ/Assets/FPS_Weapon_Bundle/Weapons/Meshes/Ammunition/SM_Shell_545x39_Empty.SM_Shell_545x39_Empty"));
if (ShellMeshAsset.Succeeded())
{
ShellMesh->SetStaticMesh(ShellMeshAsset.Object);
}
ShellMesh->SetWorldScale3D(FVector(2.f, 2.f, 2.f));
}
void AWeaponShell::EjectShell(FVector Direction)
{
ShellMesh->AddImpulse(Direction * 3.f, NAME_None, true);
}
3 - 2. 액터 스폰
- 소켓을 통해 스폰할 위치를 저장해두고 SpawnActor를 call 해주었다.
- 이때 우리가 만든 클래스를 스폰하려면 ::StaticClass() 를 통해서 UClass 타입으로 만들어 주었다.
- 만약 액터를 BP로 만들었다면, TSubclassOf 타입의 변수를 만들어서 아래와 같이 사용하면 된다.
- TSubclassOf<AActor> ShellClass;
- GetWorld()->SpawnActor<AActor>( ShellClass, SpawnLocation, SpawnRotation);
//shell effect
FVector ShellLocation = GunMesh->GetSocketLocation(TEXT("ShellSocket"));
FRotator ShellRotation = GunMesh->GetSocketRotation(TEXT("ShellSocket"));
FActorSpawnParameters SpawnParams;
AWeaponShell* ShellActor = GetWorld()->SpawnActor<AWeaponShell>(AWeaponShell::StaticClass(), ShellLocation, ShellRotation, SpawnParams);
if (ShellActor)
{
FVector Direction = ShellRotation.RotateVector(FVector(-30.f, 0.f, 0.f));
ShellActor->EjectShell(Direction);
ShellActor->SetLifeSpan(3.f);
}
4. 최종 동작 모습
'Unreal Engine' 카테고리의 다른 글
Unreal Engine - 캐릭터 앉기 및 구르기 (0) | 2025.03.05 |
---|---|
Unreal Engine - TSubclassOf & StaticClass (0) | 2025.02.27 |
UE5 Issues : 총기 스폰 및 포인터 (0) | 2025.02.27 |
UE5 Issues : 인벤토리 UI (0) | 2025.02.26 |
UE5 Issues : 캐릭터 아이템 획득 로직 구현 (0) | 2025.02.24 |