[4.7.5] Component tick function still queued after Deactivate()

Spawning actors takes a lot of time so we pre-spawn lots of actors and re-use them by activating/ deactivating them.

However a lot of actor components do not disable their tick function after being deactivated which leads to tick function being queued every frame. This can add up to multiple ms of time spend for queuing unused tick functions.

basic procedure is to spawn an actor and then deactivate all components via UActorComponent::Deactivate().

work-around is to explicitly call SetComponentTickEnabled() for every component.

following components we used in our project where still being queued even after being deactivated:

  • ParticleSystemComponent
  • AudioComponent
  • SceneComponent
  • StaticMeshComponent
  • TimelineComponent
  • SphereComponent
  • InstancedStaticMeshComponent
  • PointLightComponent
  • BoxComponent

Marc

Hi Marc,

I don’t believe I’m seeing this behavior. If I create an Actor and give it a ParticleSystemComponent, Deactivating it stops Particle System from emitting. Can you post the .h and .cpp for an example Actor that displays this issue for you?

You mention using SetComponentTickEnabled() for each component. Would using AActor::SetActorTickEnabled make this easier for you?

Hi ,

problem is not that e.g. particle system does not stop emitting particles. Most components seem to internally switch into a deactivated state however their tick function is still registered with FTickTaskLevel and thus being queued using task system. If there are a lot of deactivated actors / components time to queue their (useless) tick function adds up to a few ms per frame (at least on consoles). This can be checked in profiler listed as “Queue Ticks” (STAT_QueueTicks).

I cannot post a single cpp/h combination of an actor since that is part of a “pre-spawn” system that creates instances from any actor defined within project. However here are relevant code parts to pre-spawn a single actor and to test for problem:

		APrespawnableActor* actor = Cast<APrespawnableActor>( world->SpawnActor( _class, nullptr, nullptr, params ) );

[...]

	SetActorHiddenInGame   ( true );
	SetActorTickEnabled    ( false );

[...]

	TArray<UActorComponent*> components;
	GetComponents( components );

	for( UActorComponent* component : components )
	{
		component->Deactivate();

 		if( component->IsComponentTickEnabled() == true )
 		{
 			UE_LOG( LogTemp, Display, TEXT( "Tick Enabled after Deactivate: %s" ), *component->GetFullName() );
 		}

	}

Also AActor::SetActorTickEnabled() only modifies tick function of actor itself, not its components. This is mentioned in docs and it can be seen it code as well.

Marc

Hey mkamradt-

Using MyComponent->PrimaryComponentTick.SetTickFunctionEnable(false); within actor class will cause component to stop ticking.

Cheers

Sir! Thank you very much! I couldn’t figure out why my 2000 deactivated, non visible, SetComponentTickEnabled false components were hurting my performance so bad. I added your suggestion above, and I got performance I would have expected. Again thank you!