Receiving Damage in a FPS RPG

Hey there friends!

I’m currently working on a FPS RPG as you can gather from the title. I’ve got a few different enemy types and I’m trying to figure out how I will assign their damage to the player. So far I’ve been using colliders and an OnTriggerEnter function on a script called Player Vitals which manages health and mana and such. When an enemy hits the players hitbox with one of their weapons, the Player Vitals script uses a TakeDamage function and currently uses a couple int values in the same script to calculate the damage.

So this is my issue. Now that I’ve established this collision system for damage, how do I make the damage incoming from each enemy unique? Say I have an enemy at level 1, and an enemy at level 2. They both hit you, but my script can only register the tag of the object that it is hit with. How can I efficiently figure out which enemy hit the player, from the Player Vitals script? Do I need to separate my scripts more? The only thing I could think of is to come up with multiple tags, and assign enemy colliders according to say 5 different intensities of damage. Such as Super Weak, Weak, Average, Strong, Super Strong. Then I would vary the tags on each weapon as each scene dictates.

This approach feels artificial and I feel like there must be a much better established way for calculating the damage. Being an FPS makes this seem more difficult than maybe it really is. Your guidances are much appreciated.

It’s the RPG part that’s making it difficult. Pointing a gun in a direction and shooting a projectile is really simple compared to tracking and modifying stats on many different pieces of equipment.

You should pass a struct in TakeDamage with more information than just an int.

void OnTriggerEnter(Collider c)
{
    var otherPlayerVitals = c.GetComponent<PlayerVitals>();
    if (otherPlayerVitals != null)
    {
        // attacker should be a reference to the attacker and their stats
        // or a struct with all information you need to determine damage.
        otherPlayerVitals.TakeDamage(attacker);
    }
}

When I’m calculating damage, I usually ask the attacking player to give me their “attack power” which they will calculate by going through all their stats and gear. The defender will compare to their own “defense power” to determine the final damage amount. I usually have a separate class that gathers stats and gear info then calculates these numbers

As you can see, every stat that you add will have to propagate through all these calculations. Each stat you add increases the complexity of calculations exponentially, so try not to go overboard with a bunch of stats right away!

1 Like

Aha, thank you for the timely response!

This seems to be exactly what I’m going for. I hear that GetComponent is taxing though? Do you think I can get away with this if we’re maybe only registering a few incoming attacks at a time?

GetComponent() isn’t that slow. It is slower than caching a reference and reusing it which is why people say to avoid it in Update() loops.

As long as you aren’t using it in big for-loops, or calling it every frame, or have many many collisions going on at a time… GetComponent() is a good way to check for the existence of a script on another GameObject.

If you do have a ton of collisions, you can use layers to filter out many of the collisions before even using GetComponent().

1 Like

Use an Interface. Check out my tutorials for an example of how i made a damage syste,

IDamagable

2 Likes

I would run with an interface and ExecuteEvents.

Good to know about the performance issues, or rather lack there of. My game is kinda hack and slashy and for the most part I think 5 enemies versus the player should be more than enough. So maybe like, 7 or 8 collisions a second, at max. That doesn’t sound like it should be a problem.

Thanks for the advice on interfaces as well. I’m pretty new to development. I’m computer smart, but I’ve never programmed before messing around with Unity and C# just about a year ago. I’ve got a lot to learn, and interfaces is definitely one of them. It makes my brain sad thinking about how I don’t know how to use libraries, or interfaces. I literally don’t even know what you would use a for-loop for lol.