Best Way to Find nearby colliders when you already have a trigger collider on gameObject

I’m working on a 2D game.
Each character has:

  • A small Collider2D attached to
    himself centered on himself.
  • A rectangular Trigger Collider2D
    offset toward the front to check
    for enemies in melee range.

Goal: come up with a way to determine which other characters are nearby. This needs to occur frequently, possibly in Update(). It would be preferable to get all the information at once rather than as separate events/messages.

I have thought of several possibilities, but I don’ t know which is best in terms of performance and cleanness of code. The 5 possibilities I have considered are:

  1. Create a new game object child and put a trigger collider on that.
  2. Use a circle cast.
  3. Remove the “in Range” trigger collider and make do with a single big circle collider on the gameObject
  4. Use Collider.Cast with ignoreSiblingColliders
  5. Remove all trigger events and use a single trigger collider that gets the information from Collider.Cast

I’m listing them here with my initial thoughts and hope people can give some opinions on what is best or give a different tack.

1. Create a new gameobject child to this game object and put a Trigger Collider2D on that game object to find all nearby characters via onTriggerStay().

Downside: Every update you will find the colliders connected to your own character and will have to ignore them. Also, this will not give the whole list in a single chunk to work with, which may be nicer than seeing 5 separate events on the onTriggerStay() method.
Also, this option may not even be tenable because the messages will be also be sent to the triggers surrounding the other characters, which means it may interfere with the “in Range” trigger I have on other characters.

2. Use a Circle Cast

This seems cleaner than A but may have worse performance?
You get all the colliders at once, but you still have to filter out the ones you don’t want. If characters are often not near each other, it means you are typically filtering out every collider you hit.

3. Use a single big Circle Trigger Collider

This option dispenses with the “In Range” collider. It uses a single large circle trigger collider and does two separate processes with all the colliders found: If collider’s transforms are in the right area, it puts the collider on the “In Range” list. And it takes all the colliders and uses that to know what entities are nearby.
This may look clean, but we once again are getting all the separate characters as individual events rather than as a single list to work with. For my purposes that is a bit awkward.
There is also some extra work in determining whether the point is in the “in range” area that is currently defined by the rectangular trigger collider that this object is connected to.

4. Use Collider.Cast and ignoreSiblingColliders

I could also take the collider at the center of my characters and cast it out in several directions to cover the area. By using ignoreSiblingColliders, I don’t have to bother with filtering the hits because the trigger collider in front that determines enemies “in range” will be ignored. Also, I have more control over how the data is brought in because I don’t rely on a onTriggerStay() method to pick up the colliders independently.

The downside is that this will require several casts to cover the circle.

5. Use a single large Circle collider with Collider.Cast and ignoreSiblingColliders

This is a combination of C. and D. It basically dispenses with any use of the onTrigger() messages for anything. Each character has a single large trigger collider and a single small real collider. There are no onTriggerStay() or onTriggerEnter() methods anywhere. I use a Collider.Cast with 0 distance to get a single list of all other colliders in range, using ignoreSiblingColliders so I don’t have to worry about returning the character doing the casting.

I then check to see if any characters are in the “In range” region from the list of colliders returned.

Downsides: I have to do a separate check to see which enemies are in range, and doing this circle.cast every update may be less performant than relying on onTriggerStay().

Did you ever get a good solution for this?