Why does APlayerController::GetHitResultUnderCursor not function properly if there is no Player Start in a level?

I have a simple level with a bunch of static meshes and a custom game mode and player controller that provides mouse functionality. If i delete the player start from the level, GetHitResultUnderCursor always returns an actor with the name “DefaultPawn_”, but with a Player Start in the level, the correct actor under the cursor is reported.

What does Player Start provide that enables this and is there a way to circumvent needing a player start? for this project I don’t think I need a Player Start as there’s no concept of a traditional in-game player object, so the less clutter the better.

Hey -

Where are you using GetHitResultUnderCursor? In a simple blueprint test (Level Blueprint screenshot of the setup below) I found that hovering the mouse over different object printed the correct names to the screen even without a player start in the level. Please explain your setup and/or list the code you’re using so that I can follow your steps in my testing.

Cheers

Hi , Thanks for taking a look a this. Apologies for not posting my code originally, here’s what I’m working with:

RSController.cpp

ARSController::ARSController(const FObjectInitializer &pInit) : Super(pInit)
{
	this->PrimaryActorTick.bCanEverTick = true;
	this->PrimaryActorTick.bStartWithTickEnabled = true;
	this->bShowMouseCursor = true;
	this->bEnableClickEvents = true;
	this->bEnableMouseOverEvents = true;
	this->DefaultClickTraceChannel = ECollisionChannel::ECC_WorldStatic;
	this->AutoReceiveInput = EAutoReceiveInput::Player0;
}

void ARSController::BeginPlay()
{
	GEngine->AddOnScreenDebugMessage(-1, 4.0f, FColor::Blue, TEXT("Starting Up Player Controller"));

}

void ARSController::Tick(float pDeltaTime)
{
	FHitResult hit;
	if (GetHitResultUnderCursor(DefaultClickTraceChannel, false, hit))
	{
		auto msg = TEXT("WE GOT ONE: ")+hit.GetActor()->GetName();
		GEngine->AddOnScreenDebugMessage(-1, 4.0f, FColor::Cyan, msg);
	}
}

StainedGlassGameMode.cpp

AStainedGlassGameMode::AStainedGlassGameMode(const FObjectInitializer &pInit) : Super(pInit)
{
	PlayerControllerClass = ARSController::StaticClass();
}

Looking at your BP Setup, i think I’m doing something similar, but I’m not sure. Interestingly enough, I just changed my code to use GetHitResultUnderCursorForObjects, i.e.:

RSController.cpp

void ARSController::Tick(float pDeltaTime)
{
	FHitResult hit;

	TArray<TEnumAsByte<EObjectTypeQuery>> oTypes;
	//oTypes.Init(EObjectTypeQuery::ObjectTypeQuery_MAX);
	oTypes.Add(EObjectTypeQuery::ObjectTypeQuery1);

	if (GetHitResultUnderCursorForObjects(oTypes, false, hit))
	{
		auto msg = TEXT("WE GOT ONE: ")+hit.GetActor()->GetName();
		GEngine->AddOnScreenDebugMessage(-1, 4.0f, FColor::Cyan, msg);
	}
}

And now it works as expected. I’m not really married to using one function over the other, I just threw in the one I came across first. Is there a huge different between the two functions, i.e. is there a specific one I should be using? This is definitely not a showstopper, I’m just trying to learn as much as I can. Thanks again!

GetHitResultUnderCursor as you mentioned originally is a deprecated function and instead you should use GetHitResultUnderCursorByChannel or GetHitResultUnderCursorForObject depending on your needs.

Ah nice, i should’ve looked in the header first, thanks for clearing that up!