Quick answer: The most common cause is a class hierarchy mismatch. The object you are casting is not actually an instance of the target class or any of its subclasses.
Here is how to fix Unreal Blueprint cast always failing. Your Cast To node fires, the execution hits it, and every single time it takes the Cast Failed output pin. No error, no crash, just a silent failure that short-circuits the rest of your Blueprint logic. This is one of the most common problems in Unreal Blueprint development, and the cause is almost always a class hierarchy mismatch, a null input, or a misunderstanding of how Unreal handles object types at runtime.
The Symptom
You have a Cast To node targeting a specific Blueprint class — maybe your player character, an enemy AI, or a custom actor. You feed an actor reference into the Object pin and the node always takes the Cast Failed branch. It does not matter what you do; the cast never succeeds.
In some cases, the cast worked before and stopped working after you reparented a Blueprint, renamed a class, or moved assets between folders. In other cases, it never worked from the start, and you cannot figure out why an object that “should be” the right type is not being recognized.
The Output Log shows no warnings about the failed cast. Unreal treats a failed cast as a normal control flow event, not an error, which makes it harder to diagnose.
Understanding the Class Hierarchy
The Cast To node in Blueprints is a dynamic_cast under the hood. It checks whether the runtime type of the input object is the target class or any subclass of it. If you cast to BP_PlayerCharacter but the actual object is a plain ACharacter, the cast fails because ACharacter is a parent of BP_PlayerCharacter, not a child.
This is where most people get confused. Consider this hierarchy:
// Class hierarchy
AActor
ACharacter
AMyCharacterBase // C++ class
BP_PlayerCharacter // Blueprint class
BP_EnemyCharacter // Blueprint class
If you have a variable of type ACharacter* and the actual runtime object is BP_EnemyCharacter, then casting to BP_PlayerCharacter will fail every time. They share a common ancestor but neither is a subclass of the other.
Verify the actual class at runtime. Before the Cast To node, use a Print String node connected to the output of a GetClass → GetDisplayName chain. This shows you exactly what the object is.
// C++ equivalent of checking the class
if (AActor* HitActor = HitResult.GetActor())
{
UE_LOG(LogTemp, Warning, TEXT("Actual class: %s"),
*HitActor->GetClass()->GetName());
AMyPlayerCharacter* Player = Cast<AMyPlayerCharacter>(HitActor);
if (Player)
{
// Cast succeeded
Player->TakeDamage(10.f);
}
else
{
UE_LOG(LogTemp, Warning, TEXT("Cast to AMyPlayerCharacter failed"));
}
}
Null References Kill Casts Silently
If the input to the Cast To node is null, the cast fails. This is the second most common cause and it is deceptively hard to spot in Blueprints because the wire carrying the null reference looks exactly the same as one carrying a valid object.
Common sources of null references that feed into casts:
Get Player Character at the wrong time. If you call GetPlayerCharacter in a Construction Script or before the player has possessed a pawn, the return value is null. The cast that follows will always fail.
Overlap events with destroyed actors. An overlap event can fire for an actor that is in the process of being destroyed. By the time your cast executes, the object may be pending kill and return null from the overlap result.
Unset variables. You have an actor reference variable that you expect to be filled by an assignment elsewhere, but the assignment never ran or ran on a different instance. The variable remains its default value of null.
// Always validate before casting
void AMyTrigger::OnOverlapBegin(
UPrimitiveComponent* OverlappedComp,
AActor* OtherActor,
UPrimitiveComponent* OtherComp,
int32 OtherBodyIndex,
bool bFromSweep,
const FHitResult& SweepResult)
{
if (!IsValid(OtherActor))
{
UE_LOG(LogTemp, Warning, TEXT("OtherActor is null or pending kill"));
return;
}
AMyPlayerCharacter* Player = Cast<AMyPlayerCharacter>(OtherActor);
if (Player)
{
Player->CollectPickup(this);
}
}
In Blueprints, add an IsValid node before the Cast To node. If the IsValid check fails, you know the problem is upstream of the cast, not the cast itself.
Interface Casting vs Class Casting
If you find yourself casting to multiple different classes to call the same function on each one, you are probably fighting the wrong battle. Unreal provides Blueprint Interfaces specifically for this use case, and they avoid the class hierarchy problem entirely.
Use Cast To when you need access to specific properties of a known class. Use Interfaces when you need to send a message to any actor that supports it, regardless of its type.
Here is the difference in practice. Suppose you have a damage system where multiple actor types can take damage: players, enemies, destructible barrels, and breakable walls. With casting, you need four separate Cast To nodes:
// Bad: casting to every possible class
void AProjectile::OnHit(AActor* HitActor)
{
if (auto* Player = Cast<APlayerCharacter>(HitActor))
Player->ApplyDamage(Damage);
else if (auto* Enemy = Cast<AEnemyCharacter>(HitActor))
Enemy->ApplyDamage(Damage);
else if (auto* Barrel = Cast<ADestructibleBarrel>(HitActor))
Barrel->ApplyDamage(Damage);
}
// Good: use an interface
void AProjectile::OnHit(AActor* HitActor)
{
if (HitActor->Implements<UDamageable>())
{
IDamageable::Execute_ApplyDamage(HitActor, Damage);
}
}
To set this up in C++, declare the interface:
UINTERFACE(MinimalAPI, Blueprintable)
class UDamageable : public UInterface
{
GENERATED_BODY()
};
class IDamageable
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintNativeEvent, BlueprintCallable)
void ApplyDamage(float Amount);
};
Any class that implements IDamageable can now receive the ApplyDamage call without the caller needing to know the concrete type. No cast required.
Soft References and Loading
Soft references (TSoftObjectPtr and TSoftClassPtr) are a common source of cast failures because an unresolved soft reference is null until you explicitly load it. If you store an actor as a soft reference and then try to cast the raw pointer without loading it first, the cast fails.
// Soft class reference - must be loaded before use
UPROPERTY(EditAnywhere, Category = "Config")
TSoftClassPtr<AMyEnemy> EnemyClass;
void ASpawner::SpawnEnemy()
{
// Wrong: EnemyClass.Get() may return null if not loaded
// UClass* Loaded = EnemyClass.Get();
// Correct: load synchronously, then use
UClass* Loaded = EnemyClass.LoadSynchronous();
if (Loaded)
{
GetWorld()->SpawnActor<AMyEnemy>(Loaded, &SpawnTransform);
}
else
{
UE_LOG(LogTemp, Error,
TEXT("Failed to load enemy class from soft reference"));
}
}
In Blueprints, soft references appear as asset paths (strings) rather than loaded objects. You must use the Async Load Asset or Load Asset Blocking node to resolve the reference into an actual object before passing it to a Cast To node.
Hard references (TSubclassOf, direct object pointers) do not have this problem because the referenced asset is loaded automatically when the owning Blueprint loads. However, hard references increase your memory footprint and load times because every hard-referenced asset is pulled into memory along with the referencing Blueprint.
Common Cast Patterns and Fixes
Casting from Get Player Controller. GetPlayerController returns APlayerController*. If your custom controller is BP_MyPlayerController, the cast works only if the Game Mode’s Player Controller Class is set to BP_MyPlayerController. Check your Game Mode settings in Project Settings → Maps & Modes.
Casting from Get Player Pawn. The pawn returned is whatever the player controller has possessed. If possession has not happened yet (common in BeginPlay), the pawn is null. Delay the cast or use an event that fires after possession, such as OnPossess in the controller.
Casting overlapping actors. Overlap events give you the overlapping actor as AActor*. If the actor is a child actor of a larger Blueprint, you get the child component’s owner, not the top-level Blueprint. Use GetOwner() or GetAttachParentActor() to walk up to the expected type.
// When the overlapping actor is a child actor component
void AMyTrigger::OnOverlapBegin(AActor* OtherActor)
{
// Direct cast might fail if OtherActor is a child actor
AMyEnemy* Enemy = Cast<AMyEnemy>(OtherActor);
if (!Enemy)
{
// Try the owner instead
Enemy = Cast<AMyEnemy>(OtherActor->GetOwner());
}
if (Enemy)
{
Enemy->OnEnteredZone();
}
}
Casting after async loading. When loading assets asynchronously via StreamableManager, the loaded asset is returned as a UObject*. You must cast it to the expected type, and the cast will fail if the asset was not the type you expected or if loading silently failed and returned null.
Related Issues
If your cast succeeds but the Blueprint event you call afterward does not fire, see our guide on Blueprint events not firing. If you are casting to a widget class and it always fails, the issue might be that the widget was never created — check widgets not showing on screen for creation and visibility issues.
Print the class name before every cast. If it says the C++ parent instead of your Blueprint class, your Game Mode is spawning the wrong type.