
이제 부숴지는 항아리는 만들었으니 부숴졌을 때 보물같은 것이 나오도록 구현해보자
우선 fab에서 무료 보물 에셋을 다운받아주자.
https://www.fab.com/ko/listings/a4c1584f-e305-4562-ad37-4c1483e09a10

다운받은 다음 보물이 나타날때 소리효과를 추가하기 위해 다음 사이트에서 Coin sfx를 하나 다운받아주자.
Soundimage.org | Thousands of free music tracks, sounds and images for your projects by Eric Matyas
“Ancient Mars”_Looping (You can freely download this music track in MP3 format from my Sci-Fi 12 page…enjoy!) ______________________________________________________________________________ The purpose of this site to make good-sounding music, sound
soundimage.org
mp3로 다운받아 질텐데 wav로 변환한 다음 임포트해주고 이를 바탕으로 meta sound를 만들어주자.

이렇게 해준 다음 아이템 클래스를 상속받는 Treasure 클래스를 생성해주자.

이때 OnSphereOverlap 함수를 가져와서 재정의 해줄것이다. 이때 파생클래스는 UFUNCTION을 사용할 수 없다.
플레이와 overlap될 때 보물이 없어지고 소리가 재생되도록 해주자.
Treasure.h
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "Items/Item.h"
#include "Treasure.generated.h"
/**
*
*/
UCLASS()
class SLASH_API ATreasure : public AItem
{
GENERATED_BODY()
protected:
virtual void OnSphereOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult) override;
private:
UPROPERTY(EditAnywhere, Category = Sounds)
USoundBase* PickupSound;
};
Treasure.cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "Items/Treasure.h"
#include "Characters/SlashCharacter.h"
#include "Kismet\GameplayStatics.h"
void ATreasure::OnSphereOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
ASlashCharacter* SlashCharacter = Cast<ASlashCharacter>(OtherActor);
if (SlashCharacter)
{
if (PickupSound)
{
UGameplayStatics::PlaySoundAtLocation(
this,
PickupSound,
GetActorLocation()
);
}
Destroy();
}
}
컴파일해준 다음 이 클래스를 기반으로 블루프린트 클래스를 만들어주자. 만들어준 다음 소리를 추가해주고 매쉬를 적당한 매쉬로 추가해주자.



항아리가 깨졌을 때 스폰되게 만들어야하지만 일단 함수가 올바르게 작동하는지 확인하기 위해 씬에 하나 배치해보자.
시작하고 가까이 다가가면 소리가 재생되면서 없어지는 것을 볼 수 있다.


이제 항아리가 부숴지면 항아리가 있던 자리 중앙에 보물이 생성되게 만들어야한다. 이를 코드로 구현해보자. SpawnActor 함수를 통해 소환해줄 수 있다.
이때 함수의 정의와 매개변수에 대해 찾아보면 UClass를 매개변수로 받고있는 것을 볼 수 있다.

우선 코드상에서 각 클래스를 지정해주는 변수에 대해 알아보면 다음과 같다.
UClass 변수를 지정해주고 블루프린트상에서 할당해주면 블루프린트 클래스를 가져다가 쓸수 있다.

항아리가 부숴질때 Actor를 Spawn하기 위해 Breakable 클래스에 UClass변수를 추가해주자.
BreakableActor.h
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Interfaces/HitInterface.h"
#include "BreakableActor.generated.h"
class UGeometryCollectionComponent;
UCLASS()
class SLASH_API ABreakableActor : public AActor, public IHitInterface
{
GENERATED_BODY()
private:
UPROPERTY(EditAnywhere)
UClass* TreasureClass;
};
이렇게 해주고 블루프린트상에서도 할당을 해주자.

이렇게 해주고 SpawnActor에서 이 변수를 매개변수로 사용하면 C++클래스 대신 블루프린트 클래스가 소환된다.
BreakableActor.cpp
void ABreakableActor::GetHit_Implementation(const FVector& ImpactPoint)
{
UWorld* World = GetWorld();
if (World && TreasureClass)
{
FVector Location = GetActorLocation();
Location.Z += 75.f;
World->SpawnActor<ATreasure>(TreasureClass, Location, GetActorRotation());
}
}
컴파일 해주면 보물이 잘 생성되는 것을 볼 수 있다.

이때 UClass 변수로 생성해줬기 때문에 할당할 수 있는 것에 제한이 없다. 이러한 점을 보완하기 위해서 TSubclassOf라는 변수를 사용한다.

BreakableActor.h
private:
UPROPERTY(VisibleAnywhere)
UGeometryCollectionComponent* GeometryCollection;
UPROPERTY(EditAnywhere)
TSubclassOf<class ATreasure> TreasureClass;
};
이렇게 해주고 컴파일해주면 선택할 수 있는 Actor가 제한되어있는것을 볼 수 있다.

그리고 여기서 부수고 난 다음에 충돌을 끄기 위해 UCapsuleComponent를 사용하자. 이것을 통해 Pawn이 통과하지 못하지만 깨지고 난 다음에는 지나다닐 수 있도록하자.
BreakableActor.h
protected:
UPROPERTY(VisibleAnywhere, BlueprintReadWrite)
class UCapsuleComponent* Capsule;
BreakableActor.cpp
#include "Breakable/BreakableActor.h"
#include "Components/CapsuleComponent.h"
#include "GeometryCollection/GeometryCollectionComponent.h"
#include "Items/Treasure.h"
ABreakableActor::ABreakableActor()
{
PrimaryActorTick.bCanEverTick = false;
GeometryCollection = CreateDefaultSubobject<UGeometryCollectionComponent>(TEXT("GeometryCollection"));
SetRootComponent(GeometryCollection);
GeometryCollection->SetGenerateOverlapEvents(true);
GeometryCollection->SetCollisionResponseToChannel(ECollisionChannel::ECC_Camera, ECollisionResponse::ECR_Ignore);
GeometryCollection->SetCollisionResponseToChannel(ECollisionChannel::ECC_Pawn, ECollisionResponse::ECR_Ignore);
Capsule = CreateDefaultSubobject<UCapsuleComponent>(TEXT("Capsule"));
Capsule->SetupAttachment(GetRootComponent());
Capsule->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Ignore);
Capsule->SetCollisionResponseToChannel(ECollisionChannel::ECC_Pawn, ECollisionResponse::ECR_Block);
}
이렇게 해주고 LifeSpan이 끝날때 이 캡슐과 Pawn의 충돌도 Ignore로 바꿔준다.

이렇게 해주면 잘 작동하는 것을 볼 수 있다.


'게임공부 > Unreal Engine' 카테고리의 다른 글
[Unreal Engine][C++]19. Actor Component (0) | 2025.01.14 |
---|---|
[Unreal Engine][C++]18. Treasure2 (0) | 2025.01.03 |
[Unreal Engine][C++]16. Breakable Actors2 (1) | 2025.01.02 |
[Unreal Engine][C++]15. Breakable Actors (0) | 2024.12.31 |
[Unreal Engine][C++]14. Hit React (3) | 2024.12.27 |