Download

Questions on Designing Damage/Interact systems

Assuming I dont use interfaces

So lets say i have a line trace where i can shoot a weapon from. So there are now barrels and humans and other destructible items in my game world. How should I approach casting that? So for humanoid i wanna cast to enemy NPC and for destructibles I want to cast to destructibles. Should I make a parent class for both and have the parent have receive damage event, but the thing is those 2 are two entirely different things. My current solution is using a sequence with different cast to but I am wondering if thats a recommended approach. So i am casting to enemy npc then the other sequence is casting to destructible and the other sequence pin is casting to another object etc.

  1. I am also wondering what would be the cleanest way to handle line traces with different set ups. So for instance i want to be able to holster the weapon and use the line trace to talk or interact rather than damaging objects. Should I use a switch enum for that? Also use an enum for the weapon type? (Different weapons have different ranges etc). If someone knows a tutorial or has tips how to handle this without having to cast to each and every class, it would be awesome.

I’m only answering your first question:

This is where the beauty of Object Oriented Programming (OOP) comes in. What you should do is have all of the objects that can interact with being shot be subclasses of a parent. No I know you’re thinking “Well, the implementation of my Barrel getting shot and my Enemy getting shot are entirely different.” That’s where overriding functions comes in. You see, you could have the “OnGetShot” function in your parent class, and then have different code run on the subclasses, but under the same function. So you could do your shooting line trace, get the actor, cast it to the parent, and just call “OnGetShot”, and the function on the specific subclass will be run.

Inheritance, function overriding, and polymorphism are part of what makes C++ so popular, and, fortunately, Blueprints have a lot of that implemented as well.

Here’s how you override the function:

  1. Make the parent class
  2. Create a new function “OnGetShot”
  3. Wire it to a return node (Important)
  4. Make the subclass
  5. Under the “Functions” section in the “My Blueprint” tab, click “Override”, and from there, select “OnGetShot”
  6. The new overriden function is now made. The “Parent: OnGetShot” node calls the parent class’s nodes for that function. You can now build in the subclass, and when the OnGetShot function gets called even when cast only to the parent class, the subclass’s implementation will be called

Hope this helps!

Ah so i should just create a base class like „destroyable/interactable object“ and then abstract or branch out 2 classes: 1 enemie subclass and one prop subclass.

Yes, do that

Thanks for taking your time to help Nacho!!! :heart:

The problem is that you can’t do that in blueprints because humans inherit character and barrels from actors.
Everything that explains NachoMonkey2 already exists outofthebox, and it is the damage events.

Apply damage without casting to the hit actor and use anydamage, Point Damage or Radial Damage events to put the different logic on each object

1 Like

Perhaps then just use a sequence with multiple cast to nodes?

Ah, true, I wasn’t thinking of using the Character class. Interfaces would work, but as you said from the start, you don’t want to use them.

But, if you’re only talking about Damage, then just use the built-in damage system, like DomusLudus said. You won’t need to do any casting. On the actor that causes the damage, use the Apply Damge nodes. (If you want to damage a specific actor, use “Apply Damage”, and if you want to damage more than one actir, like if you’re blowing up a grenade, use Apply Radial Damage)

There are functions designed to be overriden that are called when your hurt actor takes damage, so override those on your Enemy and Barrel actor classes.

Yea thats the thing I am trying to wrap my head around. For instance lets pretend i wanna use left click to damage some objects and with others i want to interact, like basic light switches or initiate dialgoue. I think interfaces would be best but i am wondering how one would neatly do it with casting alone. Have a sequence node with bunch of casting? Like cast to „enemy“, cast to „objectprop“, cast to „npc“ to talk etc. Now all three could have different parents and are different classes entirely. Just looking for a way to efficiently do it; or want to know how i would deal with it if i only had to cast.

Note: I am asking purely for educational reasons as I am trying to understand and leverage my knowledge on every communication method.

Without going into UE4 api; in c++ would you handle it by checking if(actor == hitactor) and then go from there? So bunch of if statements that deal with every hittable object. Am I right to assume casting is a bp thing?

The thinking with Interfaces is it isn’t the parent of your Blueprint, but your Blueprint gets all of the functions from it. With an Interface, you define one, list its supported functions in it, and then you define the implementation of the function in the Blueprint in which it is implemented.

Read about interfaces here:


“Casting” is part of core C++, not just Unreal Engine. (However, UE has a different way to go about it). To check if an Actor is of type Barrel, you could try if (IsValid(Cast<ABarrel>(HitActor)). Just remember, the whole point of using Interfaces is so that you don’t have to do tons of Casts, you just try to call the function if the interface is implemented in the Actor’s class, no matter what class of Actor it is.

Yea I get interfaces. Like mentioned, I am just curious how one would approach a system similar to interfaces if only casting was at disposal.

You can’t use casting in this case, because in Unreal Engine, each object can have only one Parent. Your Enemy is a Character and your Barrel is an Actor. You can’t just reparent the Character class without modifying the engine. If you were using all plain Actors or all Characters, it would be possible, but, in this case, interfaces are the way to go.

1 Like

You can also use an actor component and manage all damage-related logic in there. Make an actor component called “DamageComponent” and add the necessary variables and event dispatchers to it. In any actor blueprint, you would then add that component; it’ll look like this:
image
To apply damage, you would get the damage component using the GetComponentByClass (the one that returns a single component). Then you would call an “ApplyDamage” function in the DamageComponent to apply the damage, which will subtract from the component’s health and call OnTakeDamage, or if the health is depleted, OnHealthDepleted.

The advantage with this over interfaces is that the component handles all the logic itself, including ticking. This allows for more things to be possible. For instance, say you wanted every actor to play a sound and shake whenever it takes damage. With interfaces, you would have to set this up on each actor that implements it. But with a component, you can do it from the component, and it will be applied to every actor that uses it automatically. The OnTakeDamage event would then be used for actor-specific things.

1 Like