.h文件
// Copyright Access! GameStudio. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "Blueprint/UserWidgetPool.h"
#include "Subsystems/WorldSubsystem.h"
#include "ObjectPoolSubsystem.generated.h"
/**
*
*/
USTRUCT(BlueprintType)
struct FActorPool
{
GENERATED_BODY()
public:
FActorPool(){};
void SetWorld(UWorld* World)
{
if(World)
{
OwningWorld = World;
}
}
bool IsInitialized() const { return OwningWorld.IsValid(); }
AActor* GetActor(TSubclassOf<AActor> ActorClass);
//创建actor
template <typename ActorT = AActor>
AActor* GetOrCreateActor(TSubclassOf<ActorT> ActorClass)
{
if (!ActorClass || !ensure(IsInitialized()))
{
return nullptr;
}
AActor* Actor = nullptr;
for (AActor* InactiveActor : InactiveActors)
{
if (InactiveActor->StaticClass() == ActorClass)
{
Actor = InactiveActor;
InactiveActors.RemoveSingleSwap(InactiveActor);
break;
}
}
if(Actor)
{
SetActorEnable(Actor,true);
}
if (!Actor)
{
Actor = OwningWorld.Get()->SpawnActor(ActorClass);
if (!Actor)
{
return nullptr;
}
}
ActiveActors.Add(Actor);
return Cast<ActorT>(Actor);
}
//将actor释放回对象池
void ReleaseActor(AActor* Actor);
void ReleaseActor(TArray<AActor*> Actors);
void ReleaseAll();
//重置对象池
void ResetPool();
//设置Actor的开启与关闭(碰撞、显示、Tick和所有子Actor)
static void SetActorEnable(AActor* Actor, bool Enable);;
private:
UPROPERTY(Transient)
TArray<TObjectPtr<AActor>> ActiveActors;
UPROPERTY(Transient)
TArray<TObjectPtr<AActor>> InactiveActors;
TWeakObjectPtr<UWorld> OwningWorld;
};
UCLASS()
class XXXXXX_API UObjectPoolSubsystem : public UWorldSubsystem
{
GENERATED_BODY()
public:
//创建Widget
UFUNCTION(BlueprintCallable)
UUserWidget* CreateOrGetWidget(TSubclassOf<UUserWidget> WidgetClass);
//释放Widget到对象池
UFUNCTION(BlueprintCallable)
void ReleaseWidget(UUserWidget* Widget);
UFUNCTION(BlueprintCallable)
void ReleaseWidgets(TArray<UUserWidget*> Widgets);
//创建Actor
UFUNCTION(BlueprintCallable)
AActor* CreateOrGetActor(TSubclassOf<AActor> ActorClass);
//释放Actor到对象池
UFUNCTION(BlueprintCallable)
void ReleaseActor(AActor* Actor);
UFUNCTION(BlueprintCallable)
void ReleaseActors(TArray<AActor*> Actors);
UFUNCTION(BlueprintCallable)
void ReleaseActorByClass(TSubclassOf<AActor> ActorClass);
UFUNCTION(BlueprintCallable)
void ResetPool(TSubclassOf<AActor> ActorClass);
protected:
virtual void PostInitialize() override;
private:
UPROPERTY()
FUserWidgetPool WidgetPool;
UPROPERTY()
TMap<TSubclassOf<AActor>,FActorPool> ActorPools;
};
.cpp文件
// Copyright Access! GameStudio. All Rights Reserved.
#include "Subsystem/ObjectPoolSubsystem.h"
AActor* FActorPool::GetActor(TSubclassOf<AActor> ActorClass)
{
return GetOrCreateActor(ActorClass);
}
void FActorPool::ReleaseActor(AActor* Actor)
{
if (!Actor)
{
return;
}
if (const auto Index = ActiveActors.Find(Actor) != INDEX_NONE)
{
ActiveActors.RemoveAt(Index);
InactiveActors.Push(Actor);
SetActorEnable(Actor,false);
}
}
void FActorPool::ReleaseActor(TArray<AActor*> Actors)
{
for (AActor* Actor : Actors)
{
ReleaseActor(Actor);
}
}
void FActorPool::ReleaseAll()
{
for(auto Actor:ActiveActors)
{
SetActorEnable(Actor,false);
}
InactiveActors.Append(ActiveActors);
ActiveActors.Empty();
}
void FActorPool::ResetPool()
{
InactiveActors.Reset();
ActiveActors.Reset();
}
void FActorPool::SetActorEnable(AActor* Actor, bool Enable)
{
if(!Actor)
return;
Actor->SetActorHiddenInGame(!Enable);
Actor->SetActorEnableCollision(Enable);
Actor->SetActorTickEnabled(Enable);
TArray<UActorComponent*> Components;
Actor->GetComponents(Components);
for (UActorComponent* ActorComponent : Components)
{
ActorComponent->SetActive(Enable);
ActorComponent->SetComponentTickEnabled(Enable);
}
}
void UObjectPoolSubsystem::PostInitialize()
{
Super::PostInitialize();
WidgetPool.SetWorld(GetWorld());
//ActorPool.SetWorld(GetWorld());
}
UUserWidget* UObjectPoolSubsystem::CreateOrGetWidget(const TSubclassOf<UUserWidget> WidgetClass)
{
return WidgetPool.GetOrCreateInstance(WidgetClass);
}
void UObjectPoolSubsystem::ReleaseWidget(UUserWidget* Widget)
{
if(!Widget) return;
Widget->SetVisibility(ESlateVisibility::Collapsed);
WidgetPool.Release(Widget,false);
}
void UObjectPoolSubsystem::ReleaseWidgets(TArray<UUserWidget*> Widgets)
{
for (const auto Widget : Widgets)
{
ReleaseWidget(Widget);
}
}
AActor* UObjectPoolSubsystem::CreateOrGetActor(TSubclassOf<AActor> ActorClass)
{
if(!ActorClass) return nullptr;
if(const auto Pool = ActorPools.Find(ActorClass))
{
return Pool->GetOrCreateActor(ActorClass);
}
else
{
FActorPool NewPool;
NewPool.SetWorld(GetWorld());
ActorPools.Add(ActorClass, NewPool);
return NewPool.GetOrCreateActor(ActorClass);
}
}
void UObjectPoolSubsystem::ReleaseActor(AActor* Actor)
{
if(!Actor) return;
if(const auto Pool = ActorPools.Find(Actor->StaticClass()))
{
Pool->ReleaseActor(Actor);
}
}
void UObjectPoolSubsystem::ReleaseActors(TArray<AActor*> Actors)
{
if(!Actors.IsEmpty())
{
if(const auto Pool = ActorPools.Find(Actors.Last()->StaticClass()))
{
Pool->ReleaseActor(Actors);
}
}
}
void UObjectPoolSubsystem::ReleaseActorByClass(TSubclassOf<AActor> ActorClass)
{
if(const auto Pool = ActorPools.Find(ActorClass))
{
Pool->ReleaseAll();
}
}
void UObjectPoolSubsystem::ResetPool(TSubclassOf<AActor> ActorClass)
{
if(const auto Pool = ActorPools.Find(ActorClass))
{
Pool->ResetPool();
}
}