UE5 对象池 一个umg和actor的对象池

该文章展示了在UnrealEngine中实现的一个名为UObjectPoolSubsystem的系统,用于管理游戏中的对象池,如Actor和UserWidget。它包含FActorPool结构,用于存储和检索Actor实例,支持对象的创建、释放和重用,优化游戏性能。
摘要由CSDN通过智能技术生成

.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();
	}
}

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值