[Resolved (Ty Marc) ] How do I instance the TActorIterator? AStaticMeshActor, ASomeCustomClass etc not working

Edit2: I posted a tutorial on how to do this, thanks to Marc’s help :slight_smile:

Link: How to Iterate Over Only Specific Class of All Actors in World

Edit: Solution as Per Marc:

    TActorIterator< AYourActorClass > CustomActorItr = 
                            TActorIterator< AYourActorClass >(GetWorld());

~

Dear Friends at Epic,

This should be an easy question :slight_smile: (but it is still unresolved)

I figured out how to use the regular Actor Iterator, and am currently filtering out class types manually.

I posted an example of All Actor iterator on the forum:

void AYourControllerClass::PrintAllActorsLocations()
{
	//EngineUtils.h
	FActorIterator AllActorsItr = FActorIterator(GetWorld());
	
	//While not reached end (overloaded bool operator)
	while (AllActorsItr)
	{
		ClientMessage(AllActorsItr->GetClass()->GetDesc());
		ClientMessage(AllActorsItr->GetActorLocation().ToString());
		
		//next actor
		++AllActorsItr;
	}
}

I would love to use the built in functions for filtering actors, but I just cannot figure out what template parameter type I am supposed to provide:

TActorIterator TheItr = TActorIterator(GetWorld);

I’ve tried variations like

TActorIterator TheItr = TActorIterator(GetWorld);
TActorIterator TheItr = TActorIterator(GetWorld);

and about 40 other things.

But I just cannot figure this out :slight_smile:

Could you please show me an example of code for instancing a TActorIterator?

I know how to iterate over them and all that, I just cant instance it and supply template parameters that it accepts

EngineUtils.h
/**
 * Template filter to select actors based on their type.
 */
template 
class TActorTypeFilter :
	public FActorFilter
{
public:
	/**
	 * Determines if the actor should be returned during iteration or not
	 *
	 * @param	ActorIndex ignored
	 * @param	Actor	Actor to check
	 * @return	true if actor is selected, false otherwise
	 */
	FORCEINLINE bool IsSuitable( int32 /*ActorIndex*/, AActor* Actor ) const
	{
		return Actor ? Actor->IsA(ActorType::StaticClass()) : false;
	}
};

/**
 * Template actor iterator. Uses TActorTypeFilter to iterate over actors of the template type.
 */
template 
class TActorIterator : 
	public TActorIteratorBase< TActorTypeFilter >
{
public:
	/**
	 * Constructor, inits the starting position for iteration
	 */
	TActorIterator( UWorld* InWorld )
		: TActorIteratorBase< TActorTypeFilter >( InWorld )
	{
		++(*this);
	}

	/**
	 * Returns the current suitable actor pointed at by the Iterator
	 *
	 * @return	Current suitable actor
	 */
	FORCEINLINE ActorType* operator*()
	{
		check(FActorIteratorBase::CurrentActor);
		checkf(!FActorIteratorBase::CurrentActor->HasAnyFlags(RF_Unreachable), TEXT("%s"), *FActorIteratorBase::CurrentActor->GetFullName());
		return CastChecked(FActorIteratorBase::CurrentActor);
	}
	/**
	 * Returns the current suitable actor pointed at by the Iterator
	 *
	 * @return	Current suitable actor
	 */
	FORCEINLINE AActor* operator->()
	{
		check(FActorIteratorBase::CurrentActor);
		checkf(!FActorIteratorBase::CurrentActor->HasAnyFlags(RF_Unreachable), TEXT("%s"), *FActorIteratorBase::CurrentActor->GetFullName());
		return CastChecked(FActorIteratorBase::CurrentActor);
	}
};

Thanks!

:slight_smile:

Rama

The class type of the actor to iterate over is the template property. I did notice in your examples GetWorld did not have the () after it. This should be correct incantation:

TActorIterator< APawn > TheItr = TActorIterator(GetWorld());

There must be a bug with this build then, because I’ve tried that a gazillion times :slight_smile: Thanks for the help (the get world was just a typo)

Here’s my code:

TActorIterator< APawn > PawnItr = TActorIterator(GetWorld());

Here’s the error I am getting

------ Build started: Project: VictoryGameEditor, Configuration: Development x64 ------
1> Parsing headers for VictoryGameEditor
1> Code generation finished for VictoryGameEditor and took 1.314
1> Module.VictoryGame.cpp
1>E:\RocketVictory\VictoryGame\Source\VictoryGame\Private\VictoryGamePlayerController.cpp(1516): error C2955: ‘TActorIterator’ : use of class template requires template argument list
1> c:\program files\rocket\engine\source\runtime\engine\public\EngineUtils.h(500) : see declaration of ‘TActorIterator’
1>E:\RocketVictory\VictoryGame\Source\VictoryGame\Private\VictoryGamePlayerController.cpp(1516): error C2512: ‘TActorIterator’ : no appropriate default constructor available
1> with
1> [
1> ActorType=APawn
1> ]
1> -------- End Detailed Actions Stats -----------------------------------------------------------
1>ERROR : UBT error : Failed to produce item:

the most confusing line to me in the error is this:

‘TActorIterator’ : no appropriate default constructor available with
[
ActorType=APawn
]

If you’re allocating your TActorIterator that way you’ll need to do:

TActorIterator< APawn > PawnItr = TActorIterator< APawn >(GetWorld());

The more typical usage case however, would be:

for (TActorIterator It< APawn >(GetWorld()); It; ++It) { ... }

But Marc what I am telling you is that

TActorIterator< APawn > PawnItr = TActorIterator< APawn >(GetWorld());

does not compile!

Please try it yourself using current Rocket beta build :slight_smile:

I dont really follow the more typical usage, where is the actor filter type being determined?

:slight_smile:

Rama

I did compile the code I provided you in the most recent rocket release and it does compile (specifically I dropped it in the ::OnFire function of the created Character class when creating a project from the first person code template). If I use the line that you provided above I get the exact same error that you did.

The difference is that I needed to specify the < APawn > in both the declaration and the construction. In your example line you don’t have the < A Pawn > on the second instance of TActorIterator on the line.

woohooo!!

Thank you Marc!

I did not realize the need for the 2nd

Thank youuuu

tyepicdevsheart.jpg

I think you need a pointer type, that’s the object. But, I’m not 100%. I’m at work and can’t check my project right now, I am using Iterators in two places though. I got that error when I was messing around trying to get the syntax right.

Not being able to see into the .cpp files I think it’s just a guessing game on how things are supposed to be called. After work I’ll check my project and post here if it’s not answered yet.

Nice to hear from you Michael!

I tried using several different kinds of pointers as well, judging from the code in my first post where it says ActorType::StaticClass() I should have to think that Marc’s version of just tying APawn would seem most correct, because that would become APawn::StaticClass()

but anything you find out in your own attempts to use TActorIterator do let me know please :slight_smile:

public:
    /**
     * Determines if the actor should be returned during iteration or not
     *
     * @param  ActorIndex ignored
     * @param  Actor    Actor to check
     * @return true if actor is selected, false otherwise
     */
    FORCEINLINE bool IsSuitable( int32 /*ActorIndex*/, AActor* Actor ) const
    {
       return Actor ? Actor->IsA(ActorType::StaticClass()) : false;
    }
};

That example should not compile. How can GetWorld() cast into a TActorIterator? It can’t work like that. The example I gave uses a Getter for an Iterator, that’s why the cast works.

It isn’t a cast, it is a TActorIterator constructor which takes the World as a parameter. The example you give would definitely work, but as Nathan referenced it only works for Pawns and Controllers. If you had an ABaseCat class and wanted to iterate over all of them you’d need to use the TActorIterator< ABaseCat> or another approach would be to use the FActorIterator and then do the Cast< ABaseCat> the way that you did with the PawnIterator. It would look roughly like the following (haven’t compiled this version).

	for (FActorIterator It(GetWorld()); It; ++It)
	{
		ABaseCat* cat =  Cast(*It);  
		if(cat)
		{
			cat->GetAttention(this);

		}
	}

Thank you for the clarification, this is very helpful. I should have looked more into it as I thought there was a typo.

for (FConstPawnIterator It = GetWorld()->GetPawnIterator(); It; ++It)
{
ABaseCat* cat = Cast(*It);
if(cat)
{
cat->GetAttention(this);

		}
	}

Thank you for this, perhaps using APawn was a bad example, the world iterators are only for pawn and controllers, I am needing a filter for any type of actor, like StaticMeshActor, for example, and especially for iterating over custom classes :slight_smile:

but thanks again for your research and code Michael!