본문 바로가기

언리얼엔진

[C++] MuzzleFlash, Sound 활성화 / GPCBullet

MuzzleFlash와 Sound 발생시키기

저번시간에는 Construction() 함수를 이용하여 RootComponent에 다른 Component들을 붙여주었다.

이번에는 마우스 좌클릭으로 총알을 발사하게 되는데, 이때 MuzzleFlash와 GunshotSound를 활성화시켜줄 것이다.

 

void AGPCGun::BeginFire()
{
    MuzzleFlash->Activate(true);
    GunshotSound->Play();
}

총알 발사 시, GPCGun 클래스의 BeginFire()이 호출될 것이다. 이곳에서 MuzzleFlash의 Activate()를 부르며, bReset의

여부를 정해준다. (bReset은 Activate될 시 다시 처음부터 활성화될 지의 여부를 묻는다)

 

GunshotSound는 Play()를 통해 소리를 재생해준다. Play()를 사용함으로 써, 연발로 사격 시 사운드의 트랙이 하나씩 생성되어 각자 재생되게 된다.

 

ParticleSystem / Audio Component에 직접 바인드

이제 MyGPCGun 블루프린트로 돌아와서 각 Component들에 해당하는 것들을 직접 바인드 해주었다. (Rifle로 선택)


총알(Bullet) 클래스 만들기

언리얼 에디터에서 새 C++클래스 - 부모 클래스 Actor 선택 - GPCBullet 클래스로 하나 만들어준다.

 

GPCBullet 클래스로 와서, 헤더파일에 먼저 사용하게될 컴포넌트들을 선언해주었다.

UCLASS(Abstract)
class GPC_CPP_12_API AGPCBullet : public AActor
{
	GENERATED_BODY()
	
public:	
	AGPCBullet();

protected:
	void BeginPlay() override;

public:	
	void Tick(float DeltaTime) override;

private:
	UPROPERTY(VisibleAnywhere)
		class USphereComponent* Collider;

	UPROPERTY(VisibleAnywhere)
		class UParticleSystemComponent* Tracer;

	UPROPERTY(VisibleAnywhere)
		class UProjectileMovementComponent* Movement;
};
class USphereComponent* Collider;

총알에 피격을 감지할 Collider 를 SphereComponent로 만듬

 

class UParicleSystemComponent* Tracer;

총알에 파티클을 활성화시켜줄 Tracer 선언

 

class UProjectileMovementComponent* Movement;

총알 발사체의 움직임을 다룰 발사체 무브먼트 컴포넌트 Movement


이어서 GPCBullet 클래스의 cpp에는 다음과 같이 정의하였다.

#include "GPCBullet.h"
#include "Particles/ParticleSystemComponent.h"
#include "Components/SphereComponent.h"
#include "GameFramework/ProjectileMovementComponent.h"
#include "GPC_CPP_12.h"

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

	InitialLifeSpan = 5; //투사체 수명

	CreateDefaultSubobjectAuto(Collider);
	SetRootComponent(Collider); //Collider를 Root Component로 설정

	CreateDefaultSubobjectAuto(Tracer);
	Tracer->SetupAttachment(Collider); //Tracer를 Collider에 붙임

	CreateDefaultSubobjectAuto(Movement);
	Movement->InitialSpeed = 5000; //투사체의 속도 설정
	Movement->bRotationFollowsVelocity = true;
}

void AGPCBullet::BeginPlay()
{
	Super::BeginPlay();
	
}

void AGPCBullet::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

}

 

먼저 앞 헤더파일에서 추가한 Component들을 사용하기 위해 해당 헤더파일들을 먼저 포함시켜준다.

#include " Particles/ParticleSystemComponent.h"
#include " Components/SphereComponent.h"
#include "GameFramework/ProjectileMovementComponent.h"
#include "GPC_CPP_12.h"

 

그리고 AGPCBullet() 생성자에서 InitialLifeSpan(투사체의 수명)을 5로 설정해주었다.

CreateDefaultSubobjectAuto()를 통해 Collider와 Tracer, Movement 인스턴스를 생성해주고, Collider를 SetRootComponent()를 통해 Root로 설정해주었다.

그리고 Tracer는 Collider에 SetupAttachment()로 붙여주었다.

 

Movement의 InitialSpeed(초기 속도)는 5000으로 설정해주고, bRotationFollowsVelocity를 활성화시켜준다.

* RotationFollowsVelocity : 회전이 속도에 따라감. 발사체가 속도의 방향에 맞춰 매 프레임 회전을 업데이트함


MyGPCBullet 블루프린트 생성

GPCBullet 클래스의 정의를 마치고 빌드 후, 언리얼 에디터에서 GPCBullet 클래스를 기반으로 블루프린트를 생성해준다.

(MyGPCBullet 블루프린트 생성)

 

이제 블루프린트의 Tracer(ParticleSystemComponent) 컴포넌트에서 해당 Tracer 파티클을 직접 바인딩해준다.

 

MyGPCBullet의 뷰포트로 보면 Sphere Collider와 Tracer Particle이 보일 것이다.

Tracer의 위치를 X : -65.0 만큼 이동시켜 좀 더 자연스러운 위치로 옮겨주었다.


GPCGun 클래스에서 총알 발사하기

먼저 GPCGun에서 Mesh를 가져다 쓸 수 있도록 GPCWeapon 클래스의 Mesh 접근지정자를 protected: 로 바꿔주었다.

 

이어서 GPCGun 클래스의 헤더파일이다.

UCLASS(Abstract)
class GPC_CPP_12_API AGPCGun : public AGPCWeapon
{
	GENERATED_BODY()
public:
	AGPCGun();

	void OnConstruction(FTransform const& Transform) override;

protected:
	void BeginPlay() override;
.
.
.
private:
	UPROPERTY(EditDefaultsOnly, Meta = (AllowPrivateAccess))
		TSubclassOf<class AGPCBullet> BulletClass;
};

GPCGun 클래스에서 먼저 BeginPlay() 함수를 선언해주었다.

BeginPlay() 함수에서는 Bullet을 미리 생성해두는 역할을 할 것이다.

 

TSubclassOf<class AGPCBullet> BulletClass;

그리고 GPCBullet 클래스를 담을 BulletClass를 만들고, 이는 MyGPCGun 블루프린트로 와서 BulletClass에 직접 MyGPCBullet을 바인딩 해주었다.

블루프린트에서 BulletClass에 직접 바인딩


그리고 GPCGun 클래스의 cpp파일로 와서, BeginFire()가 호출될 시, 총알이 발사되도록 구현 중이었다.

일단 구현 도중이라 지금은 작동 안됨

void AGPCGun::BeginFire()
{
    MuzzleFlash->Activate(true);
    GunshotSound->Play();

    FTransform Muzzle = Mesh->GetSocketTransform(MuzzleSocket);

    Muzzle.SetLocation(Muzzle.GetLocation() + Muzzle.GetRotation().GetForwardVector() * 25);

    GetWorld()->SpawnActor<AActor>(BulletClass, Muzzle);

    //FActorSpawnParameters;
}