[UE5] 재질별 캐릭터 발소리 구현 & 배경음악 넣기

연하·2024년 7월 18일
0

Trapper

목록 보기
24/32
post-thumbnail

재질별 캐릭터 발소리 구현

트래퍼에는 이렇게 땅, 물, 콘크리트 세 종류의 바닥 재질이 있다. 재질별로 발소리를 다르게 해줘야 했다. 밑의 유튜브에서 설명이 잘 되어 있어서, 따라가며 작업했다. 나중에 또 필요할 때를 대비해 여기에 정리해두겠다 :)

https://youtu.be/TzGqRIioBbY?si=KrwM0WA1dYWcbWyO

먼저 해당하는 사운드 큐를 만들어줘야한다.

모든 사운드 큐는 내부적으로 여러개의 사운드를 랜덤으로 재생한다.

사용할 사운드 큐를 모두 만들었다면, 프로젝트 세팅의 Engine - Physics - Physics Surface 로 이동해 이름을 지어주면 된다. 나는 세개를 사용할 것이므로, Ground / Water / Concrete 이렇게 사용해주었다.

이제 피직스 머테리얼을 만들어주자. 각각 머테리얼마다 아까 만들어준 Surface Type을 설정해주면 된다.

레벨에 배치된 캐릭터가 걸어다닐 액터들을 선택하고 방금 만들어준 피직스 머테리얼을 설정해주었다.

발소리는 몽타주 내에서 이벤트로 처리해줄 것이기 때문에, AnimNotify를 상속받은 블루프린트를 만들어주자.

Override - Received Notify를 선택해주면, 이제 노드를 구현할 차례이다.

먼저 Mesh Comp에서 Owner를 받아와준 뒤, 액터의 로케이션을 가져와 새로운 벡터를 만들어 줘야한다. Z값에 캐릭터로부터 캐릭터가 밟고있는 지면까지 레이를 쏠 수 있도록 적당한 값을 빼주면 되는데, 나는 캐릭터의 캡슐 컴포넌트를 가져와 빼주고 추가로 작은 값을 더 빼주었다. 만약 소리가 나지 않는다면 디버그 라인을 사용해 지면에 레이가 정확히 히트되는지 파악해보는걸 추천 :)

라인 트레이스의 Start에 액터의 위치를 넣어주고, End에는 방금 만들어준 벡터를 연결해주자. 여기서 캐릭터를 Actors to Ignore에 추가해주는게 중요하다. 이걸 해주지 않으면,

라인 트레이스에서 캐릭터를 판정해버려 그냥 디폴트로 설정한 소리가 나게 된다.

Actors to Ignore 배열을 정확히 지정해주면 이렇게 바닥에 잘 히트되는 것을 볼 수 있음!

이제 Branch를 통해 히트한 결과가 있다면 사운드 재생, 없다면 리턴해주면 된다.

Out Hit에서 Surface Type을 받아와 Select 노드의 인덱스로 넣어주고, 종류에 따라 사운드를 처리해주면 된다. Spawn Attached 노드의 Location에는 히트한 위치를 넣어주고, Sound에는 방금 Select에서 리턴된 값을 넣어주면 된다.

사실 로직 자체가 간단해서 C++로 구현해볼까 했지만.. 귀찮았다..ㅎㅎ 언젠가 시간이 있으면 바꿔보는걸로..

이제 애니메이션 시퀀스나 몽타주에 내가 만든 블루프린트를 노티파이로 추가해주면 끝!

물 발소리가 나지 않는 현상 해결

왜인지 모르겠지만.. 나는 다 적용하고 나서도 캐릭터가 걸을 때 물 발자국 소리가 나질 않고, 땅 발자국 소리만 계속 났다. 라인으로 디버그를 찍어봐도 물쪽에 Hit 처리가 안되는걸 보니 콜리전 채널이 문제인가 싶었는데, 라인트레이스 채널을 Block으로 바꿔줘도 같은 현상이 일어났었다. 이것저것 옵션을 바꿔봐도 해결이 안되어서, 일단은 피직스 볼륨을 사용해 예외적으로 처리해주었다.

피직스 볼륨을 물이 있는 쪽에 넓게 깔아주면 정상적으로 트레이스되며 물 발소리가 재생된다. 땅 재질보다 살짝 낮게 깔아두어서 땅 위로 올라가면 정상적으로 땅 발소리가 재생된다!

배경음악 재생하기

우리 게임은 레벨마다 배경음악이 다르므로, 레벨이 배경음악 재생을 맡도록 했다.

C++ 코드에서 배경음악 재생을 명령할 것이므로, LevelScriptActor를 상속받은 TrapperScriptActor를 하나 만들어주었다.

UCLASS()
class TRAPPERPROJECT_API ATrapperScriptActor : public ALevelScriptActor
{
	GENERATED_BODY()
	
public:
	UFUNCTION(BlueprintImplementableEvent)
	void ChangeBackgroundSound(float FadeOutTime);

	virtual void BeginPlay() override;
};

void ATrapperScriptActor::BeginPlay()
{
	Super::BeginPlay();

	ChangeBackgroundSound(0.f);
}

BlueprintImplementableEvent 로 함수를 하나 만들어주었고, BeginPlay 함수에서는 맨 처음 배경음악을 재생하기 위해 해당 함수를 호출해주었다.

트래퍼 레벨의 Parent Class를 방금 만든 TrapperScriptActor로 지정해주고,

받은 FadeOutTime 값에 따라 Fade Out을 진행,

레벨에서 재생을 담당할 오디오 컴포넌트를 가진 BGM Manager 액터를 하나 만들어 준 뒤 타겟으로 넣어주었다.

지정한 시간이 끝난 뒤에 Change BGM 함수를 실행한다.

게임 스테이트를 캐스팅한 후, 현재 Game Progress를 가져와 해당 모드에 따라 BGM을 골라서 재생하도록 만들어주었다.
(이거때문에 게임모드에 있던 Current Game Progress 변수를 Game State로 옮기는 과정도 거쳤다. 언제 다 옮기지.. 번거로우니까 포스팅에서는 생략하겠다)

void ATrapperGameMode::SetGameProgress(EGameProgress Progress)
{
	EGameProgress PreviousProgress = TrapperGameState->CurrentGameProgress;

	if (PreviousProgress != Progress)
	{
		TrapperGameState->CurrentGameProgress = Progress;
		TrapperGameState->OnRep_GameProgressSetting();
	}
        
// 생략...

void ATrapperGameState::OnRep_GameProgressSetting()
{
	UE_LOG(LogTemp, Warning, TEXT("Change Background"));

	ALevelScriptActor* LevelScriptActor = GetWorld()->GetLevelScriptActor();
	ATrapperScriptActor* MyLevelScriptActor = Cast<ATrapperScriptActor>(LevelScriptActor);
	if (MyLevelScriptActor)
	{
		MyLevelScriptActor->ChangeBackgroundSound(3.f);
	}
}

CurrentGameProgress가 바뀔때마다 ChangeBackgroundSound 함수를 호출하도록 해주었다. OnRep 함수로 지정했기 때문에, 클라이언트에서도 잘 적용된다.

효과음 적용

캐릭터와 관련된 효과음들은 애니메이션 시퀀스나 몽타주에서 간단하게 설정할 수 있으므로, 캐릭터의 목소리, 점프, 솔루나 시프트 등 여러가지를 적용해주었다.

0개의 댓글