Best way to add damage/healthbar to mortars

Just realised after watching the finishing up part 2 video that I misunderstood the point of making the mortars damageable - I was thinking we need to add the same health tracking and health bar UI to the mortars as for the tanks!

It strikes me that there are several possible solutions to doing this and I’d appreciate feedback on how to best do it using UE4’s mechanisms.

  • Recreate the Mortars as C++ classes, inherit from them in the Mortar BP, make a separate copy of the healthbar UI that expects a Mortar C++ class as the entity to pull the health from etc. The core problem is that the HealthBar UI expects an ATank (which implements the contract of GetHealth) and so it’s fiddly to make this accept the Mortar as well.
  • Create some kind of parent C++ class (e.g. ADamageableActor) that both the Mortar and Tanks inherit from, that implements the GetHealth contract, and have the HeathBar widget expect to use one of those. More along the lines of traditional C++ OOP design but I don’t like excessive hierarchies most of the time.
  • Make some kind of UActorComponent that implements the health checking contract, put all of the health counters and GetHealth public function in there, then drop it onto both the Mortar and Tank objects. The problem now is that potentially you set the starting health on the tank and mortar, but that needs to be pulled into the health component at initialization. The HealthBar UI now needs to get a reference to the Health component, and we the wiring up of all the objects is a bit more fiddly.
  • Just put all of the health counters into the Health UI widget, and have the Tank or Mortar update the UI counters directly whenever they take damage. They also need to check the counters in the widget to understand whether it is time to die or not.

I’ve been leaning towards the UActorComponent solution as it seems cleanest, although more fiddly. I’ve also started simple by creating the component as a blueprint, but now I’m puzzled as to how you can get a reference to it in the tank’s C++ class (i.e. to decrement the health counter on damage) - is that even possible? Or must you always use a C++ class in order to be able to access it directly?

It has been a bit of time since I touched this course so I’ve probably forgotten some basics - any ideas appreciated!

There’s another possibility I just realised - make an abstract class that defines the interface of the health system and inherit from that also in each of the damageable entities (using multiple inheritance). This strikes me as possibly the cleanest option but maybe with its own complexities… not sure now!

I would go for an ABC that Tank and Mortar inherit from personally.

Doing that in Unreal would be something like

UCLASS(Abstract)
class AProjectilePawnBase : public APawn
{
    float GetHealth() const PURE_VIRTUAL(AProjectilePawnBase::GetHealth, return 0.f;)
};

All UObjects need to be instantiable so the PURE_VIRTUAL macro is just

{ 
   LowLevelFatalError(TEXT("Pure virtual not implemented (%s)"), TEXT(#func)); 
   extra 
}

So the above would expand to be

float GetHealth() const 
{
    LowLevelFatalError(TEXT("Pure virtual not implemented (%s)"), TEXT("AProjectilePawnBase::GetHealth")); 
    return 0.f;
)
1 Like

Thanks DanM! In the meantime I googled a bit and many pages mentioned that multiple inheritance might not work on UE4 so that seems like a non-starter (at least where UClasses are involved). I created a UActorComponent which seems to work although feels fiddly as I mentioned - seems like it needs to be a C++ class in order to be accessible everywhere, but fortunately that means it works in the C++ Tank and the BP Mortar!

I like that your solution is quite minimal. I’ll give that a try as well :slight_smile:

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

Privacy & Terms