언리얼 팀프로젝트

멀티 플레이어 (데디서버) NPC 랜덤 위치 스폰 액터 구현 -1

Turtle_Jun 2025. 9. 10. 22:16

NPC 액터를 스폰하는 클래스를 생성하여본다.

 

1. C++ 클래스 생성 >  Actor 부모 클래스 > DCNPCSpawnVolume 클래스 생성

 

- DCNPCSpawnVolume.h

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "DCNPCSpawnVolume.generated.h"

class ADCNPC;
class UBoxComponent;

UCLASS()
class DC_API ADCNPCSpawnVolume : public AActor
{
    GENERATED_BODY()

public:
    ADCNPCSpawnVolume();

protected:
    virtual void BeginPlay() override;

    FVector GetRandomPointInVolume() const; // 스폰 할 위치 랜덤 반환
    void SpawnNPC();

protected:
    UPROPERTY(VisibleAnywhere, Category = "Spawn Volume")
    USceneComponent* Root;

    UPROPERTY(VisibleAnywhere, Category = "Spawn Volume")
    UBoxComponent* SpawnBox;

    UPROPERTY(EditAnywhere, Category = "Spawn Volume")
    TSubclassOf<ADCNPC> NPCClass;

    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Spawn Volume")      // NPC 스폰할 수
    int32 SpawnCount;
};

 

 

- DCNPCSpawnVolume.cpp


#include "NPC/DCNPCSpawnVolume.h"

#include "Components/BoxComponent.h"
#include "NPC/DCNPC.h"
#include "Kismet/KismetMathLibrary.h"

ADCNPCSpawnVolume::ADCNPCSpawnVolume()
    :SpawnCount(0)
{
    bReplicates = true; // 리플리케이트 실행
    Root = CreateDefaultSubobject<USceneComponent>("Root");
    SetRootComponent(Root);

    SpawnBox = CreateDefaultSubobject<UBoxComponent>("SpawnBox");
    SpawnBox->SetupAttachment(Root);
    SpawnBox->SetCollisionEnabled(ECollisionEnabled::NoCollision);  // 충돌 비활성화
}

void ADCNPCSpawnVolume::BeginPlay()
{
    Super::BeginPlay();

    if (HasAuthority()) // 서버에서 실행
    {
        SpawnNPC();
    }
}

FVector ADCNPCSpawnVolume::GetRandomPointInVolume() const
{
    FVector BoxExtent = SpawnBox->GetScaledBoxExtent(); // Box 크기를 얻어옴
    FVector BoxOrigin = SpawnBox->GetComponentLocation();   // 박스의 중심위치

    return UKismetMathLibrary::RandomPointInBoundingBox(BoxOrigin, BoxExtent);  // 랜덤 위치 반환
}

void ADCNPCSpawnVolume::SpawnNPC()
{
    if (IsValid(NPCClass) == true)
    {
        for (int32 i = 0; i < SpawnCount; ++i)  // Count 만큼 NPC 스폰
        {
            GetWorld()->SpawnActor<ADCNPC>(
                NPCClass,
                GetRandomPointInVolume(),
                FRotator::ZeroRotator
                );
        }
    }
    else
    {
        return;
    }

    Destroy();  // 스폰 후 볼륨 파괴
}

 

 

SpawnBox와 SpawnActor 함수를 이용해 NPC Spawn 을 하고 또한 스폰후 볼륨을 파괴하는 로직을 통해 구현해주었다.