이번에는 몬스터를 스폰해보자.
몬스터를 스폰하는 건 어렵지 않다.
몬스터 스폰하기
먼저 몬스터의 스폰을 관리하는 액터를 만들고 이 액터를 필요한 Room에서 가지고 있도록 해보자.
Spawner의 역할인 것이다.
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "RASMonsterSpawner.generated.h"
UCLASS()
class PROJECTRAS_API ARASMonsterSpawner : public AActor
{
GENERATED_BODY()
public:
ARASMonsterSpawner();
UFUNCTION(BlueprintCallable)
void SpawnCreature();
UFUNCTION()
void CheckClearRoom();
void SetRoom(class ARASRoom* InRoom, bool bMonsterSpawn) { OwnRoom = InRoom; bIsMonsterSpawn = bMonsterSpawn; }
protected:
virtual void BeginPlay() override;
public:
virtual void Tick(float DeltaTime) override;
protected:
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Spawn")
TArray<TSubclassOf<class ARASMonster>> MonsterClasses;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Spawn")
int32 MaxMonsterCount;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Spawn")
int32 MinMonsterCount;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Spawn")
bool bIsSpawned;
int SpawnCount;
TObjectPtr<class ARASRoom> OwnRoom;
bool bIsMonsterSpawn = false;
};
최소 스폰 몬스터의 수와 최대를 지정해두고 소환하고자 하는 몬스터의 클래스를 에디터에서 지정해주면 된다.
그리고 에디터에서 콜리전 박스를 추가하고 그 것을 블루프린트로 호출하기 위해 BlueprintCallable로 설정해두었다.
// Fill out your copyright notice in the Description page of Project Settings.
#include "Map/RASMonsterSpawner.h"
#include "Character/Monster/RASMonster.h"
#include "Map/RASRoom.h"
// Sets default values
ARASMonsterSpawner::ARASMonsterSpawner()
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
MaxMonsterCount = 3;
MinMonsterCount = 2;
SpawnCount = 0;
bIsSpawned = false;
}
void ARASMonsterSpawner::SpawnCreature()
{
if (bIsSpawned || bIsMonsterSpawn == false)
{
return;
}
if(OwnRoom == nullptr)
{
return;
}
OwnRoom->CloseDoors();
bIsSpawned = true;
SpawnCount = FMath::RandRange(MinMonsterCount, MaxMonsterCount);
FActorSpawnParameters SpawnParams;
SpawnParams.SpawnCollisionHandlingOverride =
ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn;
const FVector Center = GetActorLocation();
for (int32 i = 0; i < SpawnCount; ++i)
{
const int32 Idx = FMath::RandRange(0, MonsterClasses.Num() - 1);
TSubclassOf<ARASMonster> MonsterClass = MonsterClasses[Idx];
if (!MonsterClass) { continue; }
const float OffX = FMath::RandRange(-600.f, 600.f);
const float OffY = FMath::RandRange(-600.f, 600.f);
FVector Pos = Center + FVector(OffX, OffY, 0.f);
FHitResult Hit;
const FVector Start = Pos + FVector(0.f, 0.f, 200.f);
const FVector End = Pos - FVector(0.f, 0.f, 200.f);
if (GetWorld()->LineTraceSingleByChannel(Hit, Start, End, ECC_WorldStatic))
{
Pos.Z = Hit.Location.Z;
}
const float RandomYaw = FMath::RandRange(-180.f, 180.f);
const FRotator Rot(0.f, RandomYaw, 0.f);
ARASMonster* Monster = GetWorld()->SpawnActor<ARASMonster>(MonsterClass, Pos, Rot, SpawnParams);
Monster->OnRoomClear.BindUObject(this, &ARASMonsterSpawner::CheckClearRoom);
}
bIsSpawned = true;
}
void ARASMonsterSpawner::CheckClearRoom()
{
SpawnCount--;
if (SpawnCount > 0)
{
return;
}
if (OwnRoom == nullptr)
{
return;
}
OwnRoom->OpenDoors();
}
void ARASMonsterSpawner::BeginPlay()
{
Super::BeginPlay();
}
void ARASMonsterSpawner::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
정해진 위치에 랜덤하게 스폰하게 된다.

옷 설정하기
지금 보스의 스켈레톤 메쉬를 보면 파라곤에서 제공하는 것을 그대로 사용하고 있기 때문에
옷 부분도 하나의 뼈로 지정되어 있어 부자연스러운 움직임을 보인다.
그래서 스켈레톤 메쉬에서 Clothes를 설정해보자.

clothing Data를 만들어 주고 이걸 색칠을 통해 활성화 하고 싶은 영역을 칠해준다.

하얗게 칠해진 부분은 이제 Clothes로 인정될 것이다.
그리고 LOD를 0으로 설정한 다음
Number Lod를 1로 설정한다.
바람을 넣어 테스트 해보면 다음과 같다.

'Unreal Engine 5 > ProjectRAS' 카테고리의 다른 글
| [UE5] ProjectRAS - 미니맵, 월드맵 만들기 (1) | 2025.06.23 |
|---|---|
| [UE5] ProjectRAS - 메인 Title UI와 메뉴 UI 만들기 (0) | 2025.06.11 |
| [UE5] ProjectRAS - UI 스킬 쿨타임 과 포션 마시기 (0) | 2025.05.21 |
| [UE5] ProjectRAS - 보스 패턴 제작하기 (0) | 2025.05.16 |
| [UE5] ProjectRAS - Map Generator (0) | 2025.04.23 |