- Home /
Melee damage with OverlapSphere to detect closest enemy in field of view of player
I am trying to make a melee script that does damage to the closest enemy in the player's field of view. I am using an OverlapSphere to detect potential colliders, iterating through an array of them, filtering out any not in the field of view, identifying the closest one, then a raycast to make sure no obstruction. I have been able to do damage so I know it's working somewhat, but for the most part it wont damage even when right in front of the target. It seems I am not getting the right angles for the FOV check as it always registers 90 degrees when my crosshair is centered on the target when I assume should be 0. Am I missing something there or somewhere else or probably multiple places?
public class Sword : WeaponBase
{
public float attackDamage = 40f;
public float fovRange = 2f;
private Collider closestTarget;
private Vector3 dirToTarget;
float distance;
private int layerMask = 1 << 8; //select layer 8
[Range(0, 360)] public float fovAngle = 30.0f;
void Start()
{
attackCoolDown = 0.55f;
hand = "Right";
closestTarget = null;
distance = Mathf.Infinity;
}
public override void Attack()
{
Collider[] hitColliders = Physics.OverlapSphere(transform.position, fovRange, layerMask); //get all the objects that could potentially be in field of view.
for (int i = 0; i < hitColliders.Length; i++) //make a loop to check whats there
{
dirToTarget = hitColliders[i].transform.position - transform.position; // get target direction then check against field of view
float angle = Vector3.Angle(dirToTarget, transform.forward);
Debug.Log("Target Angle = " + angle);
if (angle < fovAngle)
{
float curDistance = dirToTarget.sqrMagnitude;
if (curDistance < distance)
{
closestTarget = hitColliders[i];
distance = curDistance;
Debug.Log("Closest Target = " + closestTarget.gameObject.name);
}
}
else
{
return;
}
}
if (closestTarget != null)
{
// check to make sure nothing is obstructing
RaycastHit hit;
Physics.Raycast(fpsCam.transform.position, dirToTarget, out hit, layerMask);
{
IDamageable damageable = hit.transform.GetComponent<IDamageable>(); // already checked for this above but not sure which one to get rid of yet
if (damageable != null)
{
Debug.Log("You hit " + damageable);
damageable.ApplyDamage(attackDamage);
closestTarget = null;
}
}
}
else
{
return;
}
}
}
Does the angles still change linearly? If not how do they change? What I mean is as you move where the player is looking relative to the target how does the calculated angle change? I am not seeing the problem yet so trying to get more information.
Yeah it seems pretty linear, though to the left would be less than 90 so subtracting 90 would get negative number, which is fine and what I would expect anyway, but figured the wrong angle was indicating my method wasn't right. I just tried subtracting 90 from the angle and it gives the numbers I was expecting, though still not registering hits for damage for some reason. It seems to do damage only if I have 2 or more targets in proximity.
$$anonymous$$ake sure you are resetting the distance variable each time attack is called at the start of the function otherwise it will not select the right one. See of that helps. If you are still having trouble step through the code where you should get a hit and figure out where it is rejecting the hit.
If it changes linearly just subtract 90 and be done with it lol. Even flip the signs or what ever you need to do to make it align with the expected values.
Answer by unity_ek98vnTRplGj8Q · Mar 09, 2020 at 03:45 PM
I see two potential issues here: I see that this logic is inside your sword class. Does this mean that it is attached to a sword object, not the player object? It seems like if you are checking FOV you want to check fov from player position and rotation, not sword position and rotation. Also make sure that the angle between the target and the player is correct vertically, for example if the player origin is at the player's head and the target origin is at its feet the even when looking right at the target Vector3.Angle() will return the vertical angle, making it seem like the object is closer to the edge of FOV than it is
Yes, it's a sword that can be picked up and dropped. I am surprised I didn't think about that but makes sense. It also explains why there were times it was doing damage to the player. Do you have a suggestion for finding the right angle? Checking against transform.up or something?
In the sword class I would just hold a reference to the player transform and check from there. As far as getting the right angle it really depends on exactly how your game is set up and what you want the behavior to be. For example, the quick and easy way would just be to set the y component of the direction between the target and the player to zero so that you are only checking the horizontal angle, as well as set the y component of the player's transform.forward to zero (this way you only compare angles on the XZ plane). However this will cause enemies to still be hit if you are looking way up or way down, (if you are using a first-person setup for example) which may or may not be something you want. It could also cause a few other bugs, but if you are doing a 3rd person game this could work quite well.
The code you have should work alright though as long as you just use the player transform. I only mentioned this because I could forsee an issue where you were getting the direction from player's eye level to enemy's feet which could cause some issues. Just make sure you think about how you want FOV to work when, for example, the enemy is above the player or the player is looking up or down.
Yeah I this is for 1st person so I'll have to see if this is the best option for what I'm going for. Either way, I'm learning a lot so thanks a lot for the tips! I'll play around with it all and see if I can get it all working.
Your answer
Follow this Question
Related Questions
Multi Coloured Buttons 0 Answers
having problems with my raycast shooting script 0 Answers
Fall Damage Script Problem? 1 Answer
Getting UV coordinate with GraphicRaycaster 2 Answers
What is the Best way to use Raycast for enemy Fire? 2 Answers