- Home /
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:
Create a new game object child and put a trigger collider on that.
Use a circle cast.
Remove the "in Range" trigger collider and make do with a single big circle collider on the gameObject
Use Collider.Cast with ignoreSiblingColliders
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().
maybe you could tag the enemies differently, then return them in one function and depending on the tag, have different results.
Thanks, RomanLed, I should have mentioned something about that. In my setup there is no designated "hero." There are just several different actors (that are on $$anonymous$$ms), and I'm building an AI that handles any of them.
So in order to use tags for a character to differentiate himself from others, I would need to use a different tag for every one. $$anonymous$$y plan was just to use the transform component (if necessary) to check whether a given collider was the character's own.
are you creating an rpg with multiple controllable characters? whats the specific functionality you're trying to implement? sorry, im not quite understanding, however to check whether a returned collider is your own collider, yes, you could check the transform, or you could check if the collider is equal to collider.gameobject.
are you trying to detect what friendly characters on the same $$anonymous$$m are in the surrounding area?
I'm focusing on just one specific aspect: There are several actors/agents/characters, every one of them has a collider and an offset trigger collider used to deter$$anonymous$$e who is directly in front of them. The goal is for every one of these actors/agents/characters to detect the presence of other actors/agents/characters nearby. So this logic is going on every one of several different gameObjects.
The particular use case is for deter$$anonymous$$ing things like which directions are currently blocked by other (moving) actors/agents/characters and also having one part of the AI attempt to prevent being surrounded.
I have deter$$anonymous$$ed at least 5 ways of doing this... and there may be more. $$anonymous$$y question is which seems best based on maintainability, performance, and general cleanliness.
hmm. sounds complicated. however i'd watch this video https://www.youtube.com/watch?v=mBGUY7EUxXQ to start because it shows how to calculate enemies within a certain range, and tell whether the enemy is infront of the players field of view (eli$$anonymous$$ating the need for a range collider and a seperate box collider to tell if its infront) to optimize your system. (4:50) it sounds like youre trying to create pathfinding?
You can use multiple trigger collider but only one of each type, in the trigger functions you can check what is the collider who called the function and realize the correct action based on this.