[UE5] ๐Ÿš€ Project Galaga (9)

Singery00ยท2024๋…„ 5์›” 21์ผ
0

Project Galaga

๋ชฉ๋ก ๋ณด๊ธฐ
9/15
post-thumbnail

๊ฐœ์š”

๐Ÿš€ Project Galaga ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค.

Unreal C++๊ณผ ๊ฒŒ์ž„์ˆ˜ํ•™์„ ์ ‘๋ชฉํ•ด์„œ ํ”„๋กœ์ ํŠธ๋ฅผ ์ง„ํ–‰ํ–ˆ์Šต๋‹ˆ๋‹ค.

2024.05.04 ~ 2024.05.21์˜ ๊ฐœ๋ฐœ ๊ธฐ๊ฐ„์œผ๋กœ, ์ด 17์ผ ๋™์•ˆ ๊ฐœ๋ฐœ์„ ์™„๋ฃŒํ•˜์˜€์Šต๋‹ˆ๋‹ค.

๊ฑฐ์ฐฝํ•˜๊ฒŒ ์‹œ์ž‘ํ•œ ํ”„๋กœ์ ํŠธ๋ณด๋‹จ ์ง€๊ธˆ๊นŒ์ง€ ๋ฐฐ์šด ๊ฒƒ๋“ค์„ ์ข…ํ•ฉ์ ์œผ๋กœ ์‚ฌ์šฉํ•ด์„œ ๊ฒฐ๊ณผ๋ฌผ์„ ๋งŒ๋“ค์–ด ๋‚ด๋ณด๊ฒ ๋‹ค๋Š” ๋งˆ์Œ์œผ๋กœ ์™„์„ฑํ•˜์˜€์Šต๋‹ˆ๋‹ค.

ํ•ด๋‹น ์‹œ๋ฆฌ์ฆˆ์—๋Š” ๊ฐœ๋ฐœ ์ผ์ง€๋ฅผ ์ •๋ฆฌํ•˜๋ฉฐ, ๊ฐœ๋ฐœ ๋‚ด์šฉ์— ๋Œ€ํ•œ ์„ค๋ช…๊ณผ ์ด์Šˆ๋ฅผ ์ •๋ฆฌํ•  ์˜ˆ์ •์ž…๋‹ˆ๋‹ค.

๐Ÿš€ Project Galaga Github Repository


๋ณธ๋ก 


์˜ค๋ธŒ์ ํŠธ ํ’€๋ง ๊ฐœ๋…

์ด๋ฒˆ ํ”„๋กœ์ ํŠธ๋ฅผ ์ง„ํ–‰ํ•˜๋ฉฐ ๊ฐ€์žฅ ํ•ต์‹ฌ์ด ๋˜๋Š” ๊ตฌํ˜„ ์‚ฌํ•ญ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

๊ฒŒ์ž„์˜ ํ•ต์‹ฌ ๊ธฐ๋Šฅ์ธ ์ด์•Œ ์†Œํ™˜์˜ ์ตœ์ƒ์œ„ ๊ตฌํ˜„๋ถ€์ด๊ธฐ ๋•Œ๋ฌธ์ด์ฃ .

์ผ๋ฐ˜ ์  ์•กํ„ฐ๋“ค์ด ํ•œ๋ฐœ ๋‘๋ฐœ ์ด์•Œ์„ ์˜๋Š” ๊ฑด ํฌ๊ฒŒ ๋ฌธ์ œ๊ฐ€ ๋˜์ง€ ์•Š์„ ๊ฒ๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ ๋ณด์Šค๊ฐ€ ๋‚˜์™€์„œ ํ™•์‚ฐํ˜• (Spread)๋กœ 0.01์ดˆ๋งˆ๋‹ค ์ด์•Œ์„ ์†Œํ™˜ํ•ด์„œ ๋ฟŒ๋ฆฐ๋‹ค๋ฉด ์–ด๋–จ๊นŒ์š”?

์ˆ˜์—†์ด ์•กํ„ฐ๊ฐ€ ์ƒ์„ฑ๋˜์—ˆ๋‹ค ์†Œ๋ฉธํ•˜๋ฉฐ ํผํฌ๋จผ์Šค๊ฐ€ ๊ณ„์†ํ•ด์„œ ๋–จ์–ด์ง€๊ฒŒ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

ํ•ด๋‹น ๋ฌธ์ œ๋ฅผ ์ค„์ด๊ธฐ ์œ„ํ•ด ์•กํ„ฐ๋ฅผ ๋ฏธ๋ฆฌ ์ƒ์„ฑํ•ด๋‘์—ˆ๋‹ค๊ฐ€ ํ•„์š”ํ•  ๋•Œ ๊ฐ€์ ธ๋‹ค ์“ธ ์ˆ˜ ์žˆ๋„๋ก ๋งŒ๋“  ๊ฒƒ์ด Pool์ด๋ผ๋Š” ๊ฐœ๋…์ž…๋‹ˆ๋‹ค.


ํ’€๋ง ํด๋ž˜์Šค ๊ตฌํ˜„

ํ”„๋กœ์ ํŠธ์—์„œ 2๊ฐ€์ง€์˜ Bullet Pool์ด ํ•„์š”ํ–ˆ์Šต๋‹ˆ๋‹ค.

Player Bullet Pool๊ณผ Enemy Bullet Pool์ž…๋‹ˆ๋‹ค.

๋‘๊ฐ€์ง€์˜ ๊ตฌํ˜„ ๋‚ด์šฉ์€ ๊ฐ™์œผ๋‚˜, Player๊ฐ€ ํ˜ผ์ž ์‚ฌ์šฉํ•˜๋Š” Player Bullet Pool์€ ์•กํ„ฐ ์ปดํฌ๋„ŒํŠธ๋กœ ๋งŒ๋“ค์–ด ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ Enemy Bullet Pool์€ ๋ชจ๋“  ์ ๋“ค์ด ์ ‘๊ทผํ•˜์—ฌ ์ด์•Œ์„ ๊ฐ€์ ธ๋‹ค ์จ์•ผ ํ•จ์œผ๋กœ ์•กํ„ฐ๋กœ ๋งŒ๋“ค์–ด ๋ ˆ๋ฒจ์— ํ•˜๋‚˜ ๋ฐฐ์น˜ํ•ด์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.

Object Pool ๋ณ€์ˆ˜ ์„ ์–ธ

Pool์— ์‚ฌ์šฉ๋œ ๋ณ€์ˆ˜๋ถ€ํ„ฐ ํ•˜๋‚˜์”ฉ ์„ค๋ช…ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

PooledObject

์–ด๋–ค ์•กํ„ฐ๋ฅผ Poolingํ• ์ง€ ์ง€์ •ํ•ด์ฃผ์–ด์•ผ ํ•˜๋‹ˆ TSubclassOf๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ Bullet์„ ๋„ฃ์–ด ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.

	UPROPERTY(EditDefaultsOnly, Category = ObjectPool)
	TSubclassOf<class APlayerBullet> PooledObjectSubclass;

Pool Size

์˜ค๋ธŒ์ ํŠธ ํ’€๋ง์˜ ๋‹จ์ ์€ ๋ฏธ๋ฆฌ ์•กํ„ฐ๋“ค์„ ์ƒ์„ฑํ•ด๋‘๊ธฐ ๋•Œ๋ฌธ์— ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์žก์•„ ๋จน๋Š”๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ ๋‹ค๋‹ค์ต์„ ์ด๋ผ๋Š” ์ƒ๊ฐ์œผ๋กœ ์ด์•Œ์„ ๋งˆ๊ตฌ์žก์ด๋กœ 5์ฒœ๊ฐœ๋ฅผ ์ƒ์„ฑํ•ด๋‘๋Š”๊ฒŒ ์˜คํžˆ๋ ค ํ•ด๊ฐ€ ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ ํ”Œ๋ ˆ์ด์— ์ง€์žฅ์ด ์ƒ๊ธฐ์ง€ ์•Š๋Š” ์ ๋‹นํ•œ ์„ ์—์„œ Pool Size์„ ๊ฒฐ์ •ํ•ด์ฃผ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

ํ•ด๋‹น ํ”„๋กœ์ ํŠธ์˜ ๊ฒฝ์šฐ Player Bullet Pool Size๋Š” 50, Enemy Bullet Pool Size๋Š” 200์œผ๋กœ ์„ค์ •ํ•ด์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.

	UPROPERTY(EditAnywhere, Category = ObjectPool)
	int PoolSize = 50;

PooledObject Life Span

ํ’€๋ง๋œ ์˜ค๋ธŒ์ ํŠธ๊ฐ€ ๋‹ค์‹œ ๋น„ํ™œ์„ฑํ™”๋˜๊ธฐ๊นŒ์ง€์˜ ์ƒ๋ช…์ฃผ๊ธฐ ์‹œ๊ฐ„ ๋ณ€์ˆ˜๋ฅผ ์„ ์–ธํ•ด์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.

	UPROPERTY(EditAnywhere, Category = ObjectPool)
	float PooledObjectLifeSpan = 1.0f;

ObjectPool

ํ’€๋งํ•œ ์˜ค๋ธŒ์ ํŠธ๋ฅผ ๋‹ด์•„์„œ ๋ณด๊ด€ํ•  ํฌ์ธํ„ฐ ๋ฐฐ์—ด์ž…๋‹ˆ๋‹ค.
ํ•ด๋‹น ๋ฐฐ์—ด์ด ์‹ค์งˆ์ ์ธ Pool์ด ๋ฉ๋‹ˆ๋‹ค.

	UPROPERTY(EditAnywhere, Category = ObjectPool)
	TArray<APlayerBullet*> ObjectPool;

SpawnedPoolIndexes

ํ’€๋ง๋œ ์˜ค๋ธŒ์ ํŠธ ์ค‘์—์„œ ํ™œ์„ฑํ™”๋œ ์˜ค๋ธŒ์ ํŠธ๋ฅผ ๋ณด๊ด€ํ•˜๋Š” ๋ฐฐ์—ด์ž…๋‹ˆ๋‹ค.

์‹ค์ œ๋กœ ์˜ค๋ธŒ์ ํŠธ์„ ์ฐธ์กฐํ•  ํ•„์š”๋Š” ์—†์Šต๋‹ˆ๋‹ค.
๋‹ค๋งŒ ์–ด๋–ค ์˜ค๋ธŒ์ ํŠธ๊ฐ€ ํ™œ์„ฑํ™” ๋˜์—ˆ๋Š”์ง€๋งŒ ํ™•์ธ์„ ํ•˜๋ฉด ๋˜๋‹ˆ Pool์˜ Index๋ฅผ ์ €์žฅํ•  ๋ฐฐ์—ด์ด๋ฉด ์ถฉ๋ถ„ํ•ฉ๋‹ˆ๋‹ค.

	UPROPERTY(EditAnywhere, Category = ObjectPool)
	TArray<int> SpawnedPoolIndexes;

๋น„ํ™œ์„ฑํ™” ํ•จ์ˆ˜

์ƒ๋ช…์ฃผ๊ธฐ ์‹œ๊ฐ„์ด ๋„˜์–ด๊ฐ€๋ฉด ํ•ด๋‹น ์˜ค๋ธŒ์ ํŠธ๋ฅผ ๋‹ค์‹œ Pool์— ๋„ฃ์–ด์„œ ๋น„ํ™œ์„ฑํ™” ํ•ด์ฃผ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ Despawn()ํ•จ์ˆ˜๋ฅผ ์„ ์–ธํ•ด์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.

ํ•ด๋‹น ํ•จ์ˆ˜๋Š” Delegate๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ ์ด์•Œ๋ณ„๋กœ ํ™œ์„ฑํ™” ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•˜๊ณ , SpawnedPoolIndexes ๋ฐฐ์—ด์—์„œ ์ œ๊ฑฐํ•ด์ฃผ๊ธฐ ์œ„ํ•ด์„œ ๋ฐ”์ธ๋”ฉํ•ด์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.

	UFUNCTION()
	void OnPlayerPooledBulletDespawn(APlayerBullet* PoolActor);

Bullet Class ์ถ”๊ฐ€ ๋‚ด์šฉ

Bullet Class๋Š” ์ด์ „์— ์ „๋ฐฉ ์ด๋™ ํ•จ์ˆ˜์™€ ํ”ผ๊ฒฉ ์ด๋ฒคํŠธ ํ•จ์ˆ˜์— ๋Œ€ํ•ด์„œ ์„ค๋ช…ํ–ˆ์Šต๋‹ˆ๋‹ค.

์ด์ œ๋Š” ํ’€๋ง์„ ์œ„ํ•œ ๋‚ด์šฉ์„ ์ถ”๊ฐ€ํ•ด์ฃผ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋ณ€์ˆ˜ ์„ ์–ธ

ํ™œ์„ฑํ™” ๋ณ€์ˆ˜

ํ™œ์„ฑํ™” ์—ฌ๋ถ€๋ฅผ ์•Œ๋ ค์ฃผ๋Š” ๋ณ€์ˆ˜์ž…๋‹ˆ๋‹ค.

	UPROPERTY(EditAnywhere, Category = BulletStat)
	bool Active = false;

์ƒ๋ช…์ฃผ๊ธฐ ๋ณ€์ˆ˜

์–ผ๋งˆ๋‚˜ ํ™œ์„ฑํ™” ๋  ๊ฒƒ์ธ๊ฐ€๋ฅผ ๊ฒฐ์ •ํ•˜๋Š” ์ƒ๋ช…์ฃผ๊ธฐ ๋ณ€์ˆ˜์ž…๋‹ˆ๋‹ค.

	UPROPERTY(VisibleAnywhere, Category = BulletStat)
	float LifeSpan = 0.0f;

ํ’€๋ง ์ธ๋ฑ์Šค ๋ณ€์ˆ˜

์ด์ „์— Pool์—๋Š” 2๊ฐ€์ง€ ๋ณ€์ˆ˜๊ฐ€ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.
์ƒ์„ฑ๋œ ์ˆœ์„œ์— ๋”ฐ๋ผ PoolIndex๋ฅผ ๋„ฃ์–ด์„œ ๊ด€๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ๋ณ€์ˆ˜๋ฅผ ์ถ”๊ฐ€ํ•ด์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.

	UPROPERTY(VisibleAnywhere, Category = BulletStat)
	int PoolIndex;

์ƒ๋ช…์ฃผ๊ธฐ ํƒ€์ด๋จธ

์ƒ๋ช…์ฃผ๊ธฐ ์‹œ๊ฐ„์— ๋”ฐ๋ผ ๋น„ํ™œ์„ฑํ™” ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๊ธฐ ์œ„ํ•œ ํƒ€์ด๋จธ ๋ณ€์ˆ˜์ž…๋‹ˆ๋‹ค.

FTimerHandle LifeSpanTimer;

Delegate

๊ฐ€์žฅ ์ค‘์š”ํ•œ ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค.

Delegate์ž…๋‹ˆ๋‹ค.

๋น„ํ™œ์„ฑํ™” ์‹œ Delegate๋ฅผ ํ†ตํ•ด ๋น„ํ™œ์„ฑํ™” ๋œ ์ž์‹ (this)๋ฅผ ๋„˜๊ฒจ์ฃผ์–ด SpawnedPoolIndexes ๋ฐฐ์—ด์—์„œ ์ œ๊ฑฐํ•ด์ฃผ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋ธ”๋ฃจํ”„๋ฆฐํŠธ์—์„œ ์‚ฌ์šฉํ•˜์ง€ ์•Š์•˜์ง€๋งŒ ํ˜น์—ฌ๋‚˜ํ•˜์—ฌ DYNAMIC์„ ์‚ฌ์šฉํ•˜์˜€์Šต๋‹ˆ๋‹ค.

๋˜ํ•œ Pool Size ๊ฐœ์ˆ˜๋งŒํผ์˜ ์ด์•Œ๋“ค์ด Pool์—๊ฒŒ ๋ฐ”์ธ๋”ฉ๋  ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— MULTICAST๋ฅผ ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค.

๋งˆ์ง€๋ง‰์œผ๋กœ ์ž๊ธฐ ์ž์‹ (this)๋ฅผ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ์„œ ๋„˜๊ฒจ์ฃผ์–ด์•ผ ํ•จ์œผ๋กœ OneParam์„ ์ถ”๊ฐ€ํ•˜์—ฌ BulletClass๋ฅผ ํƒ€์ž…์œผ๋กœ ๋„˜๊ฒจ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.

DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnPlayerPooledBulletDespawn, APlayerBullet*, PoolActor);

FOnPlayerPooledBulletDespawn OnPlayerPooledBulletDespawn;

ํ’€๋ง ๋™์ž‘ ๊ตฌํ˜„

ํ’€๋ง ์˜ค๋ธŒ์ ํŠธ ์ƒ์„ฑ

ํ”„๋กœ๊ทธ๋žจ์ด ์‹œ์ž‘๋˜๋ฉด BeginPlay()์—์„œ ๋น„์–ด์žˆ๋Š” Pool์— Pool Size๋งŒํผ ์˜ค๋ธŒ์ ํŠธ๋ฅผ ์ฑ„์›Œ ๋„ฃ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋ฐ˜๋ณต๋ฌธ์œผ๋กœ ์ด์•Œ์„ ์ƒ์„ฑํ•˜๊ณ , Bullet Class์— ์„ ์–ธํ•œ ๋ณ€์ˆ˜ ๊ฐ’์„ ์ดˆ๊ธฐํ™”ํ•˜๋ฉฐ Pool์— ๋„ฃ์–ด ์ค๋‹ˆ๋‹ค.

์ด๋•Œ AddDynamic์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ ์ด์•Œ๋งˆ๋‹ค Pool์˜ BulletDespawn()ํ•จ์ˆ˜์™€ ๋ฐ”์ธ๋”ฉํ•ด์ค๋‹ˆ๋‹ค.

// Called when the game starts
void UPlayerBulletPool::BeginPlay()
{
	Super::BeginPlay();

	// ...
	me = Cast<AMyPlayer>(GetOwner());

	if (me == nullptr)
	{
		UE_LOG(LogTemp, Warning, TEXT("No me"));
	}

	if (PooledObjectSubclass != nullptr)
	{
		FActorSpawnParameters param;
		param.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;

		for (int i = 0; i < PoolSize; i++)
		{
			APlayerBullet* PoolableActor = GetWorld()->SpawnActor<APlayerBullet>(PooledObjectSubclass, FVector(-2500,-2500,0), FRotator::ZeroRotator, param);

			if (PoolableActor != nullptr)
			{
				PoolableActor->SetActive(false);
				PoolableActor->SetPoolIndex(i);
				PoolableActor->OnPlayerPooledBulletDespawn.AddDynamic(this, &UPlayerBulletPool::OnPlayerPooledBulletDespawn);

				this->ObjectPool.Add(PoolableActor);

			}
		}
	}
}

ํ’€๋ง ์˜ค๋ธŒ์ ํŠธ ํ™œ์„ฑํ™”

์ด์•Œ์„ ์‚ฌ์šฉํ•  ์ฃผ์ฒด๋Š” Pool์˜ SpawnPooledObject() ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ด์•Œ์„ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋•Œ Pool์˜ ์•ž ์ชฝ Index๋ถ€ํ„ฐ ์ด์•Œ์ด ์žˆ๋Š”์ง€, ๋น„ํ™œ์„ฑํ™”์ธ์ง€๋ฅผ ๊ฒ€์‚ฌํ•ฉ๋‹ˆ๋‹ค.

๋‘ ์กฐ๊ฑด์— ๋งŒ์กฑํ•˜๋Š” ์ด์•Œ์ด ์žˆ๋‹ค๋ฉด ํ•ด๋‹น ์ด์•Œ์„ ํ™œ์„ฑํ™”ํ•˜๊ณ  ๋ฐ˜ํ™˜ํ•ด์ค๋‹ˆ๋‹ค.

AEnemyBullet* AEnemyBulletPool::SpawnPooledObject(FVector newLocation, FRotator newRotation)
{

	for (AEnemyBullet* PoolableActor : ObjectPool)
	{
		if (PoolableActor != nullptr && !PoolableActor->IsActive())
		{
			PoolableActor->TeleportTo(newLocation, newRotation, false, true);
			PoolableActor->SetLifeSpan(PooledObjectLifeSpan);
			PoolableActor->SetActive(true);
			SpawnedPoolIndexes.Add(PoolableActor->GetPoolIndex());

			return PoolableActor;
		}
	}


	// ์ƒ๋žต


	return nullptr;
}

์—ฌ๊ธฐ์„œ ๋ชจ๋“  ์ด์•Œ์ด ์ด๋ฏธ ํ™œ์„ฑํ™”๋œ ์ƒํƒœ์ผ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

์•ž์„œ Pool๋‚ด๋ถ€์—์„œ ํ™œ์„ฑํ™”ํ•˜์—ฌ ๋ฐ˜ํ™˜ํ•ด์ค„ ์ˆ˜ ์žˆ๋Š” ์ด์•Œ์ด ์—†๋‹ค๋ฉด ์•„๋ž˜ ๋กœ์ง์ด ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.

๊ฐ€์žฅ ๋จผ์ € ํ™œ์„ฑํ™”๋œ ์ด์•Œ์„ ๊ฐ€์ ธ์™€์„œ ์žฌํ™œ์„ฑํ™”ํ•ด์ฃผ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

AEnemyBullet* AEnemyBulletPool::SpawnPooledObject(FVector newLocation, FRotator newRotation)
{

	// ์ƒ๋žต


	if (SpawnedPoolIndexes.Num() > 0)
	{
		int PoolObjectIndex = SpawnedPoolIndexes[0];
		SpawnedPoolIndexes.Remove(PoolObjectIndex);
		AEnemyBullet* PoolableActor = this->ObjectPool[PoolObjectIndex];

		if (PoolableActor != nullptr)
		{
			PoolableActor->SetActive(false);

			PoolableActor->TeleportTo(newLocation, newRotation, false, true);
			PoolableActor->SetLifeSpan(PooledObjectLifeSpan);
			PoolableActor->SetActive(true);
			SpawnedPoolIndexes.Add(PoolableActor->GetPoolIndex());

			return PoolableActor;
		}
	}


	return nullptr;
}

ํ•ด๋‹น ๋กœ์ง์€ ์ค‘์š”ํ•˜๋‚˜, ์ €๋Š” ์˜คํžˆ๋ ค ์ œ ํ”„๋กœ์ ํŠธ์—๋Š” ํ•„์š”์—†๋Š” ๊ธฐ๋Šฅ์ด๋ผ ์ƒ๊ฐํ•˜์˜€์Šต๋‹ˆ๋‹ค.

์™œ๋ƒ๋ฉด ์ ์ด ๋ฐœ์‚ฌํ•œ ์ด์•Œ์€ ๋๊นŒ์ง€ ๊ฐ€์„œ ํ”Œ๋ ˆ์ด์–ด์—๊ฒŒ ์œ„ํ˜‘์ด ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ ์ด์•Œ์ด ๋‚ ์•„๊ฐ€๋‹ค ์—ญํ™œ์„ฑํ™”๋˜์–ด ๋ฒ„๋ฆฐ๋‹ค๋ฉด ํ”Œ๋ ˆ์ด์–ด๋Š” "์–ด? ์ด์•Œ์ด ์™œ ์˜ค๋‹ค๋ง์ง€?" ๋ผ๋Š” ์˜๋ฌธ์„ ๊ฐ€์ง€๊ฒŒ ๋˜๊ฒ ์ฃ .

๋˜ํ•œ ๋™์ผํ•˜๊ฒŒ ํ”Œ๋ ˆ์ด์–ด์˜ ์ž…์žฅ์—์„œ๋Š” "์™œ ์ด์•Œ์ด ๊ฐ€๋‹ค๊ฐ€ ์‚ฌ๋ผ์ง€์ง€?"๋ผ๋Š” ์ƒ๊ฐ์„ ํ•  ๊ฒ๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ ํ•ด๋‹น ๋กœ์ง์„ Player ๊ตฌํ˜„๋ถ€์—๋Š” ์˜๋„์ ์œผ๋กœ ์ฃผ์„์ฒ˜๋ฆฌ๋ฅผ ํ•ด์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.

ํ™œ์„ฑํ™”๊ฐ€ ๋˜๊ฒŒ ๋œ๋‹ค๋ฉด Bullet Class์˜ SetActive()ํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.

๋™์‹œ์— LifeSpan๋งŒํผ ๋Œ€๊ธฐ ํ›„์— ๋น„ํ™œ์„ฑํ™” ํ•จ์ˆ˜๊ฐ€ ์˜ˆ์•ฝ๋ฉ๋‹ˆ๋‹ค.

void APlayerBullet::SetActive(bool IsActive)
{
	Active = IsActive;
	SetActorHiddenInGame(!IsActive);
	GetWorldTimerManager().SetTimer(LifeSpanTimer, this, &APlayerBullet::Deactivate, LifeSpan, false);
}

ํ’€๋ง ์˜ค๋ธŒ์ ํŠธ ๋น„ํ™œ์„ฑํ™”

Timer๋ฅผ ํ†ตํ•ด ์ƒ๋ช…์ฃผ๊ธฐ๊ฐ€ ๋๋‚˜๋ฉด Deactivate()๊ฐ€ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.

ํ™œ์„ฑํ™” ์ƒํƒœ๋ฅผ ๋น„ํ™œ์„ฑํ™” ์ƒํƒœ๋กœ ๋ณ€๊ฒฝํ•ด์ค๋‹ˆ๋‹ค.

๋˜ํ•œ Delegate์— ๋ฐ”์ธ๋”ฉ๋œ ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•ด์ค๋‹ˆ๋‹ค.

void APlayerBullet::Deactivate()
{
	SetActive(false);
	SetActorLocation(FVector(-2500,-2500,0));
	GetWorldTimerManager().ClearAllTimersForObject(this);
	OnPlayerPooledBulletDespawn.Broadcast(this);
}

ํ’€๋ง ์˜ค๋ธŒ์ ํŠธ ์ œ๊ฑฐ

Delegate๋ฅผ ํ†ตํ•ด OnPlayerPooledBulletDespawn() ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋˜๋ฉด ํ™œ์„ฑํ™” ๋ชฉ๋ก ๋ฐฐ์—ด์—์„œ ์ œ๊ฑฐํ•ด์ค๋‹ˆ๋‹ค.

void UPlayerBulletPool::OnPlayerPooledBulletDespawn(APlayerBullet* PoolActor)
{
	SpawnedPoolIndexes.Remove(PoolActor->GetPoolIndex());
}

์œ„ ๊ณผ์ •์„ ํ†ตํ•ด ์˜ค๋ธŒ์ ํŠธ ํ’€๋ง์˜ ๊ตฌํ˜„๊ณผ ์‚ฌ์šฉ์— ๋Œ€ํ•ด์„œ ์ •๋ฆฌํ•˜์˜€์Šต๋‹ˆ๋‹ค.


๋งˆ๋ฌด๋ฆฌ

์—ฌ๊ธฐ๊นŒ์ง€๊ฐ€ ์˜ค๋ธŒ์ ํŠธ ํ’€๋ง์— ๋Œ€ํ•œ ๊ตฌํ˜„๋‚ด์šฉ ์ •๋ฆฌ์˜€์Šต๋‹ˆ๋‹ค.
์‹œ๊ฐ์ ์ธ ์ด๋ฏธ์ง€๋กœ ๋ณด์—ฌ์ฃผ๊ธฐ ํž˜๋“  ๋‚ด์šฉ์ด๋ผ ํ…์ŠคํŠธ๋งŒ ๊ฐ€๋“ํ•ด์„œ ์ฃ„์†กํ•ฉ๋‹ˆ๋‹ค.

profile
๊ฒŒ์ž„ ๊ฐœ๋ฐœ์ž๊ฐ€ ๋˜์–ด๋ณด์ž

0๊ฐœ์˜ ๋Œ“๊ธ€