0. 개요
TargetPoint 액터를 상속받는 클래스와 액터를 상속받는 몬스터 소환 볼륨을 이용하여, 특정 위치에서 몬스터가 소환되도록 한다.
1. 몬스터 소환
(1) C++ 클래스 생성
TargetPoint 액터를 상속받는 AuraEnemySpawnPoint 클래스와, 액터를 상속받는 AuraEnemySpawnVolume 클래스를 생성한다.
(2) AuraCharacterBase에서 캐릭터 클래스 Setter 선언
void SetCharacterClass(ECharacterClass InClass) {CharacterClass = InClass;}
SpawnActorDeffered로 소환된 적의 클래스를 변경할 수 있도록 Setter를 선언한다.
(3) AuraEnemy에서 몬스터 레벨 Setter 선언
void SetLevel(int32 InLevel) {Level = InLevel;}
(3) AuraEnemySpawnPoint 클래스
#pragma once
#include "CoreMinimal.h"
#include "AbilitySystem/Data/CharacterClassInfo.h"
#include "Engine/TargetPoint.h"
#include "AuraEnemySpawnPoint.generated.h"
class AAuraEnemy;
UCLASS()
class AURA_API AAuraEnemySpawnPoint : public ATargetPoint
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintCallable)
void SpawnEnemy();
public:
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Enemy Class")
TSubclassOf<AAuraEnemy> EnemyClass;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Enemy Class")
int32 EnemyLevel = 1;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Enemy Class")
ECharacterClass CharacterClass = ECharacterClass::Warrior;
};
void AAuraEnemySpawnPoint::SpawnEnemy()
{
// 액터 스폰 파리미터
FActorSpawnParameters SpawnParams;
SpawnParams.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn;
AAuraEnemy* Enemy = GetWorld()->SpawnActorDeferred<AAuraEnemy>(EnemyClass, GetActorTransform());
Enemy->SetLevel(EnemyLevel);
Enemy->SetCharacterClass(CharacterClass);
Enemy->FinishSpawning(GetActorTransform());
Enemy->SpawnDefaultController();
}
- Spawn Collision Handling Override = Adjust If Possible But Always Spawn
액터 스폰 시 해당 위치에 맞게 조정 가능하다면 조정하고, 불가능 하더라도 일단 소환하도록 하는 옵션이다.
- SpawnDefaultController
적에게 AI 관련 기능(블랙 보드, 비헤이비어 트리)를 사용할 수 있도록 게임모드의 기본 컨트롤러를 부여한다.
(4) AuraEnemySpawnVolume
플레이어 캐릭터가 해당 볼륨에 닿으면 적을 소환한다.
캐릭터가 볼륨에 닿은 것은 불리언으로 관리되어, 레벨을 왔다갔다해도 다시 몬스터를 소환하지 않도록 한다.
#pragma once
#include "CoreMinimal.h"
#include "AuraEnemySpawnPoint.h"
#include "GameFramework/Actor.h"
#include "Interaction/SaveInterface.h"
#include "AuraEnemySpawnVolume.generated.h"
class UBoxComponent;
UCLASS()
class AURA_API AAuraEnemySpawnVolume : public AActor, public ISaveInterface
{
GENERATED_BODY()
public:
AAuraEnemySpawnVolume();
public:
/* 저장 인터페이스 시작*/
virtual void LoadActor_Implementation() override;
/* 저장 인터페이스 끝*/
UPROPERTY(BlueprintReadOnly, SaveGame)
bool bReached = false;
protected:
virtual void BeginPlay() override;
UFUNCTION()
virtual void OnSphereOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);
UPROPERTY(EditAnywhere)
TArray<AAuraEnemySpawnPoint*> SpawnPoints;
private:
UPROPERTY(VisibleAnywhere)
TObjectPtr<UBoxComponent> Box;
};
(4-1) 생성자
AAuraEnemySpawnVolume::AAuraEnemySpawnVolume()
{
PrimaryActorTick.bCanEverTick = false;
Box = CreateDefaultSubobject<UBoxComponent>("Box");
SetRootComponent(Box);
Box->SetCollisionEnabled(ECollisionEnabled::QueryOnly);
Box->SetCollisionObjectType(ECC_WorldStatic);
Box->SetCollisionResponseToChannels(ECR_Ignore);
Box->SetCollisionResponseToChannel(ECC_Pawn, ECR_Overlap);
}
박스 컴포넌트를 생성하고, 캐릭터와의 충돌을 감지할 것이다.
모든 채널에 대해 무시하고, Pawn 클래스에 대해 겹침을 판정한다.
(4-2) BeginPlay에서 콜리전 콜백 함수 바인딩
void AAuraEnemySpawnVolume::BeginPlay()
{
Super::BeginPlay();
Box->OnComponentBeginOverlap.AddDynamic(this, &AAuraEnemySpawnVolume::OnSphereOverlap);
}
(4-3) 콜리전 콜백 함수
void AAuraEnemySpawnVolume::OnSphereOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor,
UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
// 부딫힌 액터가 플레이어가 아니면 리턴
if (OtherActor->Implements<UPlayerInterface>() == false)
return;
bReached = true;
for (AAuraEnemySpawnPoint* Point : SpawnPoints)
{
if (IsValid(Point))
{
Point->SpawnEnemy();
}
}
Box->SetCollisionEnabled(ECollisionEnabled::NoCollision);
}
- OtherActor를 체크하여 Aura 플레이어가 아니면 리턴한다.
- 제공된 SpawnPoints 배열에 대해 적을 소환한다.
- 종료 후, 콜백 함수가 다시 호출되지 않도록 콜리전을 비활성화한다.
게임을 다시 로드할 때에는 bReached 변수로 인해 이 액터가 재생성되지 않을 것이다.
(4-4) SaveInterface의 LoadActor 오버라이드
void AAuraEnemySpawnVolume::LoadActor_Implementation()
{
if (bReached)
{
Destroy();
}
}
이미 이 볼륨 액터에 도달한 적이 있다면 파괴한다.
(5) 볼륨에 닿으면 특정 위치에 적이 소환되게 하기
(5-1) BP_SpawnPoints 클래스 디폴트 지정 후 배치
(5-2) BP_SpawnVolume 클래스 디폴트에 스폰 포인트 추가
'UE 5 스터디 > Gameplay Ability System(GAS)' 카테고리의 다른 글
30-10. 아이템 - (1) 아이템 드랍 (0) | 2025.04.16 |
---|---|
30-9. 레벨 디자인 - (2) 플레이어 사망 (0) | 2025.04.16 |
30-7. 맵 이동 - (7) 모델링 모드 - 던전 입구 계단 (0) | 2025.04.15 |
30-6. 맵 이동 - (6) 맵 이동 입구 액터를 클릭해 맵 이동하기 (0) | 2025.04.11 |
30-5. 맵 이동 - (5) 체크 포인트를 상속받는 블루프린트 클래스 - 빛 기둥 (0) | 2025.04.11 |