How would I make a Defense stat?

I noticed that there's a stat system in the UCC, the one that handles the health and stamina iirc, and I wondered if I could make a defense stat with this. I've never been able to do this well, but I've been trying to implement a rather simple one which would reduce incoming damage by the number of the defense the character has. So if an enemy does 50 damage, and the player has 25 defense, the damage the player would take would be 25.

Does anyone have experience with this?
 
You could create a subclass of Health, which would modify the amount of incoming damage before applying it. E.g.:

C#:
using UnityEngine;
using Opsive.UltimateCharacterController.Traits;

public class TestHealth : CharacterHealth
{
    public override void OnDamage(float amount, Vector3 position, Vector3 direction, float forceMagnitude, int frames, float radius, GameObject attacker, object attackerObject, Collider hitCollider) {
        amount -= 5;
        base.OnDamage();
    }
}
 
You could create a subclass of Health, which would modify the amount of incoming damage before applying it. E.g.:

C#:
using UnityEngine;
using Opsive.UltimateCharacterController.Traits;

public class TestHealth : CharacterHealth
{
    public override void OnDamage(float amount, Vector3 position, Vector3 direction, float forceMagnitude, int frames, float radius, GameObject attacker, object attackerObject, Collider hitCollider) {
        amount -= 5;
        base.OnDamage();
    }
}

Sorry, I haven't had to create a subclass of anything yet. Would I then place this script directly on the player, or would I have to assign this another way?

Also, I'm getting this strange error here with the script:

Assets\MyFiles\MyScripts\TestHealth.cs(8,14): error CS7036: There is no argument given that corresponds to the required formal parameter 'amount' of 'CharacterHealth.OnDamage(float, Vector3, Vector3, float, int, float, GameObject, object, Collider)'

If I comment out the "base.OnDamage();" line, the error vanishes.

I can't really compile it to test where I should place it, so I'll await further instruction if you're willing to give it.
 
Last edited:
You'd replace the CharacterHealth component with your new subclass. A subclass in C# is a class that inherits all the properties, methods, etc. of its "parent" class, in this case TestHealth inherits everything from CharacterHealth, then you can "override" specific things, like we're overriding the OnDamage method here. You could read a bit more about subclassing in C# or just play around with it.

The base.OnDamage call would need to also pass in all of the arguments it received (i.e. amount, position, direction, etc.)
 
You'd replace the CharacterHealth component with your new subclass. A subclass in C# is a class that inherits all the properties, methods, etc. of its "parent" class, in this case TestHealth inherits everything from CharacterHealth, then you can "override" specific things, like we're overriding the OnDamage method here. You could read a bit more about subclassing in C# or just play around with it.

The base.OnDamage call would need to also pass in all of the arguments it received (i.e. amount, position, direction, etc.)

Hi, sorry this response is so late. I had some issues I needed to attend to first, but I'm back for a bit more help.

To clarify, the base.OnDamage needs more code related to it in order to function correctly, right? I assume that'd be related to the "float, Vector3, Vector3, float, int, float, GameObject, object, Collider"?

So I need only specify the following "float, Vector3, ect" in the parentheses of the base.OnDamage?

Then I'd just replace the player health with my new version that would allow for a defense stat. I'm asking first before I dive in so that I don't end up ruining my code in some way with nothing to show for it.
 
Yeah you'd just copy all the parameters of the OnDamage call itself, i.e.:

base.OnDamage(float amount, Vector3 position, Vector3 direction, float forceMagnitude, int frames, float radius, GameObject attacker, object attackerObject, Collider hitCollider)

And before calling it you can modify any of those parameters to suit your needs (in this case probably just the 'amount' parameter).
 
Yeah you'd just copy all the parameters of the OnDamage call itself, i.e.:

base.OnDamage(float amount, Vector3 position, Vector3 direction, float forceMagnitude, int frames, float radius, GameObject attacker, object attackerObject, Collider hitCollider)

And before calling it you can modify any of those parameters to suit your needs (in this case probably just the 'amount' parameter).

Thank you very much. While my question is technically solved, I do have one more question. I can't seem to change the player's defense outside of the script, and I'm trying to make a stat script that'll interact with this. I set up an int called "Defense" with the number of defense my player has, but I've failed to make my second script notice the first one.

The second script would have another "defense" int linked to my health's defense stat, so modifying one would change the other. Would you know how to do this?
 
If you've got the "Defense" set up as an attribute in the character's Attribute Manager, then you can just do something like:

C#:
attributeManager = character.GetComponent<AttributeManager>();
defense = attributeManager.GetAttribute("Defense");

// use defense.Value to get the actual value of the attribute, e.g.:
amount -= defense.Value;

If you've literally just got an int on your Health script, then just make sure it's public and reference it directly:

C#:
health = GetComponent<Health>();
health.myDefenseVariable += 5;
amount -= health.myDefenseVariable;
 
If you've got the "Defense" set up as an attribute in the character's Attribute Manager, then you can just do something like:

C#:
attributeManager = character.GetComponent<AttributeManager>();
defense = attributeManager.GetAttribute("Defense");

// use defense.Value to get the actual value of the attribute, e.g.:
amount -= defense.Value;

If you've literally just got an int on your Health script, then just make sure it's public and reference it directly:

C#:
health = GetComponent<Health>();
health.myDefenseVariable += 5;
amount -= health.myDefenseVariable;

Perfect. Thanks for your help!

And sorry about all the hand holding. Sometimes I can't code anything without being explicitly told how.
 
Top