Weapon damage based on raycast distance

matheussartori

New member
Hello! Is there a built-in option for weapon damage based on distance?

I know there's a distance for the raycast to hit, but i want to do less damage based on how far is the enemy.

If there's not a built-in option, what way should i follow to do this?
 
I'd recommend making a custom Health component and overriding the OnDamage method. Then you can check the distance between the hit object and the attacker (e.g. using Vector3.Distance(m_GameObject.transform.position, attacker.transform.position), then multiply the damage amount by that much. Something like:

C#:
public class MyHealth : Health
{
    public override void OnDamage(float amount, Vector3 position, Vector3 direction, float forceMagnitude, int frames, float radius, GameObject attacker, object attackerObject, Collider hitCollider) {
        amount *= 1 / Vector3.Distance(m_GameObject.transform.position, attacker.transform.position);
        OnDamage(amount, position, direction, forceMagnitude, frames, radius, attacker, attackerObject, hitCollider);
    }
}
 
I'd recommend making a custom Health component and overriding the OnDamage method. Then you can check the distance between the hit object and the attacker (e.g. using Vector3.Distance(m_GameObject.transform.position, attacker.transform.position), then multiply the damage amount by that much. Something like:

C#:
public class MyHealth : Health
{
    public override void OnDamage(float amount, Vector3 position, Vector3 direction, float forceMagnitude, int frames, float radius, GameObject attacker, object attackerObject, Collider hitCollider) {
        amount *= 1 / Vector3.Distance(m_GameObject.transform.position, attacker.transform.position);
        OnDamage(amount, position, direction, forceMagnitude, frames, radius, attacker, attackerObject, hitCollider);
    }
}
Thank you so much! That's exactly what i wanted.
 
Last edited:
I'd recommend making a custom Health component and overriding the OnDamage method. Then you can check the distance between the hit object and the attacker (e.g. using Vector3.Distance(m_GameObject.transform.position, attacker.transform.position), then multiply the damage amount by that much. Something like:

C#:
public class MyHealth : Health
{
    public override void OnDamage(float amount, Vector3 position, Vector3 direction, float forceMagnitude, int frames, float radius, GameObject attacker, object attackerObject, Collider hitCollider) {
        amount *= 1 / Vector3.Distance(m_GameObject.transform.position, attacker.transform.position);
        OnDamage(amount, position, direction, forceMagnitude, frames, radius, attacker, attackerObject, hitCollider);
    }
}
Is there a way to know what weapon was fired?

Because i want the sniper rifles to have almost 0 damage reduction on distance, meanwhile assault rifles have more.

I gave a good look on the CharacterHealth class, and i didn't found nothing.
 
You can check the attackerObject, you should be able to do something like:

C#:
var attackerObjectName = attackerObject.ToString(); // this should give you the full name of the attacking object component, e.g. "Sword"
if (attackerObjectName.Contains("SniperRifle")) {
    // ...
}
 
You can check the attackerObject, you should be able to do something like:

C#:
var attackerObjectName = attackerObject.ToString(); // this should give you the full name of the attacking object component, e.g. "Sword"
if (attackerObjectName.Contains("SniperRifle")) {
    // ...
}

Thanks again for the reply.

I tried to see the content of attackerObject, but i'm getting a Null on Debug.Log(attackerObject), and an error if i try to stringify this parameter.

Maybe is because the player don't spawn with the weapon? Because i'm working with a item spawner that i made, to spawn weapons (Runtime Pickup) on the ground.

I'm getting a warning when i destroy the weapon runtime pickup also, but i don't think this interfere.

1632406525471.png
 
Hm I believe attackerObject should be whatever object actually collided with the Health component. You might instead need to use hitCollider, e.g. checking the hitCollider.gameObject.name (i.e. if the attack was with a sword, then the sword's collider should be the one that registers). Failing that, you may even need to check the attacker's currently equipped item.
 
Hm I believe attackerObject should be whatever object actually collided with the Health component. You might instead need to use hitCollider, e.g. checking the hitCollider.gameObject.name (i.e. if the attack was with a sword, then the sword's collider should be the one that registers). Failing that, you may even need to check the attacker's currently equipped item.

The hit collider was returning the affected player, but, with the attackers currently equiped weapon, i made it work.

Thank you so much, now i finally finished this module!

C#:
public override void OnDamage(float amount, Vector3 position, Vector3 direction, float forceMagnitude, int frames, float radius,
        GameObject attacker, object attackerObject, Collider hitCollider)
    {
        var distance = Vector3.Distance(m_GameObject.transform.position, attacker.transform.position);
        var inventory = attacker.GetComponent<Inventory>();
        var weaponName = inventory.GetActiveItem(0).ToString();

        var parsedDamage = HandleDamageByWeaponAndDistance(weaponName, distance, amount);
        
        base.OnDamage(parsedDamage, position, direction, forceMagnitude, frames, radius, attacker, attackerObject, hitCollider);
    }
 
Top