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

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

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

在Unreal Engine 5 (UE5)中实现合成系统可以通过以下步骤完成: 1. 创建一个Actor类,作为合成系统的基础。可以使用UE5自带的Actor类或者自定义一个Actor类。 2. 在Actor类中添加必要的变量函数,例如合成的输入输出物品、合成的材料、合成的效果等。 3. 创建一个UI界面,用于显示控制合成系统。可以使用UE5自带的UMG或者其他UI框架来创建。 4. 在UI界面中添加按钮其他控件,用于控制合成系统。例如,添加一个合成按钮,当用户点击该按钮时,合成系统将进行合成操作。 5. 在合成系统的函数中实现合成的逻辑。根据输入的材料合成的效果,计算出合成的结果,并将结果输出到指定的位置。 6. 在UE5中创建一些测试场景,用于测试合成系统的功能性能。 下面是一个简单的例子,演示如何使用UE5实现一个合成系统: 1. 创建一个Actor类,名为CraftingSystem。 2. 在CraftingSystem中添加以下变量函数: ```c++ UPROPERTY(EditAnywhere) UStaticMeshComponent* OutputItemMesh; // 合成的输出物品 UPROPERTY(EditAnywhere) TArray<TSubclassOf<AActor>> InputItemClasses; // 合成的输入物品 UPROPERTY(EditAnywhere) TArray<int32> InputItemCounts; // 合成的输入物品数量 UPROPERTY(EditAnywhere) TSubclassOf<AActor> CraftEffectClass; // 合成的效果 UFUNCTION(BlueprintCallable) void Craft(); // 合成的函数 ``` 3. 创建一个UI界面,名为CraftingUI。 4. 在CraftingUI中添加一个合成按钮。 5. 在CraftingUI中为合成按钮添加点击事件,调用CraftingSystem的Craft函数。 6. 在CraftingSystem的Craft函数中实现合成的逻辑。计算出需要的输入物品数量,如果输入物品足够,将其减少并生成一个输出物品一个合成效果。 ```c++ void ACraftingSystem::Craft() { TArray<AActor*> inputItems; for (int32 i = 0; i < InputItemClasses.Num(); i++) { UClass* inputClass = InputItemClasses[i]; int32 inputCount = InputItemCounts[i]; TArray<AActor*> foundActors; UGameplayStatics::GetAllActorsOfClass(GetWorld(), inputClass, foundActors); int32 count = 0; for (AActor* actor : foundActors) { if (count >= inputCount) { break; } if (inputItems.Contains(actor)) { continue; } inputItems.Add(actor); count++; } if (count < inputCount) { UE_LOG(LogTemp, Error, TEXT("Not enough input items.")); return; } } for (AActor* actor : inputItems) { actor->Destroy(); } AActor* outputItem = GetWorld()->SpawnActor<AActor>(OutputItemClass
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值