본문 바로가기
Unreal/Manual

Unreal Enemy Spawner 구현

by Dev_카페인 2024. 3. 12.
반응형

[Unreal/C++] Enemy Spawner 구현

 

적(Enemy)을 생성하는 시스템으로, 게임에서 플레이어에게 도전을 제공하고 전투를 활성화하는 데 사용됩니다. Enemy Spawner는 게임의 특정 위치에 대상을 생성하거나, 특정 시간 간격으로 대상을 생성하거나, 특정 상황이나 이벤트에 응답하여 대상을 생성할 수 있습니다.

 

 

**게임의 도전성 증대**:

적의 수나 강도를 조절함으로써 게임의 난이도를 조절할 수 있습니다.

플레이어가 게임을 진행함에 따라 더 많거나 더 강한 적이 생성될 수 있습니다.

 

**스토리나 이벤트의 진행**:

게임의 특정 이벤트나 스토리 진행에 필요한 적이나 상황을 생성할 수 있습니다.

예를 들어, 보스 전투 직전에 보스의 하수인들을 생성할 수 있습니다.

 

4. **게임 흐름의 제어**:

적의 생성을 통해 게임의 흐름을 제어할 수 있습니다.

특정 구간에서 적을 생성하여 플레이어의 진행을 방해하거나,

새로운 지역으로 진입 시 적을 생성하여 플레이어의 주의를 끌 수 있습니다.

 

5. **리플레이 가치 향상**:

적의 위치나 종류, 수량 등을 다르게 조절함으로써 게임의 재미와 다양성을 높일 수 있습니다.

 

이는 게임을 다시 플레이할 때 새로운 경험을 제공합니다.

Enemy Spawner는 게임 디자인과 조율에 따라 다양한 방식으로 사용될 수 있으며,

효과적으로 구현되면 게임의 재미와 흥미를 크게 향상시킬 수 있습니다.

 

이 코드를 수행하기 위해 Nav Mesh Bound Volume가 필요합니다.

 

 

배열로 원하는 액터를 추가할 수 있습니다.

생성될 개수와 범위를 조절할 수 있습니다.

 

 

 

원형으로 범위가 나오는 것은 Editor 모듈을 추가해야하므로 코드에서 제거했습니다.

#pragma once

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

class AEnemyBase;

UCLASS()
class MULTIPLAYER_API AEnemySpawner : public AActor
{
	GENERATED_BODY()
	
public:	
	AEnemySpawner();

protected:
	virtual void BeginPlay() override;

public:
	void EnemySpawn(int32 InSpawnCount = 0);

protected :
	UPROPERTY(EditAnywhere, Category = "SpawnEnemies")
		TArray<TSubclassOf<AEnemyBase>> Enemies;

	UPROPERTY(EditAnywhere, Category = "SpawnEnemies")
		int32 SpawnCount;
        
	UPROPERTY(EditAnywhere, Category = "SpawnEnemies")
		float Radius;
};

 

#include "System/EnemySpawner.h"

#include "NavigationSystem.h"
#include "Kismet/KismetMathLibrary.h"

#include "Characters/Enemies/EnemyBase.h"

AEnemySpawner::AEnemySpawner()
{

}

void AEnemySpawner::BeginPlay()
{
	Super::BeginPlay();
	
	EnemySpawn();
}

void AEnemySpawner::EnemySpawn(int32 InSpawnCount)
{
	if (InSpawnCount == 0)
		InSpawnCount = SpawnCount;

	UNavigationSystemV1* NavSystem = UNavigationSystemV1::GetCurrent(GetWorld());
	for (int32 i = 0; i < InSpawnCount; i++)
	{
		FNavLocation NavLocation;
		FTransform transform;

		NavSystem->GetRandomPointInNavigableRadius(GetActorLocation(), Radius, NavLocation);
		transform.SetLocation(NavLocation.Location);

		int32 randIdx = UKismetMathLibrary::RandomIntegerInRange(0, Enemies.Num()-1);
		TObjectPtr<AEnemyBase> Enemy = GetWorld()->SpawnActorDeferred<AEnemyBase>(Enemies[randIdx], transform, nullptr, nullptr, ESpawnActorCollisionHandlingMethod::AlwaysSpawn);

		FVector location = transform.GetLocation();
		location.Z += Enemy->GetDefaultHalfHeight();
		transform.SetLocation(location);

		Enemy->FinishSpawning(transform);
	}
}

 


#include "NavigationSystem.h"를 포함하여 월드의 네비게이션 시스템을 참고할 수 있습니다.

UNavigationSystemV1* NavSystem = UNavigationSystemV1::GetCurrent(GetWorld());

 

생성할 개수만 큼 생성합니다.
for (int32 i = 0; i < InSpawnCount; i++)


FNavLocation NavLocation;  결과값을 저장합니다.

 

범위 내의 무작위 지점을 가져옵니다.

NavSystem->GetRandomPointInNavigableRadius(GetActorLocation(), Radius, NavLocation);

무작위 오브젝트를 선택합니다.
int32 randIdx = UKismetMathLibrary::RandomIntegerInRange(0, Enemies.Num()-1);

지정된 오브젝트를 생성합니다.
TObjectPtr<AEnemyBase> Enemy = GetWorld()->SpawnActorDeferred<AEnemyBase>(Enemies[randIdx], transform, nullptr, nullptr, ESpawnActorCollisionHandlingMethod::AlwaysSpawn);

오브젝트의 기본 크기 만큼 바닥에서 올려줍니다.
FVector location = transform.GetLocation();
location.Z += Enemy->GetDefaultHalfHeight();
transform.SetLocation(location);

Enemy->FinishSpawning(transform);

 

반응형