How to use Cast

I would like to know more about the Cast operator

I have used it once in the working code bellow:
inside a Onhit function

if (AEnemy* Enemy = Cast<AEnemy>(OtherActor))
	{
//some function
}

I understand everything except for the last part in ( ) in this case were the " (OtherActor) "
is located, what do i have to put into that lets say i want to adjust a variable of any time put.

So if i understand it correclty a Cast converts one class to another so we can use it with the last part being the expression to what we want it to convert to right??

But lets say i want communicate from AActor class to a UWidget class or to a APawn class, would that be possible or is it only allowed to cast from the same Class type?

if so? what way would be the best to change a variable like for example a Boolean or a float or adjust anything from another type class?

Yes.

Thing to convert

image

thing to convert to

image

Problem. You can only cast down the inheritance hierarchy. So, if you have an enemy that is a child of pawn, you can cast from a pawn to your enemy. But you can’t cast between different blueprint types, widget and pawn and not related.

When you want to talk to class A from class B, you need a reference to B inside A. How exactly you get that is up to you, there are many ways.

In your example of talking to a widget from an enemy, you need a reference to the widget in the enemy. That’s all.

Don’t get all hung up on casting. A lot of people think you can communicate unless you cast, which it total rubbish. It’s just that sometimes you have to cast, to unwrap the object you want to talk to.

A good example is using GetPlayerCharacter. It returns a totally generic reference. Yes, it is a pointer to your player, but it isn’t yet an enemy ( for instance ). So, you have to cast, to find the enemy hidden in the player character.

So to summarize, you can talk to just about any class to any other class, and casting has nothing to do with it. References ( or pointers ) are what you need.

3 Likes

Thank you very much for clarifying this subject.

So in my situation as i mentiont I have a Enemy(AActor) and a HealthBar(Uwidget) that is attachet to it.
I want the Enemy to adjust the HealtBar(UWidget) bar percentige once i have hit it, Everything is working except for the percentige part.

I know i can use the binding option in the blueprint, that would set the percentige every thick but that is not what i want, i want to learn on how to commicate between different classes in C++

This is what i have tried so far:

HealtBar.h (attached to AEnemy)

UCLASS(ABSTRACT)
class CASTLEDEFENCE_API UHealthBar : public UUserWidget
{
	GENERATED_BODY()
public:
	//void SetOwnerEnemy(AEnemy* InEnemy) { OwnerEnemy = InEnemy; };

	void setHealth(float Val) { HealthBar->SetPercent(Val); };

protected:

	UPROPERTY(meta = (BindWidget))
	 UProgressBar* HealthBar;

Enemy.h (Parent of Healtbar)

	UPROPERTY(EditAnywhere, Category = "Moving Object")
		class UHealthBar* healthbar;

// created a second pointer for testing

	UPROPERTY(EditAnywhere, Category = "Moving Object")  
		class UWidgetComponent* HealthWidgetComp;

There is also a Projectile that activates the Sethealth function above
and it works fine, but just to show the rest of the code that might help to understand on what im trying to do :

Projectile.cpp (OnHit function)

	if (AEnemy* Enemy = Cast<AEnemy>(OtherActor))
	{
		Enemy->SetHealth(Enemy->GetHealth() - 25);

		if (Enemy->GetHealth() <= 0) {
			OtherActor->Destroy();
		}
	}

Enemy.cpp

void AEnemy::SetHealth(float val)
{
	Health = val;

// I tested out all 4 techniques  separately, 2 of them crashed unreal engine

	healthbar->setHealth(Health / MaxHealth);  // made unreal engine crash


	if (UHealthBar* healtbarr = Cast<UHealthBar>(this))
	{
		healtbarr->setHealth(val / 100);
		GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Yellow, FString::Printf(TEXT("Cast worked")));
	}

	if (HealthWidgetComp)
	{
		healthbar->setHealth(val / 100);      // made unreal engine crash
		GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Yellow, FString::Printf(TEXT("Pointer worked")));
	}

	if (healthbar)
	{
		healthbar->setHealth(val / 100);
		GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Yellow, FString::Printf(TEXT("Pointer worked")));
	}
}

Please help me out, it would be very usefull to see multiple ways on how to achive this.
so in the future when i want to communicate between other classes. because I have searched on Google and on Unreal engine document for hours and i could not get a good solution for this problem and that explains this problem well.

If you don’t want to use a bind ( which I think probably doesn’t really matter, unless you have a lot of them ), you can use events.

I can’t actually give you a C++ example, because I don’t use it! :slight_smile: ( but I know how casting and events work ).

The most efficient and object independent way of doing it is with interfaces ( same in blueprint ).

It’s a bit like calling an event, but interfaces don’t make any assumptions about the relationship between objects.

So your enemy can trigger an event in the widget using an interface, it can tell the widget the new percentage value, for instance. In BP, that’s

image

Very similar in C++ I assume.

The crucial thing to know, is that the reference should be as generic as you can make it, the more generic the better. This is because we are trying to escape tight coupling in the code.

2 Likes

Hello! I tried yo understand what you were doing, but I didn’t get the whole picture

if (UHealthBar* healtbarr = Cast<UHealthBar>(this))

UHealthBar is subtype of UUserWidget and you cast to AEnemy (“this” part) . it shouldn’t work, because the are different types.

if (HealthWidgetComp)

crushes the engine, because you checking for nullptr of HealthWidgetComp but using healthbar in it. So my assumption is that your healthbar is nullptr(but I cannot say for sure, because of the lack of context), and it’s the reason why it cruses. If I were you I would put a break point and check it

Thank you very much for the link this is exactly what i was looking for.
I will study this when I get home :+1:

Absolutely :slight_smile:

Once you get the hang of it, it’s pretty cool. You can talk to your game instance or save game, without casting, for example.

1 Like

I have studied the Interfaces it looked very promising but i ran into several problems
After creating the interface:

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "UObject/Interface.h"
#include "HealthBarInterface.generated.h"

// This class does not need to be modified.
UINTERFACE(MinimalAPI)
class UHealthBarInterface : public UInterface
{
	GENERATED_BODY()
};

/**
 * 
 */
class CASTLEDEFENCE_API IHealthBarInterface
{
	GENERATED_BODY()

		// Add interface functions to this class. This is the class that will be inherited to implement this interface.
public:

	UFUNCTION()
		virtual void InteractPure();
};

I implemented the Interface in my Enemy.h for testing

#include "CoreMinimal.h"

#include "GameFramework/Actor.h"
#include "Components/WidgetComponent.h"
#include "Interfaces/HealthBarInterface.h"
#include "HealthBar.h"
#include "Enemy.generated.h"

UCLASS(ABSTRACT)
class CASTLEDEFENCE_API AEnemy : public AActor, public IHealthBarInterface
{
	GENERATED_BODY()
	
public:	
	// Sets default values for this actor's properties
	AEnemy();

	virtual void InteractPure() override;

so then i could call that function with the Onhit function from the Projectille.h
but before i could even start at that. when i ran the code above i get several errors that i dont know how to solve.

I dont know what i should do.
Also, isnt there a more easier way to communicate from spawning Actor to a child widget class in C++

this is what the game lookes like as you can see in the blueprint map bellow the screen.
the Bp_Enemy spawns every 1 to 2 seconds and they move forward in a random direction and the WBP_HealthBar is the healtbar UWidget that is attached to the Bp Enemy

The LNK (Linker) errors you are getting is because it can’t locate the body (Implementation) of the function InteractPure only the declaration.

virtual void InteractPure();

Should look like this with an empty implementation.

virtual void InteractPure() {}

Take a look at what @GarnerP57 says about the errors.

Yes, there is a much easier way, direct communication. That’s the default method. You already have the widget in the enemy, you can just reach in and set the percentage. But you wanted a modular event driven method, this is it. :slight_smile:

Thank you very much the interface worked,
But i dont think it can be used in a way that i wanted.

My goal is to send a float from the Enemy(AActor) to the attached Healtbar(UUserWidget)
I need the float variable to set the Healthbar percentage, I see that the Interface is more usefull for activating things rather than sending data like a variable that can be used to adjust another class.

However its a very useful technique that I will problably need in the future
But in this case I think it comes down to Casting.

from the Enemy.cpp
this function bellow wil be activated once the projectile puts damage on the Enemy
so i think this is the best place to set the healtbar percentige

void AEnemy::SetHealth(float val)
{
	Health = val;

	UHealthBar* setHealthbar = Cast<UHealthBar>(); //<- the last part in the "( )" is where i need help 

		if (setHealthbar) {
			setHealthbar->setHealth(val);
		}
}

healthbar.h would look like this:


	void setHealth(float Val) { HealthBar->SetPercent(Val); };

You can send and receive parameters with the interface…

1 Like

I see but even with parameters i need to fill in the Cast

void AEnemy::SetHealth(float val)
{
	Health = val;

	IHealthBarInterface* Interface = Cast<IHealthBarInterface>(); // <- here is where i need help 

	if (Interface)
	{
		Interface->InteractPure(val);
	}

I would like to get help on the last part on of the Cast the " ( ) " section
I know that is that part that needs to be converted, but what exaclty do i type in there in this situation.

I hope someone with allot of C++ knowledge and knows how to handle Casting can help me with this

You either cast and call the event directly, or you use the interface, not both.

@GarnerP57 Can you say something? I’m not a C buff…

Is no one able to help me Casting with a UUserWidget?

The first post in this shows the two main ways of casting.

Sir I am not asking how casting works or what the meaning of the expression are I understand that by now, I am literly asking:
what exact code do i need to use in order to affect the Widget healtbar that is attached to an AActor
I have still not got an answer too that question

You don’t need to cast, that’s what I’ve been trying to say this whole time. You make the widget. When you make the widget, you get a reference ( pointer ). You use that pointer to ‘talk’ to the widget from within the actor.

If you get stuck repost with the heading ‘C++ actor widget’, or something like that.

I am not sure this is exactly what @ClockworkOcean is suggesting, but possibly.

You create a C++ Class, say MyHealthBar that derives from UUserWidget. From that, you create a widget that has it as it’s class, it might be called UMG_MyHealthBar.

In your actor class, you start that MyHealthBar/UMG_MyHealthBar class with CreateWidget and Add to Viewport. This gives you a pointer to that class which you save in private space of the actor/controller.

Then MyHeathBar/UMG_MyHeathBar can access any variables the Actor Class can poke in via the pointer to the MyHealthBar class that was returned when you created the widget. In that MyHeathBar, for example, you might have a UPROPERTY that is a float CurrentHealth. The actor can update that, and the widget either has a Bind to grab the value or a function to do something more complex with it.

This also allows two way communication so the widget can have functions the Actor Class might execute, like an implementable event. The MyHealthBar class can also have UFUNCTIONs that can be implemented within the MyHealthBar Class, say SetHealth(float NewHealth). These can be called from the Actor Class. You can even put some C++ code in the MyHealthBar widget to be a go between for tricky things you would like the UMG widget to do.

No casting should be necessary if you start it with the subclass and save the pointer in an appropriate variable (appropriate being not UUserWidget but the derived UMyHeathBar C++ class).

In the actor class (actually the player controller or at least by referencing the playercontroller, I do all of this in the playercontroller or AIController if I have a HUD on them for player to see) you might reference it by:

.h
UPROPERTY(EditAnywhere,BlueprintReadWrite,Category=“Heath HUD”)
TSubclassOf wHealthBar;
UPROPERTY(BlueprintReadWrite,Category=“Health HUD”)
UMyHealthBar* RuntimeHealthBar;

.cpp (say in beginplay)
if(wHealthBar) { RuntimeHealthBar=CreateWidget(this,wHealthBar); }
if(RuntimeHealthBar) { RuntimeHealthBar->AddToViewport(); }

Now you have a pointer to your derived HealthBar.

In the C++ widget class (the UMyHealthBar)you’ve created…

.h
…
class _API UMyHealthBar : public UUserWidget
…
public:
UPROPERTY(BlueprintReadWrite,Category=“Health Bar”)
float MyHealthAmount=0.f;

.cpp
nothing if you don’t have something you want to do with it.

At this point, you will have reparented your UMG widget to the UMyHealthBar class and in the Actors playercontrollers property view, you’ll have set the wHealthBar to your UMG Widget.

Now the actor class can put a value into the UMyHealthbar class like:

RuntimeHealthBar->MyHealthAmount=TheHealthIJustFiguredOutInTakeDamage;

The widget can find this variable value in the bind of say a text widget, or actually do a Get on it and do things with it, like a calculating a percentage or something.

I’m not sure the above is correct, just typed it from another screen with my code, but it’s the idea.