1class UObjectPoolManager : public UObject
2{
3GENERATED_BODY()
4
5public:
6
7UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Object Pool")
8TSubclassOf<AActor> PooledActorClass;
9
10
11UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Object Pool")
12int32 MaxPoolSize = 50;
13
14
15UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Object Pool")
16int32 InitialPoolSize = 10;
17
18
19DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnActorActivated, AActor*, ActivatedActor);
20UPROPERTY(BlueprintAssignable, Category = "Object Pool")
21FOnActorActivated OnActorActivated;
22
23
24DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnActorDeactivated, AActor*, DeactivatedActor);
25UPROPERTY(BlueprintAssignable, Category = "Object Pool")
26FOnActorDeactivated OnActorDeactivated;
27
28UObjectPoolManager()
29{
30
31}
32
33
34UFUNCTION(BlueprintCallable, Category = "Object Pool")
35void InitializePool(UWorld* World);
36
37
38
39
40UFUNCTION(BlueprintCallable, Category = "Object Pool")
41AActor* GetPooledActor(FVector Location, FRotator Rotation);
42
43
44
45UFUNCTION(BlueprintCallable, Category = "Object Pool")
46void ReturnPooledActor(AActor* ActorToReturn);
47
48
49UFUNCTION(BlueprintCallable, Category = "Object Pool")
50void ClearPool();
51
52private:
53
54TArray<AActor*> AvailableActors;
55
56
57TArray<AActor*> ActiveActors;
58
59
60UWorld* OwningWorld = nullptr;
61
62
63AActor* SpawnActor(FVector Location, FRotator Rotation);
64
65
66void ResetActorState(AActor* Actor);
67
68
69void DestroyActor(AActor* Actor);
70};
71
72void UObjectPoolManager::InitializePool(UWorld* World)
73{
74if (!World || !PooledActorClass)
75{
76UE_LOG(LogTemp, Error, TEXT("ObjectPoolManager: Cannot initialize pool. World or PooledActorClass is invalid."));
77return;
78}
79OwningWorld = World;
80
81
82for (int32 i = 0; i < InitialPoolSize; ++i)
83{
84if (AvailableActors.Num() < MaxPoolSize)
85{
86AActor* NewActor = SpawnActor(FVector::ZeroVector, FRotator::ZeroRotator);
87if (NewActor)
88{
89AvailableActors.Add(NewActor);
90
91NewActor->SetActorHiddenInGame(true);
92NewActor->SetActorEnableCollision(false);
93NewActor->SetActorTickEnabled(false);
94}
95}
96else
97{
98break;
99}
100}
101UE_LOG(LogTemp, Log, TEXT("ObjectPoolManager: Initialized with %d actors. Max size: %d."), AvailableActors.Num(), MaxPoolSize);
102}
103
104AActor* UObjectPoolManager::SpawnActor(FVector Location, FRotator Rotation)
105{
106if (!OwningWorld || !PooledActorClass)
107{
108return nullptr;
109}
110FActorSpawnParameters SpawnParams;
111SpawnParams.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
112AActor* NewActor = OwningWorld->SpawnActor<AActor>(PooledActorClass, Location, Rotation, SpawnParams);
113if (NewActor)
114{
115
116
117}
118return NewActor;
119}
120
121AActor* UObjectPoolManager::GetPooledActor(FVector Location, FRotator Rotation)
122{
123AActor* ActorToActivate = nullptr;
124
125
126if (AvailableActors.Num() > 0)
127{
128ActorToActivate = AvailableActors.Pop();
129ActiveActors.Add(ActorToActivate);
130}
131else if (ActiveActors.Num() < MaxPoolSize)
132{
133
134ActorToActivate = SpawnActor(Location, Rotation);
135if (ActorToActivate)
136{
137ActiveActors.Add(ActorToActivate);
138}
139}
140else
141{
142
143UE_LOG(LogTemp, Warning, TEXT("ObjectPoolManager: Pool exhausted. Cannot retrieve actor."));
144return nullptr;
145}
146
147if (ActorToActivate)
148{
149
150ActorToActivate->SetActorLocation(Location);
151ActorToActivate->SetActorRotation(Rotation);
152ActorToActivate->SetActorHiddenInGame(false);
153ActorToActivate->SetActorEnableCollision(true);
154ActorToActivate->SetActorTickEnabled(true);
155
156
157OnActorActivated.Broadcast(ActorToActivate);
158}
159
160return ActorToActivate;
161}
162
163void UObjectPoolManager::ReturnPooledActor(AActor* ActorToReturn)
164{
165if (!ActorToReturn || !ActiveActors.Contains(ActorToReturn))
166{
167
168return;
169}
170
171
172ActiveActors.Remove(ActorToReturn);
173AvailableActors.Add(ActorToReturn);
174
175
176ResetActorState(ActorToReturn);
177ActorToReturn->SetActorHiddenInGame(true);
178ActorToReturn->SetActorEnableCollision(false);
179ActorToReturn->SetActorTickEnabled(false);
180
181OnActorDeactivated.Broadcast(ActorToReturn);
182}
183
184void UObjectPoolManager::ResetActorState(AActor* Actor)
185{
186if (!Actor)
187{
188return;
189}
190
191Actor->SetActorLocation(FVector::ZeroVector);
192Actor->SetActorRotation(FRotator::ZeroRotator);
193
194
195
196
197
198
199
200
201
202
203
204
205}
206
207void UObjectPoolManager::ClearPool()
208{
209for (AActor* Actor : AvailableActors)
210{
211DestroyActor(Actor);
212}
213AvailableActors.Empty();
214
215for (AActor* Actor : ActiveActors)
216{
217DestroyActor(Actor);
218}
219ActiveActors.Empty();
220
221OwningWorld = nullptr;
222UE_LOG(LogTemp, Log, TEXT("ObjectPoolManager: Pool cleared."));
223}
224
225void UObjectPoolManager::DestroyActor(AActor* Actor)
226{
227if (Actor && Actor->IsValidLowLevel())
228{
229Actor->Destroy();
230}
231}