Update Widget Component C++ HELP

Good Evening everyone,

For a while I have been working on my own targeting system for my game. Atm, I’m creating a widget component so that whenever I press tab on my player, it’ll create an ‘X’ on the closest target available. However, whenever I press tab on my widget component, it’ll update the owner but it wont make my widget that its assigned to visible. I have my widget component ticking so that its always checking whether or not the player is targeting or not.

For quick references here is what I mean:

AIntPlayer.cpp


void AIntPlayer::Target(){
//player target holds the closest target reference
playerTarget = GetClosestTarget(GetActorLocation(), EnemyPlayer);

//if we're already targeting, untarget. Vice versa
bTargeting = bTargeting ? false : true;
}

TargetWidgetComponent.cpp




*NOTE: "WidgetInst" is from a tutorial I was following, by tom looman here: https://www.tomlooman.com/creating-actor-widgets-umg/


//this is the widget component. Inside the player, we have this component tied to the legit widget so we can mess with direct values from the target widget.

void UTargetWidgetComponent::InitWidget()
{
Super::InitWidget();
//if widget isnt null
if (Widget) {
#if!UE_BUILD_SHIPPING
//if the widget is not the target widget
if (!Widget->IsA(UTargetWidget::StaticClass())) {
//throw this error
UE_LOG(LogTemp, Warning, TEXT("WidgetClass for %s does not derive from SActorWidget"), *GetNameSafe(GetOwner()));
}
#endif
//pointer to call the widget. Casting it so target widget is extended.
WidgetInst = Cast<UTargetWidget>(Widget);
Player = Cast<AIntPlayer>(GetOwner());

//if target widget is valid
if (WidgetInst) {

//add the widget to the owner, it cannot be the same actor
WidgetInst->SetOwningActor(GetOwner());
}

}

void UTargetWidgetComponent::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction) //if i comment this function out, X reappears on character but is always showing.
{

if(WidgetInst && Player)
{
if (Player->bTargeting) {
WidgetInst->SetOwningActor(Player->playerTarget); //should update the closest player
WidgetInst->SetVisibility(ESlateVisibility::Visible); //targetwidget should now be visible, problem is here, its always hidden.
}
else
{
WidgetInst->SetVisibility(ESlateVisibility::Hidden);
}
}
else
{
UE_LOG(LogTemp, Warning, TEXT("player null"));
}

}




TargetWidget.cpp



//just switches the owning actor.
void UTargetWidget::SetOwningActor(AActor* NewOwner)
{

//if Owning actor is the same or if the owning pawn is = to the new owner aka itself.
if (OwningActor == NewOwner || GetOwningPlayerPawn() == NewOwner)
{
SetVisibility(ESlateVisibility::Hidden);
return;
}

//if its not, change the owning actor to the new actor
OwningActor = NewOwner;
OnOwningActorChanged.Broadcast(NewOwner);


UE_LOG(LogTemp, Warning, TEXT("Owning Actor : %s , NewOwner: %s"), *OwningActor->GetName(),
*NewOwner->GetName());

}




As you can see, I feel like it should be working but its not. It should replicate the way targeting works in Dark souls. With the dot on the player or enemy you’re targeting. Can anyone help me make this work? As it doesn’t seem to be displaying the “X” at all.

No one can help? :confused:

A couple of things.

Are you calling

SetDrawAtDesiredSize(true);
SetWidgetSpace(EWidgetSpace::Screen);
SetCollisionEnabled(ECollisionEnabled::NoCollision);

On your widget? If its a billboard style widget that exists in 3d space you need to call those.

Secondly, I personally haven’t tried this type of method to “change” an owning actor, so I’m not sure its the correct way to go about it. What happens when you destroy an actor? Won’t the references get destroyed to this widget? What about the widget itself, won’t the garbage collector attempt to come in and delete the widget entirely. If that happens you code would crash.

So I’m not sure you can even do this and or even if its a good idea. The typical style OOP unreal uses would be you add a widget component to each actor as part of its blueprint class(or c++ class), and then enable and disable them as needed (default state on spawn would be disabled, and your tab key would have to activate an actor iterator to find the one you want or use a collision sphere, or cone, or line trace to get actor reference to cause a collision/hit, then set the widget to visible on that actor)

Yes I am calling those in the constructor! You’re completely right about the second way though, if I do destroy an actor. It would crash. Didnt even think of that lol… I will definitely try to add the widget component to the actor thats closest to me. I feel like thats definitely the smarter way around it. Atm , I have that everyone has the widget component on them and it would activate according to the closest player. But after what you just said, theoretically, it would 100% crash because if im still targeting the compiler wouldnt know what to do !