Event when actor selected in editor

I would like to know how to react to actors being selected in the editor.

I have tried:

UCLASS()
class TEST_API UTESTEditorEngine : public UEditorEngine
{
	GENERATED_BODY()

public:

	void SelectActor(AActor* Actor, bool InSelected, bool bNotify, bool bSelectEvenIfHidden /*= false*/, bool bForceRefresh /*= false*/) override;
	
};

but this method does not seem to run in the editor.

Just to clarify, this is before play is pressed, I want the event to run only when editing.

Any way i can make this question clearer to help you guys answer it?

In the Actor’s constructor, bind the SelectObjectEvent like this:

AMyActor::AMyActor(const class FObjectInitializer& ObjectInitializer)
   	: Super(ObjectInitializer)
{
	...other stuff...

	#if WITH_EDITORONLY_DATA
		USelection::SelectObjectEvent.AddUObject(this, &AMyActor::OnObjectSelected);
	#endif
}

Then declare/implement the OnObjectSelected function:

In MyActor.h:

#if WITH_EDITORONLY_DATA
	void OnObjectSelected(UObject* Object);
	bool SelectedInEditor = false;
#endif

In MyActor.cpp:

#if WITH_EDITORONLY_DATA
void AMyActor::OnObjectSelected(UObject* Object)
{
	UE_LOG(LogTemp, Log, TEXT("%s::OnObjectSelected(): %s was %s."), *GetName(), *Object->GetName(), *FString(Object->IsSelected() ? "selected" : "de-selected"));

	if (Object == this)
	{
		SelectedInEditor = true;

		...do stuff when your actor is selected...
	}
	else if (SelectedInEditor && !IsSelected())
	{
		SelectedInEditor = false;

		...do stuff when your actor is un-selected...
	}
}
#endif

Beware: OnObjectSelected will be called on every actor you have in the scene. This is why you have to filter out only what is relevant to your object (hence the if (Object == this) ).

It’s a bit harder to detect that an object that is un-selected. You have to keep a flag (bool SelectedInEditor) on your actor that is set when it is selected. Then, when you receive the object selected event for another object and IsSelected() on yourself returns false, you are officially un-selected.

1 Like

I came across this thread and while the above solution works great for selecting actors in the viewport, it does not work when selecting actors in the World Outliner (see Unreal Engine Issue (UE-46676)).

In case anyone comes by this thread and is wondering, like me, how to get this working with the World Outliner, I wanted to share a similar solution that works any time an actor is selected in the editor, whether it’s through the viewport or World Outliner:

(This was tested in Unreal Engine 4.27)

In the Actor’s constructor, bind the selection event like this:

#include "Engine/Selection.h"

AExampleActor::AExampleActor()
{
    #if WITH_EDITOR
    // Broadcast whenever the editor selection changes (viewport
    // or world outliner)
    USelection::SelectionChangedEvent.AddUObject(this, 
                                         &AExampleActor::OnSelectionChanged);
    #endif
}

In ExampleActor.h

#if WITH_EDITOR
    void OnSelectionChanged(UObject* NewSelection);
    bool bSelectedInEditor;
#endif

In ExampleActor.cpp

void AExampleActor::OnSelectionChanged(UObject* NewSelection)
{
	TArray<AExampleActor*> SelectedExampleActors;
	
	// Get ExampleActors from the selection
	USelection* Selection = Cast<USelection>(NewSelection);
	if (Selection != nullptr)
	{
		Selection->GetSelectedObjects<AExampleActor>(
						SelectedExampleActors);
	}
	
	// Search the selection for this actor
	for (AExampleActor* SelectedExampleActor : SelectedExampleActors)
	{
		// If our actor is in the selection and was not previously
		// selected, then this selection change marks the actor
		// being selected
		if (SelectedExampleActor == this && !bSelectedInEditor)
		{
			// Respond to this actor being selected
			bSelectedInEditor = true;
		}
	}

	// If our record shows our actor is selected, but IsSelected() is false,
	// this selection change marks the actor being deselected
	if (bSelectedInEditor && !IsSelected())
	{
		// Respond to this actor being deselected
		bSelectedInEditor = false;
	}
}
#endif

I found this solution in Unreal Engine’s AIModule’s EQSTestingPawn.cpp, which implements a lot of editor-only debugging tools like this if you want to see more examples / robust editor debugging tools.

The level editor module has a “OnActorSelectionChanged” delegate you can use.

FLevelEditorModule& levelEditor = FModuleManager::GetModuleChecked(TEXT(“LevelEditor”));
levelEditor.OnActorSelectionChanged().AddUObject(this, &UElgEditorContext_LevelEditor::HandleOnActorSelectionChanged);

I use it in my EditorScripting plugin to expose that event to Editor Utility Widgets.

1 Like