Thursday, May 24, 2018

c# - How would I check the range against the entirety of an enemy object, and not just it's transform.position?


I want to be able to do range checks against the entirety of an enemy object, and not just it's transform.position. The enemy object can have it's side or nose within range, but range detection will not determine if it's close enough to be targeted unless it's transform.position is within range.


enter image description here


Right now I run a quick check against all nearby units to determine their distance from a turret on the friendly unit.


I was thinking raycasts, but I imagine raycasts every frame for up to 10 detected enemies per unit (Each unit will at max hold onto references of 10 nearby enemies. I could have 100 friendly units within range of 100 enemies) would chew up a fair bit more CPU than just checking their cached transforms.


Suggestions, ideas, or comments?


Edit: More Detail


Currently a Unit has a trigger spherical collider that defines it's view range. Any enemy unit within this view range is added to a collection based on priority, with a maximum of 10 objects referenced per collection (each Unit can only be aware of 10 enemy objects). From there, each turret on ship checks the distance from itself to each of the enemies within that collection. When the distance is <= it's attack range, it will fire upon whichever enemy object gets within it's attack range first.


I used to use spherical colliders for each turret, which of course would detect the enemy as soon as any part of the enemy entered the trigger collider. The issue was the massive performance loss due to OnTriggerStay() begin called by hundreds of units, tens of thousands of times per frame when I have no need for the method. So I discarded the extra trigger colliders for a more performance friendly approach.


The issue is that the range check is that is checks the transform.position of the enemy. This does not take into account the collider that makes up the enemies shape, and will only trigger when the center of the object enters within range.




Answer



Two dot products, using the vector between their centers, tells you which corner is closest.
A positive "Forward" dot indicates a front corner; negative is rear.
A positive "Right" dot indicates a right corner; negative is left.
If the distance between the selected corner and the friendly is less than Range, it is in-range.


Nearest-corner test:


enter image description here


This will detect collisions that aren't caught by the nearest-corner-test:
(Diagramming purple was a mistake since it would have already passed the nearest-corner-test. The calculation will work for all cases, including perpendicular, as shown in white.
For the perpendicular, (Width / 1.0) * 1.0 == Width.)



Re-use the dots from the nearest-corner-test to find the nearest "cardinal" enemy direction (the larger of the two). Calculate the hypotenuse length and, if (DistanceBetweenCenters - HYP) <= Radius, the enemy is within range.


enter image description here


Edited to include theory and attempted to make better use of color:


enter image description here


No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...