Creating TArray of FTickFunction variable inside manager

Hello everyone,

I’m trying to learn more about FTickFunction and how to use it to create custom tick function so that I can aggerate multiple actors and components ticks as a way to learn FTickFunction and Tick inner workings.

I’m looking at Particle system tick function and in there they did this

USTRUCT()
struct FParticleSystemWorldManagerTickFunction : public FTickFunction
{
	GENERATED_USTRUCT_BODY()

	//~ FTickFunction Interface
	ENGINE_API virtual void ExecuteTick(float DeltaTime, ELevelTick TickType, ENamedThreads::Type CurrentThread, const FGraphEventRef& MyCompletionGraphEvent) override;
	ENGINE_API virtual FString DiagnosticMessage() override;
	ENGINE_API virtual FName DiagnosticContext(bool bDetailed)  override;
	//~ FTickFunction Interface

	FParticleSystemWorldManager* Owner;
};

template<>
struct TStructOpsTypeTraits<FParticleSystemWorldManagerTickFunction> : public TStructOpsTypeTraitsBase2<FParticleSystemWorldManagerTickFunction>
{
	enum
	{
		WithCopy = false
	};
};

And inside the particle manager

TArray<FParticleSystemWorldManagerTickFunction> TickFunctions;

Which basically is array of tick functions for each tick group and I want to do the same.

So I created this

USTRUCT()
struct FAggregatorTickFunction : public FTickFunction
{
	GENERATED_USTRUCT_BODY()
//public:
	
	// Begin FTickFunction overrides
	virtual void ExecuteTick(float DeltaTime, enum ELevelTick TickType, ENamedThreads::Type CurrentThread, const FGraphEventRef& MyCompletionGraphEvent) override;
	virtual FString DiagnosticMessage() override;
	virtual FName DiagnosticContext(bool bDetailed) override;
	// End FTickFunction overrides

	FTickAggregatorManager* m_owner = nullptr;
};

template<>
struct TStructOpsTypeTraits<FAggregatorTickFunction> : public TStructOpsTypeTraitsBase2<FAggregatorTickFunction>
{
	enum
	{
		WithCopy = false
	};
};

And inside my manager I tried creating a TArray of FTickFunctions same like how it is done in particle tick function

TArray<FAggregatorTickFunction> m_tick_functions;

I get this error

1>[1/5] Compile Module.TickAggregator.gen.cpp
1>C:\Program Files\Epic Games\UE_5.0\Engine\Source\Runtime\Core\Public\Templates\MemoryOps.h(217): error C2280: ‘FAggregatorTickFunction::FAggregatorTickFunction(const FAggregatorTickFunction &)’: attempting to reference a deleted function
1>D:\Dev\UE5\MyProject\Plugins\TickAggregator\Source\TickAggregator\Public\TickAggregatorManager.h(26): note: compiler has generated ‘FAggregatorTickFunction::FAggregatorTickFunction’ here
1>D:\Dev\UE5\MyProject\Plugins\TickAggregator\Source\TickAggregator\Public\TickAggregatorManager.h(26): note: ‘FAggregatorTickFunction::FAggregatorTickFunction(const FAggregatorTickFunction &)’: function was implicitly deleted because a base class invokes a deleted or inaccessible function ‘FTickFunction::FTickFunction(const FTickFunction &)’
1>C:\Program Files\Epic Games\UE_5.0\Engine\Source\Runtime\Core\Public\Containers\Array.h(2845): note: see reference to function template instantiation ‘void ConstructItems<FAggregatorTickFunction,OtherElementType,OtherSizeType>(void *,const SourceElementType *,SizeType)’ being compiled
1> with
1> [
1> OtherElementType=FAggregatorTickFunction,
1> OtherSizeType=int,
1> SourceElementType=FAggregatorTickFunction,
1> SizeType=int
1> ]
1>C:\Program Files\Epic Games\UE_5.0\Engine\Source\Runtime\Core\Public\Containers\Array.h(389): note: see reference to function template instantiation ‘void TArray<FAggregatorTickFunction,FDefaultAllocator>::CopyToEmpty<FAggregatorTickFunction,int>(const OtherElementType *,OtherSizeType,int,int)’ being compiled
1> with
1> [
1> OtherElementType=FAggregatorTickFunction,
1> OtherSizeType=int
1> ]
1>C:\Program Files\Epic Games\UE_5.0\Engine\Source\Runtime\Core\Public\Containers\Array.h(389): note: see reference to function template instantiation ‘void TArray<FAggregatorTickFunction,FDefaultAllocator>::CopyToEmpty<FAggregatorTickFunction,int>(const OtherElementType *,OtherSizeType,int,int)’ being compiled
1> with
1> [
1> OtherElementType=FAggregatorTickFunction,
1> OtherSizeType=int
1> ]
1>C:\Program Files\Epic Games\UE_5.0\Engine\Source\Runtime\Core\Public\Containers\Array.h(387): note: while compiling class template member function ‘TArray<FAggregatorTickFunction,FDefaultAllocator>::TArray(const TArray<FAggregatorTickFunction,FDefaultAllocator> &)’
1>D:\Dev\UE5\MyProject\Plugins\TickAggregator\Source\TickAggregator\Public\TickAggregatorManager.h(78): note: see reference to function template instantiation ‘TArray<FAggregatorTickFunction,FDefaultAllocator>::TArray(const TArray<FAggregatorTickFunction,FDefaultAllocator> &)’ being compiled
1>D:\Dev\UE5\MyProject\Plugins\TickAggregator\Source\TickAggregator\Public\TickAggregatorManager.h(67): note: see reference to class template instantiation ‘TArray<FAggregatorTickFunction,FDefaultAllocator>’ being compiled
1>[2/5] Compile Module.TickAggregator.cpp
1>C:\Program Files\Epic Games\UE_5.0\Engine\Source\Runtime\Core\Public\Templates\MemoryOps.h(217): error C2280: ‘FAggregatorTickFunction::FAggregatorTickFunction(const FAggregatorTickFunction &)’: attempting to reference a deleted function
1>D:\Dev\UE5\MyProject\Plugins\TickAggregator\Source\TickAggregator\Public\TickAggregatorManager.h(26): note: compiler has generated ‘FAggregatorTickFunction::FAggregatorTickFunction’ here
1>D:\Dev\UE5\MyProject\Plugins\TickAggregator\Source\TickAggregator\Public\TickAggregatorManager.h(26): note: ‘FAggregatorTickFunction::FAggregatorTickFunction(const FAggregatorTickFunction &)’: function was implicitly deleted because a base class invokes a deleted or inaccessible function ‘FTickFunction::FTickFunction(const FTickFunction &)’
1>C:\Program Files\Epic Games\UE_5.0\Engine\Source\Runtime\Core\Public\Containers\Array.h(2845): note: see reference to function template instantiation ‘void ConstructItems<FAggregatorTickFunction,OtherElementType,OtherSizeType>(void *,const SourceElementType *,SizeType)’ being compiled
1> with
1> [
1> OtherElementType=FAggregatorTickFunction,
1> OtherSizeType=int,
1> SourceElementType=FAggregatorTickFunction,
1> SizeType=int
1> ]
1>C:\Program Files\Epic Games\UE_5.0\Engine\Source\Runtime\Core\Public\Containers\Array.h(389): note: see reference to function template instantiation ‘void TArray<FAggregatorTickFunction,FDefaultAllocator>::CopyToEmpty<FAggregatorTickFunction,int>(const OtherElementType *,OtherSizeType,int,int)’ being compiled
1> with
1> [
1> OtherElementType=FAggregatorTickFunction,
1> OtherSizeType=int
1> ]
1>C:\Program Files\Epic Games\UE_5.0\Engine\Source\Runtime\Core\Public\Containers\Array.h(389): note: see reference to function template instantiation ‘void TArray<FAggregatorTickFunction,FDefaultAllocator>::CopyToEmpty<FAggregatorTickFunction,int>(const OtherElementType *,OtherSizeType,int,int)’ being compiled
1> with
1> [
1> OtherElementType=FAggregatorTickFunction,
1> OtherSizeType=int
1> ]
1>C:\Program Files\Epic Games\UE_5.0\Engine\Source\Runtime\Core\Public\Containers\Array.h(387): note: while compiling class template member function ‘TArray<FAggregatorTickFunction,FDefaultAllocator>::TArray(const TArray<FAggregatorTickFunction,FDefaultAllocator> &)’
1>D:\Dev\UE5\MyProject\Plugins\TickAggregator\Source\TickAggregator\Public\TickAggregatorManager.h(78): note: see reference to function template instantiation ‘TArray<FAggregatorTickFunction,FDefaultAllocator>::TArray(const TArray<FAggregatorTickFunction,FDefaultAllocator> &)’ being compiled
1>D:\Dev\UE5\MyProject\Plugins\TickAggregator\Source\TickAggregator\Public\TickAggregatorManager.h(67): note: see reference to class template instantiation ‘TArray<FAggregatorTickFunction,FDefaultAllocator>’ being compiled
1>C:\Program Files\Microsoft Visual Studio\2022\Community\MSBuild\Microsoft\VC\v170\Microsoft.MakeFile.Targets(44,5): error MSB3073: The command ““C:\Program Files\Epic Games\UE_5.0\Engine\Build\BatchFiles\Build.bat” MyProjectEditor Win64 Development -Project=“D:\Dev\UE5\MyProject\MyProject.uproject” -WaitMutex -FromMsBuild” exited with code 6.

Which obviously is trying to access copy constructor and cannot find it because its deleted, and array needs copy to function it is throwing this error.

But then how is it working for particle FTickFunction?

Looking inside the particle system manager TStructOpsTypeTraitsBase2

WithCopy = !TIsPODType<CPPSTRUCT>::Value, // struct can be copied via its copy assignment operator.

It says it defines weather it can be copies using assignment operator or not. So copy should be present for my struct.

Also another weird thing is if I do this

TArray<FAggregatorTickFunction> m_tick_functions;
FAggregatorTickFunction m_tick_function;

Create a local variable of my FTickFunction, then it compiles successfully without any error. But if I comment the local variable, it throws the error I added before.

What am I missing here?

Show your manager class definition

This is how my entire manager class looks like

class TICKAGGREGATOR_API FTickAggregatorManager : public FGCObject
{
public:
	FTickAggregatorManager(UWorld* world);
	virtual ~FTickAggregatorManager();

	static void OnStartup();
	static void OnShutdown();

	void Tick(ETickingGroup TickGroup, float DeltaTime, ELevelTick TickType, ENamedThreads::Type CurrentThread, const FGraphEventRef& MyCompletionGraphEvent, FActorTickFunction& tick_function);

	// FGCObject interface
	virtual void AddReferencedObjects(FReferenceCollector& collector) override;
	virtual FString GetReferencerName() const override;

	bool RegisterActor(TObjectPtr<AActor> actor);
	void UnregisterActor(TObjectPtr<AActor> actor);

	FORCEINLINE static FTickAggregatorManager* Get(UWorld* World)
	{
		FTickAggregatorManager** return_val = s_world_managers.Find(World);
		if (return_val)
		{
			checkSlow(*return_val);
			return *return_val;
		}
		return nullptr;
	}

private:
	UWorld* m_world;
	
	TArray<FAggregatorTickFunction> m_tick_functions;
	FAggregatorTickFunction m_tick_function;

	TArray<TObjectPtr<AActor>> m_registeration_pending_actors;
	TArray<TObjectPtr<AActor>> m_unregisteration_pending_actors;

	TMap<ETickingGroup, TArray<FActorData>> m_actors_data;

	static const int32 s_max_tick_group = (int32)TG_NewlySpawned;

	// Manager for different worlds. Editor window will be another world and main viewport is another world
	// so managing tick for different worlds
	static TMap<UWorld*, FTickAggregatorManager*> s_world_managers;

	static void OnWorldInit(UWorld* world, const UWorld::InitializationValues initialization_values);
	static void OnWorldPreActorTick(UWorld* world, ELevelTick level_tick, float dilated_time);
	static void OnWorldCleanup(UWorld* world, bool session_ended, bool cleanup_resources);
	static void OnPreWorldFinishDestroy(UWorld* world);
	static void OnWorldBeginTearDown(UWorld* world);
};