Casting to Actor Class causes crash on project startup

void AMyPlayerController::MousePressed()
{
UE_LOG(LogTemp, Warning, TEXT(“Mouse Pressed”));
// Trace to see what is under the mouse cursor

    FHitResult Hit;
    GetHitResultUnderCursor(ECC_Visibility, false, Hit);
    
    if (Hit.bBlockingHit)
    {
        if(Hit.GetActor()->IsA(AMyPaperFlipbookActor::StaticClass()))
        {
            AMyPaperFlipbookActor* OtherCharacter = Cast<AMyPaperFlipbookActor>(Hit.GetActor());
            
            if(OtherCharacter)
            {
                OtherCharacter->Selected();
            }
        }
    }
    
    bMoveToMouseCursor = false;
}

Hi there,

I am working on a strategy game in Unreal and I am currently setting up player input for selecting characters. The code above is from my PlayerController class and is called when the player left clicks in the game. It checks if the mouse hits something, and if it does it then checks if what it hit was of the MyPaperFlipbookActor class. If so, I then want to cast to that class, and call a function in that class called Selected();

The problem occurs when I do the casting stuff. The code compiles fine, I play the game and when I click on a flip book actor, it’s Selected() function is successfully called. So I’m thinking it should be fine, but when I close the game and try to reopen it, the project crashes every time when it reaches 70%. I’ve narrowed down the crash to only be happening when I add in the cast to MyPaperFlipbookActor.

What’s frustrating is that taking the casting part out of the code and recompiling doesn’t fix the issue. It compiles successfully but game still crashes on startup. What I have to end up doing to fix it is going through my source control to a previous state, recompiling, and then start the game.

Am I doing something wrong when casting? It does work and act as intended, but the problem just occurs when I close Unreal and try to reopen.

Any help would be greatly appreciated.

Thanks,

Eric

Hi epeterford,

I am not sure why you are having a issue with your cast but as an example, I put together a function of how I would go about tracing and seeing if that trace hit a character.

The difference with my code is that my character class is named ATwoDCodeCharacter while yours is called, AMyPaperFlipbookActor.

void ATwoDCodeCharacter::Click()
{
	ATwoDController *GameController = Cast<ATwoDController>( GetController( ) );
	if (GameController)
	{
		FVector MousePos;
		GameController->GetMousePosition( MousePos.X, MousePos.Y );

		FHitResult Hit;
		GameController->GetHitResultAtScreenPosition( FVector2D( MousePos.X, MousePos.Y ),ECollisionChannel::ECC_WorldDynamic, FCollisionQueryParams::FCollisionQueryParams( ), Hit );
		if (Hit.GetActor( ))
		{
			ATwoDCodeCharacter *HitCharacter = Cast<ATwoDCodeCharacter>( Hit.GetActor( ) );
			if (HitCharacter)
			{
				UE_LOG( LogTemp, Warning, TEXT("We hit a ATwoDCodeCharacter! %s"), *Hit.GetActor( )->GetName( ) );
			}
		}
	}
}

I have this function being called by a Input Action called Click, which is setup to be called on Left Mouse Click, in my Character class.

void ATwoDCodeCharacter::SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent)
{
	PlayerInputComponent->BindAction("Click", IE_Pressed, this, &ATwoDCodeCharacter::Click);
}

I think the problem is not the casting. It’s in the Selected function of that actor. Crash while the editor is loading is usually caused by corrupt object, maybe you store a reference to a selected transient actor in a property that is serialized, when you click save in the editor the actor (which is transient) is serialized but when the editor starts it tries to look up the object using the saved object path and see that it’s not there and breaks the execution.

As a side note, your code may crash in line 11 if you click on BSP. It would happen, because if you’d click on BSP Hit.bBlockingHit would return true, but a BSP is not an actor thus Hit.GetActor() would be null.

To prevent such cases, you should alter your 9th line to smth like this:

if (Hit.bBlockingHit && Hit.GetActor())

or totally ignore Hit.bBlockingHit part and go for

if (Hit.GetActor())

Also, i’d remove line 11 as it isn’t needed that much IMO. So the code would look like:

void AMyPlayerController::MousePressed()
 {
     UE_LOG(LogTemp, Warning, TEXT("Mouse Pressed"));
     // Trace to see what is under the mouse cursor
     
     FHitResult Hit;
     GetHitResultUnderCursor(ECC_Visibility, false, Hit);
     
     if (Hit.GetActor())
     {
        AMyPaperFlipbookActor* OtherCharacter = Cast<AMyPaperFlipbookActor>(Hit.GetActor());
             
        if(OtherCharacter)
        {
             OtherCharacter->Selected();
        }         
     }
     
     bMoveToMouseCursor = false;
 }