How to get the clicked object in C++?

On the object you want to click and interact with, add a OnClick event that triggers the function you want. You also need to change the controller to enable click events.

I believe this is the C++ syntax to bind a function to when the actor is clicked.

	OnClicked.AddDynamic(this, &AExampleActor::DoAthing);

To change the controller in UE4 go to Blueprints->Project settings → Game mode classes and then change the controller class.

59419-changecontroller.png

Personally I would make the controller as a blueprint instead of C++ or at least create a BP derived from the C++ controller because it is easier to change the settings in my opinion.

1 Like

void ARTSPlayerController::MouseClicked()
{
FHitResult Hit;
GetHitResultUnderCursor(ECC_Pawn, false, Hit);

	if (Hit.bBlockingHit){
		if (Hit.Actor != NULL){
			AMyCharacter* Selected = Cast<AMyCharacter>(Hit.GetActor());
		}
	}	
}

I’m trying to create a RTS game, and i need to select the object and operate it by clicking it. Here’s the code i am trying to, but the Selected return NULL.
How can i get the clicked object by clicking?
Thank you in advance.

Thank you for helping me to solve this problem, i know the OnClick() event, but i am doing the RTS-style game, so i have to maintain a TArray SelectedArray, and all the data (character, object in the scene, etc) are dynamically imported. I am very poor at Blueprint, so i don’t know if the blueprint can handle this kind of situation. So if there is a way to interact with object in C++, it would be good for me.

I think I might understand what you mean now. In C++ you want to know of what you clicked from within the player class, rather than having the clicked thing perform some logic.

If I needed to know all the things I clicked. I would have just had the clicked object return a pointer to a container I could access in my class scope, with the OnClick event.

I’m trying to think of a way of knowing what was clicked and return it to the class scope you need…

I only added that blueprint thing at the end as a reminder that you need to ensure the character controller stuff has enabled the mouse and click events. You could also do it in C++*

I was unable to find a way to learn of what is clicked from within your class scope. I understand that not every thing you spawn and dynamically create has logic components but I have come up with a solution that I got working on my end. It is based on what I said earlier (So still might not be useful to you).

If you create an actor component and attach it to every thing you spawn (You can do the attach in c++) you can give all of them the OnClick Logic. On my end I made a TArray in my gamemode instance (as an example). Whenever an object got clicked it added a pointer to that object, to my array correctly, which I could access within my player.

It’s inspiring. Maintaining a TArray Container in the gamemode and add the actor into it when OnClick() event happen should work. Fortunately, i modify the code and it works now. Well, it seem like the ECC_Visibility can get the object, ECC_Pawn just gives me the Pawn, and so Cast to AMyCharacter doesn’t work. Here is the new code:

    void ARTSPlayerController::MouseLeftClicked()
    {
    	FHitResult Hit;
    	GetHitResultUnderCursor(ECC_Visibility, false, Hit);
    
    	if (Hit.bBlockingHit)
    	{
    		AMyCharacter* SelectCharacter = Cast<AMyCharacter>(Hit.GetActor());
    		if (SelectCharacter)
    		{
    			if (!SelectCharacter->IsClicked())
    			{
    				SelectCharacter->SetClicked();
    				ArraySelectedCharacter.Add(SelectCharacter);
    				GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Red, "True");
    			}
    			else
    			{
    				GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Red, "False");
    			}
    			GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Red, FString::FromInt(ArraySelectedCharacter.Num()));
    		}
    		else
    		{
    			int ArraySize = ArraySelectedCharacter.Num();
    			for (int index_declick = 0; index_declick < ArraySize; index_declick++)
    			{
    				AMyCharacter* Temp_Character = ArraySelectedCharacter[0];
    				Temp_Character->DeClicked();
    				ArraySelectedCharacter.RemoveSwap(Temp_Character);
    			}
    			GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Red, FString::FromInt(ArraySelectedCharacter.Num()));
    		}	
    	}
    }