Skip to content

Commit f575cae

Browse files
committed
New plugin version 1.0
1 parent 4f44145 commit f575cae

12 files changed

+327
-338
lines changed

ObjectPool/ObjectPool.uplugin

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
{
2+
"FileVersion": 3,
3+
"Version": 1,
4+
"VersionName": "1.0",
5+
"FriendlyName": "ObjectPool",
6+
"Description": "A quick implementation of the Object Pool pattern for blueprint.",
7+
"Category": "Other",
8+
"CreatedBy": "Dawid Slabkowski",
9+
"CreatedByURL": "https://github.com/dslabkowski",
10+
"DocsURL": "https://github.com/dslabkowski/ObjectPool/wiki/Documentation",
11+
"MarketplaceURL": "",
12+
"SupportURL": "https://github.com/dslabkowski/ObjectPool/issues",
13+
"CanContainContent": false,
14+
"IsBetaVersion": false,
15+
"IsExperimentalVersion": false,
16+
"Installed": false,
17+
"Modules": [
18+
{
19+
"Name": "ObjectPool",
20+
"Type": "Runtime",
21+
"LoadingPhase": "Default"
22+
}
23+
]
24+
}

UEObjectPooling/Source/UEObjectPooling.Build.cs renamed to ObjectPool/Source/ObjectPool.Build.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22

33
using UnrealBuildTool;
44

5-
public class UEObjectPooling : ModuleRules
5+
public class ObjectPool : ModuleRules
66
{
7-
public UEObjectPooling(ReadOnlyTargetRules Target) : base(Target)
7+
public ObjectPool(ReadOnlyTargetRules Target) : base(Target)
88
{
99
PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
1010

Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
11
// Copyright Epic Games, Inc. All Rights Reserved.
22

3-
#include "UEObjectPooling.h"
3+
#include "ObjectPool.h"
44

5-
#define LOCTEXT_NAMESPACE "FUEObjectPoolingModule"
5+
#define LOCTEXT_NAMESPACE "FObjectPoolModule"
66

7-
void FUEObjectPoolingModule::StartupModule()
7+
void FObjectPoolModule::StartupModule()
88
{
99
// This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module
1010
}
1111

12-
void FUEObjectPoolingModule::ShutdownModule()
12+
void FObjectPoolModule::ShutdownModule()
1313
{
1414
// This function may be called during shutdown to clean up your module. For modules that support dynamic reloading,
1515
// we call this function before unloading the module.
1616
}
1717

1818
#undef LOCTEXT_NAMESPACE
1919

20-
IMPLEMENT_MODULE(FUEObjectPoolingModule, UEObjectPooling)
20+
IMPLEMENT_MODULE(FObjectPoolModule, ObjectPool)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
// Fill out your copyright notice in the Description page of Project Settings.
2+
3+
4+
#include "ObjectPoolComponent.h"
5+
6+
#include "AudioDevice.h"
7+
#include "ObjectPoolInterface.h"
8+
9+
UObjectPoolComponent::UObjectPoolComponent()
10+
{
11+
PrimaryComponentTick.bCanEverTick = false;
12+
}
13+
14+
void UObjectPoolComponent::AddActorsToPool(int const ActorsNumber)
15+
{
16+
if (PoolActor && ActorsNumber > 0)
17+
{
18+
FActorSpawnParameters SpawnParameters;
19+
SpawnParameters.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
20+
21+
for (int i=0; i < ActorsNumber; i++)
22+
{
23+
if (AActor* SpawnedActor = GetWorld()->SpawnActor<AActor>(PoolActor, FVector().ZeroVector, FRotator().ZeroRotator, SpawnParameters))
24+
{
25+
SpawnedActor->SetActorHiddenInGame(true);
26+
SpawnedActor->SetActorEnableCollision(false);
27+
SpawnedActor->SetActorTickEnabled(false);
28+
29+
InactiveActors.Add(SpawnedActor);
30+
}
31+
}
32+
}
33+
}
34+
35+
void UObjectPoolComponent::SpawnActorFromPool(FTransform SpawnTransform, AActor* Owner, APawn* Instigator,
36+
bool SpawnActorIfPoolIsEmpty, TEnumAsByte<EOutputStates>& Branch, AActor*& SpawnedActor)
37+
{
38+
if(!HasPoolFreeActor() && !SpawnActorIfPoolIsEmpty)
39+
{
40+
Branch = EOutputStates::Failed;
41+
SpawnedActor = nullptr;
42+
return;
43+
}
44+
45+
AActor* PoolActorToSpawn;
46+
47+
if(HasPoolFreeActor())
48+
{
49+
PoolActorToSpawn = InactiveActors.Top();
50+
51+
PoolActorToSpawn->SetActorTransform(SpawnTransform);
52+
PoolActorToSpawn->SetOwner(Owner);
53+
PoolActorToSpawn->SetInstigator(Instigator);
54+
PoolActorToSpawn->SetActorHiddenInGame(false);
55+
PoolActorToSpawn->SetActorEnableCollision(true);
56+
PoolActorToSpawn->SetActorTickEnabled(true);
57+
58+
InactiveActors.Remove(PoolActorToSpawn);
59+
}
60+
61+
else if(SpawnActorIfPoolIsEmpty)
62+
{
63+
FActorSpawnParameters SpawnInfo;
64+
SpawnInfo.Owner = Owner;
65+
SpawnInfo.Instigator = Instigator;
66+
67+
PoolActorToSpawn = GetWorld()->SpawnActor<AActor>(PoolActor, SpawnTransform, SpawnInfo);
68+
}
69+
70+
ActiveActors.Add(PoolActorToSpawn);
71+
72+
if (PoolActorToSpawn->GetClass()->ImplementsInterface(UObjectPoolInterface::StaticClass()))
73+
{
74+
IObjectPoolInterface::Execute_OnActorSpawnedFromPool(PoolActorToSpawn);
75+
}
76+
77+
OnActorBeginSpawnedFromPool.Broadcast(PoolActorToSpawn);
78+
79+
Branch = EOutputStates::Success;
80+
SpawnedActor = PoolActorToSpawn;
81+
return;
82+
}
83+
84+
bool UObjectPoolComponent::HasPoolFreeActor() const
85+
{
86+
return !InactiveActors.IsEmpty();
87+
}
88+
89+
void UObjectPoolComponent::ReturnActorToPool(AActor* Actor)
90+
{
91+
if(ActiveActors.Contains(Actor))
92+
{
93+
Actor->SetActorHiddenInGame(true);
94+
Actor->SetActorEnableCollision(false);
95+
Actor->SetActorTickEnabled(false);
96+
97+
ActiveActors.Remove(Actor);
98+
InactiveActors.Add(Actor);
99+
100+
if (Actor->GetClass()->ImplementsInterface(UObjectPoolInterface::StaticClass()))
101+
{
102+
IObjectPoolInterface::Execute_OnActorDespawnedToPool(Actor);
103+
}
104+
105+
OnActorReturnedToPool.Broadcast(Actor);
106+
}
107+
}
108+
109+
TArray<AActor*> UObjectPoolComponent::GetActiveActorsFromPool() const
110+
{
111+
return ActiveActors;
112+
}
113+
114+
TArray<AActor*> UObjectPoolComponent::GetInactiveActorsFromPool() const
115+
{
116+
return InactiveActors;
117+
}
118+
119+
int32 UObjectPoolComponent::GetPoolSize() const
120+
{
121+
return ActiveActors.Num() + InactiveActors.Num();
122+
}
123+
124+
void UObjectPoolComponent::EmptyPool()
125+
{
126+
TArray<AActor*> Pool;
127+
Pool.Append(ActiveActors);
128+
Pool.Append(InactiveActors);
129+
130+
for (AActor* ActorInPool : Pool)
131+
{
132+
ActorInPool->Destroy();
133+
}
134+
135+
ActiveActors.Empty();
136+
InactiveActors.Empty();
137+
}
138+
139+
bool UObjectPoolComponent::IsActorInUse(AActor* Actor) const
140+
{
141+
if (Actor)
142+
{
143+
return ActiveActors.Contains(Actor);
144+
}
145+
return nullptr;
146+
}
147+
148+
void UObjectPoolComponent::BeginPlay()
149+
{
150+
Super::BeginPlay();
151+
152+
if (bSpawnPoolObjectsOnBeginPlay) { AddActorsToPool(InitialPoolSize); }
153+
154+
}
155+
156+
void UObjectPoolComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
157+
{
158+
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
159+
}
160+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// Fill out your copyright notice in the Description page of Project Settings.
2+
3+
4+
#include "ObjectPoolInterface.h"
5+

UEObjectPooling/Source/Public/UEObjectPooling.h renamed to ObjectPool/Source/Public/ObjectPool.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
#include "CoreMinimal.h"
66
#include "Modules/ModuleManager.h"
77

8-
class FUEObjectPoolingModule : public IModuleInterface
8+
class FObjectPoolModule : public IModuleInterface
99
{
1010
public:
1111

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
// Fill out your copyright notice in the Description page of Project Settings.
2+
3+
#pragma once
4+
5+
#include "CoreMinimal.h"
6+
#include "Components/ActorComponent.h"
7+
#include "ObjectPoolComponent.generated.h"
8+
9+
UENUM(BlueprintType)
10+
enum EOutputStates
11+
{
12+
Success UMETA(DisplayName = "Success"),
13+
Failed UMETA(DisplayName = "Failed"),
14+
};
15+
16+
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FActorSpawnedFromPool, AActor*, SpawnedActor);
17+
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FActorReturnedToPool, AActor*, ReturnedActor);
18+
19+
UCLASS(Blueprintable, ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
20+
class OBJECTPOOL_API UObjectPoolComponent : public UActorComponent
21+
{
22+
GENERATED_BODY()
23+
24+
public:
25+
UObjectPoolComponent();
26+
27+
//Should pool actors be spawned on this component event begin play.
28+
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (ExposeOnSpawn="true"))
29+
bool bSpawnPoolObjectsOnBeginPlay = true;
30+
31+
//Subclass of AActor class to use in the pool.
32+
UPROPERTY(EditAnywhere, BlueprintReadOnly, meta = (ExposeOnSpawn="true"))
33+
TSubclassOf<AActor> PoolActor;
34+
35+
//Define how big should be pool by default.
36+
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (ExposeOnSpawn="true"))
37+
int32 InitialPoolSize;
38+
39+
//Dispatcher. Each time an actor from the pool is spawned.
40+
UPROPERTY(BlueprintAssignable, BlueprintReadWrite)
41+
FActorSpawnedFromPool OnActorBeginSpawnedFromPool;
42+
43+
//Dispatcher. Each time an actor is returned to the pool.
44+
UPROPERTY(BlueprintAssignable, BlueprintReadWrite)
45+
FActorReturnedToPool OnActorReturnedToPool;
46+
47+
//Adds the specified number of actors to the pool.
48+
UFUNCTION(BlueprintCallable, Meta = (Keywords = "object pool, pool, object"))
49+
void AddActorsToPool(int const ActorsNumber);
50+
51+
/***
52+
* Returns an actor from the pool if any is available.
53+
* @param SpawnActorIfPoolIsEmpty If there is no available actor in the pool spawn another actor and add it to pool.
54+
*/
55+
UFUNCTION(BlueprintCallable, Meta = (ExpandEnumAsExecs = "Branch", Keywords = "object pool, pool, object"))
56+
void SpawnActorFromPool(FTransform SpawnTransform, AActor* Owner, APawn* Instigator, bool SpawnActorIfPoolIsEmpty,
57+
TEnumAsByte<EOutputStates>& Branch, AActor*& SpawnedActor);
58+
59+
//Returns whether the pool has at least one free actor.
60+
UFUNCTION(BlueprintCallable, BlueprintPure, Meta = (Keywords = "object pool, pool, object"))
61+
bool HasPoolFreeActor() const;
62+
63+
//Returns given actor back to the pool.
64+
UFUNCTION(BlueprintCallable, Meta = (Keywords = "object pool, pool, object"))
65+
void ReturnActorToPool(AActor* Actor);
66+
67+
//Returns array of active actors in the pool.
68+
UFUNCTION(BlueprintCallable, Meta = (Keywords = "object pool, pool, object"))
69+
TArray<AActor*> GetActiveActorsFromPool() const;
70+
71+
//Return array of inactive actors in the pool.
72+
UFUNCTION(BlueprintCallable, Meta = (Keywords = "object pool, pool, object"))
73+
TArray<AActor*> GetInactiveActorsFromPool() const;
74+
75+
//Return total number of actors in the pool.
76+
UFUNCTION(BlueprintCallable, Meta = (Keywords = "object pool, pool, object"))
77+
int32 GetPoolSize() const;
78+
79+
/***
80+
* Destroys all the actors in the pool and releases the memory.
81+
* @warning Calling this function will cause all actors in the pool to be removed.
82+
* @warning Can cause hitch.
83+
*/
84+
UFUNCTION(BlueprintCallable, Meta = (Keywords = "object pool, pool, object"))
85+
void EmptyPool();
86+
87+
// Is given actor used by this pool right now.
88+
UFUNCTION(BlueprintCallable, BlueprintPure, Meta = (Keywords = "object pool, pool, object"))
89+
bool IsActorInUse(AActor* Actor) const;
90+
91+
protected:
92+
virtual void BeginPlay() override;
93+
94+
UPROPERTY()
95+
TArray<AActor*> ActiveActors;
96+
97+
UPROPERTY()
98+
TArray<AActor*> InactiveActors;
99+
100+
public:
101+
virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
102+
103+
104+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Fill out your copyright notice in the Description page of Project Settings.
2+
3+
#pragma once
4+
5+
#include "CoreMinimal.h"
6+
#include "UObject/Interface.h"
7+
#include "ObjectPoolInterface.generated.h"
8+
9+
UINTERFACE(BlueprintType)
10+
class UObjectPoolInterface : public UInterface
11+
{
12+
GENERATED_BODY()
13+
};
14+
15+
class OBJECTPOOL_API IObjectPoolInterface
16+
{
17+
GENERATED_BODY()
18+
19+
public:
20+
21+
UFUNCTION(BlueprintNativeEvent, BlueprintCallable)
22+
void OnActorSpawnedFromPool();
23+
24+
UFUNCTION(BlueprintNativeEvent, BlueprintCallable)
25+
void OnActorDespawnedToPool();
26+
};

0 commit comments

Comments
 (0)