Can I find actors with name or tag at runtime?

Hello,

I have a question. UE4 supports to rename name of actor instances and add tag to them. It’s very useful. Now can I find actors at runtime by using name of tag on BP, like Unity3D?

var cameraObj : GameObject;
cameraObj = GameObject.Find("MainCamera");

var playerObjs : GameObject[];
playerObjs = GameObject.FindGameObjectsWithTag("Player");

If I can do this, it’s convenience for spawnable actors.

Thanks in advances,
Kazuhisa Minato.

We don’t have any fast-query structure for tags - that isn’t really the way they are expects to be used. I would highly suggest using pointers to Actors rather than finding them by name. Finding by name makes things very hard to debug, and is never good for performance. If you have 2 Actors placed in a level, and one needs to reference the other, you can just expose an editable Actor UPROPERTY in C++ and set up that pointer in the editor (using ‘lock details’ and then ‘use selected’).

In the next release we have greatly improve the performance of iterating over object by class, so that is another way to do this - if you want to find all Actors of a specific class and do something to them.

Dear James,

in the next release will the performance increase be for this sort of syntax?

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

or is there a different iterator I should be planning to use?

:slight_smile:

I’m super excited about the performance increase given that the nature of my project requires iterating over specific classes very frequently!

:slight_smile:

Rama

Right now only TObjectIterator gets the acceleration, but we are having a conversation right now about applying this to the Actor iterator as well.

well please do let me know what you decide, as I will be rewriting large amount of code if you choose to not include the Actor iterator, replacing my code with TObjectIterator :slight_smile:

Great to hear from you James!

I am loving UE4 C++ !

:slight_smile:

Rama

Update: I added a tutorial on answer and code for your question to my main C++ thread

http://forums.epicgames.com/threads/972861-TUTORIALS-C-for-UE4-gt-gt-New-Complete-Code-Custom-Screenshot-Save-System-For-You?p=31679652&posted=1#post31679652


Dear Kasuhisa,

Hi there!

I do think I have the answers for you :slight_smile:

The function I think you want is:

line 602 of Actor.h

/** See if this actor contains the supplied tag */
	UFUNCTION(BlueprintCallable, Category="Misc")
	bool HasTag(FName Tag) const;

To loop through ALL actors, you can check out my tutorial on looping through all actors, here’s the code

http://forums.epicgames.com/threads/972861-Tutorials-C-for-UE4-Code-Samples-gt-gt-New-Video-Freeze-Render-When-Tabbed-Out?p=31663817&viewfull=1#post31663817

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;
	}
}

To loop through a subset of all actors based on a class of your choosing, for example, you only want to search through all Static Mesh Actors and look for a certain tag:

http://forums.epicgames.com/threads/972861-TUTORIALS-C-for-UE4-gt-gt-New-Change-Global-Post-Process-During-Game!?p=31667115&viewfull=1#post31667115

void AYourController::PrintAllSMAActorsLocations()
{
  //EngineUtils.h
	TActorIterator< AStaticMeshActor > ActorItr =
    TActorIterator< AStaticMeshActor >(GetWorld());
	
	//While not reached end (overloaded bool operator)
	while (ActorItr)
	{
		ClientMessage(ActorItr->GetClass()->GetDesc());
		ClientMessage(ActorItr->GetActorLocation().ToString());
		
		//next actor
		++ActorItr;
	}
}

So here’s a full code example using actor has tag to check if any Static Mesh Actors in the level have a certain tag:


void AYourController::AddSMAActorsWithTag(const FName &TheSearchTag, TArray &SMAsWithTag)
{

  //SMAsWithTag.Empty();  //uncomment this line to replace a previous search
  
//EngineUtils.h
	TActorIterator< AStaticMeshActor > ActorItr =
		TActorIterator< AStaticMeshActor >(GetWorld());
	
	//While not reached end (overloaded bool operator)
	while (ActorItr)
	{
		//debug info, useful if this function is in a player controller class
		//ClientMessage(ActorItr->GetClass()->GetDesc());
		//ClientMessage(ActorItr->GetActorLocation().ToString());
		
		if(ActorItr->HasTag(TheSearchTag))
        {
           SMAsWithTag.AddItem(Cast(*ActorItr));
        }
		
		
		//next actor
		++ActorItr;
	}
}

//you should pass in an empty TArray for the function to fill, ex:
TArray MySMAs; //could be global class var or declared in a function;

Hi Nathan,

Thank you for your detailed replay. To use this function on BluePrint, do I need to write C++ code? I understand finding actors from all actors is very heavy process and we should not use it many times. But, if a leveldesigner and artist can use it on EventGraph of spawnable BluePrint, it is very useful for prototyping. They can find MainCamera, Light and any kinds of Actors on runtime at initialization.

Because I am a programmer, it’s easy to write code and add new kismet callable function from your code. But, if Rocket provides a such function for all Rocket users in default, it would be very helpful for artists and designers. Unity3D provides this feature (GameObject.FindXXXX API) for casual developers.

Best Regards,

Kazuhisa Minato.

" But, if Rocket provides a such function for all Rocket users in default,"

This feature is coming in the next beta, Epic has some awesome Actor Iterating plans for you :slight_smile:

They are called ForEach loops :slight_smile:

http://forums.epicgames.com/threads/974748-Engine-News-10-03-13?p=31675852&viewfull=1#post31675852

While waiting for next Beta I can highly recommend the TObjectIterator or the TActorIterator as per my code above.

Do note that what is most inefficient is not the ObjectIterator or the ActorIterator, it is the HasTag function itself

if you have other ways to identify relevant actors that are faster, as James Golding suggested, your code will be quite good using ObectIterator or TActorIterator as necessary

I have spent almost all day trying to make actor pointers work as you describe.
I’ve exposed an AActor pointer:

UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Interaction")		AActor*						buttonMoveLeft;

…but I am unable to assign anything to it - it keeps resetting to empty. It seems to be because I am trying to set up links within a blueprint (to other Actors in the same blueprint), because it does work if I do it on actors in the top-level scenes.

Is there any way to do this within a blueprint or will I have to pull everything in blueprints out into the main scene and lose the ability to share that content between scenes?