박스에서 나쁜 아이템 나오면 10초간 하이더 위치에서 소리 -> 술래한테 위치 노출

 

복제 변수 말고 Multicast로 생성

투명화는 복제 bool이었음 -> 지속 상태 (5초간 투명한 상태니까)

소리는 사건 -> 한 번 울리기 시작하면 사운드 파일이 알아서 재생됨

  방식 예시
상태 복제 변수 + OnRep bIsItemInvisible (5초간 투명)
사건 Multicast 소리 재생 시작

 

SpawnSoundAttached vs SpawnSoundAtLocation

Attached를 써야 함

하이더가 소리 나면서 도망가면 -> 소리도 따라가야 술래가 실시간 추적 가능

 

 

FDHiderCharacter.h

public:
    // 소리 아이템 발동 - Duration초간 재생 후 자동 정지
    UFUNCTION(NetMulticast, Reliable)
    void Multicast_PlayNoise(float Duration);

private:
    // 소리 아이템용 사운드 (에디터에서 할당, Looping 설정 필요)
    UPROPERTY(EditDefaultsOnly, Category = "Item")
    class USoundBase* NoiseSound;

    // 재생 중인 소리 - 타이머로 정지시키려면 붙잡고 있어야 함
    UPROPERTY()
    class UAudioComponent* ActiveNoiseAudio;

    FTimerHandle NoiseStopTimerHandle;

    void StopNoise();

 

FDHiderCharacter.cpp

#include "Components/AudioComponent.h"
#include "Kismet/GameplayStatics.h"
#include "Sound/SoundBase.h"

void AFDHiderCharacter::Multicast_PlayNoise_Implementation(float Duration)
{
    if (!NoiseSound)
    {
        return;
    }

    // 이미 소리가 나고 있으면 먼저 정지 (중복 재생 방지)
    StopNoise();

    // 리턴값을 붙잡아둬야 나중에 Stop()을 부를 수 있음
    ActiveNoiseAudio = UGameplayStatics::SpawnSoundAttached(
        NoiseSound,
        GetRootComponent(),
        NAME_None,
        FVector::ZeroVector,
        FRotator::ZeroRotator,
        EAttachLocation::SnapToTarget,
        true,       // bStopWhenAttachedToDestroyed - 하이더 사라지면 소리도 멈춤
        1.f,        // VolumeMultiplier
        1.f,        // PitchMultiplier
        0.f,        // StartTime
        nullptr,    // AttenuationSettings
        nullptr,    // ConcurrencySettings
        false       // bAutoDestroy <- false! 우리가 Stop 부를 때까지 살아있어야 함
    );

    if (!ActiveNoiseAudio)
    {
        return;
    }

    // Duration 뒤 자동 정지
    GetWorldTimerManager().SetTimer(
        NoiseStopTimerHandle,
        this,
        &AFDHiderCharacter::StopNoise,
        Duration,
        false);
}

void AFDHiderCharacter::StopNoise()
{
    if (ActiveNoiseAudio)
    {
        ActiveNoiseAudio->Stop();
        ActiveNoiseAudio = nullptr;
    }

    GetWorldTimerManager().ClearTimer(NoiseStopTimerHandle);
}

 

FDItemInventoryComponent.cpp - ExecuteEffect

    // 소리
case EFDItemEffect::Noise:
{
    Hider->Multicast_PlayNoise(Data.Duration);   // Duration 전달
    break;
}

 

 

 

에디터 작업

1) 사운드 Looping 설정

Cue를 쓰려면 그래프에 Looping 노드를 넣어야 함

단순 반복이면 그냥 Sound Wave를 직접 슬롯에 넣는 게 간단

 

2) BP_FDHiderCharacter -> Details -> Item

  • Noise Sound 슬롯에 Looping 켠 Sound Wave 할당

3) DT_ItemData

  • ForcedEmote 행 삭제
  • Noise 행의 Duration = 10.0
  • DrawWeight 재조정
Invisibility Invisibility true 5.0 20
TaggerStun TaggerStun true 5.0 20
Noise Noise false 10.0 60

 

 


알게된 것

SpawnSoundAttached는 핸들을 돌려준다

재생 중인 소리를 대표하는 UAudioComponent*를 반환

이걸 안 붙잡으면 끌 방법이 없음

 

bAutoDestroy = false

기본값 true = 사운드 끝나면 언리얼이 알아서 컴포넌트 지움

직접 Stop()을 부를 거라 false로 해서 참조가 유효하게 유지되도록 해야 함

+ Recent posts