TActorIterator Could Use Some Loving Attention

Dear Friends at Epic,

Hi there! I’m loving UE4! Yay!


The TActorIterator could really use some loving attention, it is not quite as easy to use as the Object Iterator, and also I was informed that the Object Iterator is getting an acceleration of its functioning in next beta,

but it is as yet unclear what will be the fate of the actor iterator.


The reason I am such a fan of the actor iterator is that, unless I am mistaken, just because it is an actor iterator it should already run faster for most of my inquiries since I am mostly only searching for a specific class of Actor, not usually as broad a scope as any object in the world.

So if Object Iterator and Actor
iterator were running equally fast and
were equally easy to use, the Actor
Iterator would always be my favored
iterator for most of my game engine needs.


Object Iterator Syntax Advantages

Currently the object iterator has some advantages just in the code, let alone the expected upcoming acceleration.

This code compiles for an object iterator:

for ( TObjectIterator It; It; ++It )
	{
		if (It->PlayerVibe == PlayerVibe)
		{
			It->VictoryPC = this;
		}
	}

This does not compile for an Actor iterator

for ( TActorIterator It; It; ++It )
	{
		if (It->PlayerVibe == PlayerVibe)
		{
			It->VictoryPC = this;
		}
	}

Compile error:

E:\RocketVictory\VictoryGame\Source\VictoryGame\Private\Player\VictoryGamePlayerController.cpp(789): error C2512: 'TActorIterator' : no appropriate default constructor available
1>          with
1>          [
1>              ActorType=AVictoryPower
1>          ]

Requiring me to do a more complex initialization, at least in current beta (the while loop is just my choice, its the initialization that my point:

TActorIterator< AVictoryWarrior > ActorItr = 
		TActorIterator< AVictoryWarrior >(GetWorld());
	while (ActorItr)
	{
		if (Cast(*ActorItr)->PlayerVibe == PlayerVibeFuncIn)
		{
			return Cast(*ActorItr);
			
		}
		++ActorItr;
	}

More complicated retrieval of Current Iterated Actor


Also note that in the Object Iterator, I do not need to cast the retrieved iterated object!

if (It->PlayerVibe == PlayerVibe)
 {
    	It->VictoryPC = this;
 }

Whereas this will not compile for the Actor iterator as the return of the actor iterator * operator is not typed apparently

The casting is required for compiling, in current beta

if (Cast(*ActorItr)->PlayerVibe == PlayerVibeFuncIn)
    {
    	return Cast(*ActorItr);			
  }

My Request

I would really like the ActorIterator to become as powerful, fast, and easy to use in code as the object iterator,

as just by its nature, the Actor Iterator is more appropriate and logically more efficient for my game engine.

But currently the Actor Iterator’s implementation is not up to par with the Object Iterator and it is unknown to me whether the Actor Iterator is getting the accelerated functioning in the next beta like the Object Iterator is.

Thanks for considering my request!

tyepicdevsheart.jpg

Rama

The ActorIterator is being modified to use the same performance improvements that the object iterator is getting. You are right that historically the actor iterator was much faster because it was iterating a much shorter list to find actors of the specified class, however, with the changes to the object iterator and the similar ones to come for the actor iterator that is no longer a significant difference.

An actor iterator is intended to be used for the actors in a single world. Keep in mind that when in the editor and doing a PIE session an object iterator will be returning all instances of objects both in the PIE session as well as the editor world (and any worlds for preview scenes in persona, the blueprint component window, etc.) which is generally not what you want. As such the ActorIterator will always require the world be supplied and if you genuinely want all actors in all worlds you should use the TObjectIterator.

A TActorIterator and a TObjectIterator should be identical in terms of the need to cast or not. If the TActorIterator is not working that way it would definitely be a bug, I will take a look at that when I’m back in the office on Monday.

Dear Marc, thanks for the detailed answer!

I am happy to hear that the ActorIterator is getting the same performance improvements!

:slight_smile:

Yes there’s definitely a casting issue, the current beta → operator for actor iterator is not returning the typed version I guess

This compiles

TActorIterator< AVictoryWarrior > ActorItr = 
		TActorIterator< AVictoryWarrior >(GetWorld());
	while (ActorItr)
	{
		//player vibe match?
		if (Cast(*ActorItr)->PlayerVibe == PlayerVibeFuncIn)
		{
			return Cast(*ActorItr);
			
		}
		++ActorItr;
	}

         return NULL;

This does not compile in the current beta, for me at least:

TActorIterator< AVictoryWarrior > ActorItr = 
		TActorIterator< AVictoryWarrior >(GetWorld());
	while (ActorItr)
	{
		//player vibe match?
		if (ActorItr->PlayerVibe == PlayerVibeFuncIn)     //<----
		{
			return *ActorItr;
			
		}
		++ActorItr;
	}
	
	return NULL;

Error message:

1>E:\RocketVictory\VictoryGame\Source\VictoryGame\Private\Player\VictoryGamePlayerController.cpp(2895): error C2039: 'PlayerVibe' : is not a member of 'AActor'
1>          c:\program files\rocket\engine\intermediate\builddata\include\engine\../../../../Source/Runtime/Engine/Classes/GameFramework/Actor.h(28) : see declaration of 'AActor'

Great to hear from you as always Marc!

Rama

Thanks for the report on the TActorIterator bug. The * operator for dereferencing properly returned the templated actor type, but the → operator always returned AActor*, that’s a great catch.

One small thing I might mention is when you are declaring your actor iterator you don’t need to do a full assignment the way that you are. The following is equivalent and cleaner to read (in my opinion) and (very very slightly, probably unmeasurably) more efficient.

TActorIterator< AVictoryWarrior > ActorItr(GetWorld());

Dear Marc Audy,

Yay! I’m happy to have helped out :slight_smile:


“The following is equivalent and cleaner to read (in my opinion) and (very very slightly, probably unmeasurably) more efficient.”

Well I am using TActorIterators constantly so this efficiency improvement will add up, thanks so much Marc!


and oooh thank you soo much for this code-reading efficiency suggestion!

I use TActorIterators EVERYWHERE in my code, because I am writing my own in-game editor with dynamic object creation and removal, and my own 3d kismet to iterate over those dynamically created objects

You’ve helped my code go from looking like:

TActorIterator< ADirectionalLight > ActorItr = TActorIterator< ADirectionalLight >(GetWorld());

to:

//oh so nice
TActorIterator< ADirectionalLight > ActorItr(GetWorld());

Yay!


Thanks Marc!

Rama