Unreal - 자동 흡수되는 확률형 드롭 아이템 만들기

2025. 5. 22. 20:40·Unreal5 프로젝트 다이어리

적을 죽이면 스폰되는 아이템을 만들고싶습니다

드랍되는 종류는 총 3가지

1. 재화 ( 100 % )

2. 장비 ( 25% )

3. 포션 ( 50% )

 

아이템의 부모가 될 C++클래스를 생성후 콜리전 그리고 메시를 할당해줍니다

ADropActor::ADropActor()
{
	PrimaryActorTick.bCanEverTick = true;
	sceneComp = CreateDefaultSubobject<USceneComponent>(TEXT("SceneComp"));
	RootComponent = sceneComp;
	sphereComp = CreateDefaultSubobject<USphereComponent>(TEXT("SphereComp"));
	sphereComp->SetupAttachment(RootComponent);
	meshComp = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("MeshComp"));
	meshComp->SetupAttachment(RootComponent);
}

 

해당 액터가 플레이어가 근처에 오면 플레이어한테 빨려들어가듯이 이동하게 해보겠습니다

Iterator로 플레이어를 찾고 플레이어가 반경 500만큼 안에 있으면 FInterpTo로 부드럽게 이동합니다

void ADropActor::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);
	for (TActorIterator<ASwordCharacter>it(GetWorld()); it; ++it)
	{
		ASwordCharacter* swordCharacter = *it;
		if (swordCharacter)
		{
			float distance = FVector::Dist(this->GetActorLocation(), swordCharacter->GetActorLocation());
			if (distance <= 500.f)
			{
				FVector moveNewLoc = FMath::VInterpTo(GetActorLocation(), swordCharacter->GetActorLocation(), DeltaTime, 5.0f);
				SetActorLocation(moveNewLoc);
			}
		}
	}
}

 

 

오버랩 이벤트를 바인드해줍니다

오버랩 이벤트에서는 Destroy합니다 또한 관련된 변수를 누적시켜주시면됩니다

void ADropActor::BeginPlay()
{
	Super::BeginPlay();
	sphereComp->OnComponentBeginOverlap.AddDynamic(this, &ADropActor::OnBeginOverlapDropActor);	
}
void ADropActor::OnBeginOverlapDropActor(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
	if (OtherActor->GetName().Contains("SwordCharacter"))
	{
		Destroy();
	}
}

 

알맞은 액터 에셋을 적용시키고 크기를 조절합니다

 

AI로부터 스폰하게 해보겠습니다

AI의 BehaviorTree에서 죽음을 담당하는 Task에서 스폰시키겠습니다

UPROPERTY(EditAnywhere, Category="MySettings")
TSubclassOf<AActor> moneyActor;

UPROPERTY(EditAnywhere, Category = "MySettings")
TSubclassOf<AActor> gearActor;

UPROPERTY(EditAnywhere, Category = "MySettings")
TSubclassOf<AActor> potionActor;

 

FMath::FRand는 0부터 1의 균등 분포 난수를 반환합니다 그러므로 0.25f는 25프로 0.5는 50프로를 뜻합니다

ABasicSkeletonEnemy* skeleton = Cast<ABasicSkeletonEnemy>(ownerComp.GetAIOwner()->GetPawn());
FVector spawnLoc = skeleton->GetActorLocation();
FRotator spawnRot = skeleton->GetActorRotation();
if (moneyActor)
{
	GetWorld()->SpawnActor<AActor>(moneyActor, spawnLoc, spawnRot);
}
if (gearActor && FMath::FRand() <= 0.25f)
{
	GetWorld()->SpawnActor<AActor>(gearActor, spawnLoc, spawnRot);
}
if (potionActor && FMath::FRand() <= 0.5f)
{
	GetWorld()->SpawnActor<AActor>(potionActor, spawnLoc, spawnRot);
}

 

 

확인을 위해 오버랩이벤트의 Destroy를 잠시 주석처리한뒤 확인해보겠습니다

 

임시로 포션과 장비에 큐브메시와 색 메테리얼을 입혀주었습니다

포션(임시)

 

장비(임시)

 

잘 스폰이 된다 그런데 먼가 문제점이 보입니다

1. 아이템이 공중에 떠있습니다

2. 스폰하는 위치가 같아 아이템의 위치를 오프셋의 필요성이있음

 

스폰위치를 ai의 캡슐컴포넌트의 바닥으로부터 스폰하는것으로 변경해줍니다

또한 오프셋을 적용하여 위치를 조절해줍니다

UCapsuleComponent* skeletonCapsuleComp = skeleton->FindComponentByClass<UCapsuleComponent>();
FVector capsuleCenterLoc = skeleton->GetActorLocation();
float capsuleHalfHeight = skeletonCapsuleComp->GetScaledCapsuleHalfHeight();
float capsuleRadius = skeletonCapsuleComp->GetScaledCapsuleRadius();
FVector spawnLoc = capsuleCenterLoc - FVector(0.f, 0.f, capsuleHalfHeight);
FRotator spawnRot = skeleton->GetActorRotation();

if (moneyActor)
{
	GetWorld()->SpawnActor<AActor>(moneyActor, spawnLoc, spawnRot);
}
if (gearActor && FMath::FRand() <= 0.25f)
{
	FVector gearOffset = FVector(0.f, 30.f, 0.f); 
	GetWorld()->SpawnActor<AActor>(gearActor, spawnLoc + gearOffset, spawnRot);
}
if (potionActor && FMath::FRand() <= 0.5f)
{
	FVector potionOffset = FVector(0.f, -30.f, 0.f); 
	GetWorld()->SpawnActor<AActor>(potionActor, spawnLoc + potionOffset, spawnRot);
}

 

 

각 아이템별로 흡수범위를 달리하겠습니다

UPROPERTY(EditAnywhere, Category = "MySettings")
float absorptionArea;
void ADropActor::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);
	for (TActorIterator<ASwordCharacter>it(GetWorld()); it; ++it)
	{
		ASwordCharacter* swordCharacter = *it;
		if (swordCharacter)
		{
			float distance = FVector::Dist(this->GetActorLocation(), swordCharacter->GetActorLocation());
			if (distance <= absorptionArea)
			{
				FVector moveNewLoc = FMath::VInterpTo(GetActorLocation(), swordCharacter->GetActorLocation(), DeltaTime, 5.0f);
				SetActorLocation(moveNewLoc);
			}
		}
	}
}

 

돈 흡수범위 500

 

장비,포션 흡수범위 300

 

'Unreal5 프로젝트 다이어리' 카테고리의 다른 글

Unreal - 플레이어 리스폰  (0) 2025.05.24
Unreal - 던전진행도 위젯 만들기 (스칼라 파라미터 조절하기)  (0) 2025.05.23
Unrela - 시퀀스 만들기 (AI편)  (0) 2025.05.22
Unreal - 부숴지는 벽 만들기 (Chaos Distruction)  (0) 2025.05.22
Unrela - 시퀀스 만들기 (캐릭터편)  (0) 2025.05.21
'Unreal5 프로젝트 다이어리' 카테고리의 다른 글
  • Unreal - 플레이어 리스폰
  • Unreal - 던전진행도 위젯 만들기 (스칼라 파라미터 조절하기)
  • Unrela - 시퀀스 만들기 (AI편)
  • Unreal - 부숴지는 벽 만들기 (Chaos Distruction)
lucodev
lucodev
커피와 노트북 그리고 개발
  • lucodev
    루코 개발테이블
    lucodev
  • 전체
    오늘
    어제
    • 분류 전체보기 (121) N
      • Unreal5 프로젝트 다이어리 (73)
      • Unreal5 프로젝트 다이어리2 (3) N
      • Unreal 팁 (8)
      • Unreal 디버깅 (8)
      • C++ 프로그래머스 다이어리 (21) N
        • Stack (3)
        • Hash (4)
        • Heap (2)
        • Sort (1) N
      • 코드 개인보관함 (8) N
  • 인기 글

  • 최근 글

  • 최근 댓글

  • 링크

  • 공지사항

  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 태그

    언리얼 로딩
    unreal 로딩
    언리얼 비헤이비어트리
    언리얼 시퀀스
    언리얼 motionmatching
    언리얼 look at
    언리얼
    unreal 시퀀스
    언리얼 컷씬
    unreal 컷씬
    언리얼 behaviortree
    언리얼 foot step
    unreal sequence
    언리얼 behavior tree
    unreal 모션매칭
    unreal look at
    언리얼 페이드 아웃
    언리얼 모션매칭
    unreal loading
    언리얼 로딩창
  • hELLO· Designed By정상우.v4.10.3
lucodev
Unreal - 자동 흡수되는 확률형 드롭 아이템 만들기
상단으로

티스토리툴바