Contact point in chest and not belt

Just wanting to throw this out but if you want the arrow to hit a little bit higher, like say right in the middle of the sternum, lower the 2 in the formula. Should look like this:

return target.position + Vector3.up * targetCapsule.height / 1.5f;

Remember to use f after the number on the end so that way you don’t get yelled at by Visual Studio.

2 Likes

Here’s another idea. I didn’t like the idea of the projectile needing to know anything about the target much less that it may have a Capsule collider. Also what if the capsule is on its side? I instead created a method on Health to return its centermass.

If you wanted to be super efficient you could probably create a single method that returns centermass if object has a collider or transform.position if it’s not.

Edit: I revised to put the TryGetCenterMass method on Health script since we use seem to Health for this type of purpose.

public class Projectile : MonoBehaviour
{
    private Vector3 GetAimLocation()
    { // remember target is a local var of type Health
        if (target.TryGetCenterMassLocation(out Vector3 centerMass))
        {
            return centerMass;
        }
        else
        {
            return target.transform.position;
        }
    }
}
public class Health : MonoBehaviour
    {
        public bool TryGetCenterMassLocation(out Vector3 centerMassLocation)
        {
            if (TryGetComponent<Collider>(out Collider collider))
            {
                centerMassLocation = collider.bounds.center;
                return true;
            }
            else
            {
                centerMassLocation = new Vector3(0,0,0);
                return false;
            }
        }
    }

Ok. My code above and also the code in the course may have a weird issue where the Aim Location gets set to the ground below the target if the projectile is fired on an Enemy that just died and you have been disabling colliders on dead enemies. You can get these weird effects after the “Improve Projectile Behavior” lessons where the most recently fired projectile goes for the target whereas the prior projectile sails past.

Here’s an alternative that seems to work.

public class Health : MonoBehaviour, ISaveable
{
        private Vector3 localCenterMassLocation;

        private void Awake()
        {
            if (TryGetComponent<Collider>(out Collider collider))
            {
                localCenterMassLocation = transform.InverseTransformPoint(collider.bounds.center);
            }
            else
            {
                localCenterMassLocation = new Vector3(0, 0, 0);
            }
        }

        public Vector3 GetCenterMassLocation()
        {
            return transform.TransformPoint(localCenterMassLocation);
        }
}

public class Projectile : MonoBehaviour
{
    private Vector3 GetAimLocation()
    {
        return target.GetCenterMassLocation();
    }
}

While this will work, you’ve simply changed Projectile’s responsibility to calculate where it’s trying to hit and move that responsibility into Health. It’s not really Health’s job to say “hit me here”. :slight_smile:

What I do is when the projectile is homing, I check to see if the target is dead (yep, that’s still Health, we’re checking, but Health should be telling us if the character is alive or dead, and Projectile can determine if the character is dead, then just keep moving along transform.forward instead of calculating a new vector.

1 Like

Yeah I agree in that there’s too much going on in Health. The thing I want to refactor out of Health is where is the center of mass - I also didn’t think that belonged in Projectile. My plan is to refactor after the Core Combat Course after I see where we landed.

I really like your idea of having the Projectile script change its behavior based on whether the target is dead or not.

Privacy & Terms