How to get parent Character for UserWidget in c++?

I am trying to create a reusable health bar for any character in my game. I am using MVVM setup with UMainMVVMViewModelContextResolver for ViewModel Creation.

With all that, I have some issues with ContextResolver as its CreateInstance method provides me with UserWidget, which is fine when I was using it only for the player character. But when I want to use it for NPCs, I need to have an owner character reference to get its ViewModel instance.

As you can see, the Character owns the widget, my MainEnemy class, has a ViewModel instance inside it. So I need to access the Character that owns the widget, to get its view model, and return it from the resolver.

I tried a few things, but there is no method that gets the owner Actor, or Character.

I tried:

ACharacter* OwningCharacter = UserWidget->GetTypedOuter<ACharacter>();

and some other similar variations to get it, but probably it’s not structured as a Parent for it directly.

Here is my current version of the resolver for reference:


UObject* UMainMVVMViewModelContextResolver::CreateInstance(const UClass* ExpectedType, const UUserWidget* UserWidget, const UMVVMView* View) const
{
    UE_LOG(LogTemp, Warning, TEXT("UMainMVVMViewModelContextResolver"));
    if (!UserWidget)
        {
            UE_LOG(LogTemp, Warning, TEXT("ContextResolver NO WIDGET"));
            return nullptr;
        }
    
    // Get the actor that owns this widget (e.g., the enemy character instance).
    AActor* OwningActor = UserWidget->GetTypedOuter<AActor>();
        if (!OwningActor)
        {
            UE_LOG(LogTemp, Warning, TEXT("MyViewModelResolver: Widget has no OwningActor."));
            return nullptr;
        }

        // Attempt to cast the owner directly to your ACharacterBase class.
        ACharacterBase* CharacterOwner = Cast<ACharacterBase>(OwningActor);
        if (CharacterOwner)
        {
            // If the cast is successful, the owner is the correct type.
            // We can now access its ViewModel property and return it.
            // NOTE: This assumes your ViewModel property is named 'CharacterViewModel'.
            // If you named it something else (e.g., 'ViewModel'), change it here.
            UE_LOG(LogTemp, Log, TEXT("MyViewModelResolver: Found owner '%s' of type ACharacterBase. Returning its ViewModel."), *OwningActor->GetName());
            return CharacterOwner->VM_Health;
        }
        else
        {
            // If the cast fails, the widget's owner is not a child of ACharacterBase.
            UE_LOG(LogTemp, Warning, TEXT("MyViewModelResolver: OwningActor '%s' is not of type ACharacterBase."), *OwningActor->GetName());
        }
    
    
    return nullptr;
}

It returns: “MyViewModelResolver: Widget has no OwningActor.”.

I would appreciate it if you could help me figure this out by getting the Character, or maybe there is a better way to have this setup that you may know.

1 Like

While i have no idea what is UMainMVVMViewModelContextResolver, i’d like to clarify why UserWidget->GetOuter() may not work:

Your actual character is structured like:

Character

  • CapsuleComponent
  • ArrowComponent
  • WidgetComponent // ← accent on “Component”

“Component” is an UActorComponent and not a UUserWidget. Specific component downcast may have a pointer to your widget though.
The widget itself though is usually(?) parented to viewport (or other widgets that parented to viewport) and hence i doubt it’s have a character in its Outers chain. Though i may be wrong on this and it may be paranted to component in this case.

Anyway you may check what’s the type of object is returned by UserWidget->GetOuter() with debugger to be 100% sure what’s going on. May even check UserWidget->GetOuter()->GetOuter() and so on until you find the answer you need.
Note that i use GetOuter() that is always returns an UObject, this way you won’t lost the object due to attempt to cast it to wrong type

Hope this helps

1 Like

You can get the parent character by calling:

ACharacter* MyChar = Cast(GetOwningPlayerPawn());

This Works if your widget is owned by a PlayerController .