Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
7
Question by kk93 · Feb 12, 2014 at 11:05 PM · collidertrigger

Getting a list of Colliders inside a Trigger

Hello,

I have a giant sphere collider around my player object that is set as a trigger. At any point of the game, I need to get a list of colliders inside the sphere and select the one that is closest to the player. To do this, I need to first find a way to get a list of colliders inside the sphere, which i seem to not be able to do... I've dont OnTriggerStay, but that only gives me a Collider rather than a list (or an array) of colliders.

So... How do I get that list?

Thanks!

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

3 Replies

· Add your reply
  • Sort: 
avatar image
20
Best Answer

Answer by CiberX15 · Feb 12, 2014 at 11:14 PM

The best way I have found to do this with a trigger is something like this:

 //Has to go at the top of your file
 #pragma strict
 import System.Collections.Generic;
 
 //The list of colliders currently inside the trigger
 var TriggerList : List.<Collider> = new List.<Collider>();
 
 //called when something enters the trigger
 function OnTriggerEnter(other : Collider)
 {
     //if the object is not already in the list
     if(!TriggerList.Contains(other))
     {
         //add the object to the list
         TriggerList.Add(Other);
     }
 }
 
 //called when something exits the trigger
 function OnTriggerExit(other : Collider)
 {
     //if the object is in the list
     if(TriggerList.Contains(other))
     {
         //remove it from the list
         TriggerList.Remove(Other);
     }
 }

Mind you I have not tested this, but I have used this method before on other projects.

Comment
Add comment · Show 10 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image kk93 · Feb 12, 2014 at 11:26 PM 0
Share

Works beautifully. Thanks!

avatar image Lichemperor · Feb 26, 2016 at 11:57 PM 0
Share

Simple and effective. Cheers!

avatar image NoxCaos · May 03, 2016 at 01:00 PM 3
Share

Sometimes objects exit trigger and unity misses this

avatar image mfarnoosh NoxCaos · Dec 23, 2016 at 03:27 PM 0
Share

I have the same problem, i created a list and .... but sometimes no collision detected but my list has value!!!

avatar image CiberX15 NoxCaos · Feb 16, 2019 at 05:50 PM 0
Share

This can happen sometimes depending on the triggers setting. I am fairly certain you can prevent this by adding a rigidbody to the trigger (set it to kinematic if you don't want it to move), then set the rigidbodys collision detection to dynamic. This is worse for performance but guarantees detection even if an entity would normally be moving so fast as to miss the collider between frames.

avatar image cavrnusdemo · Jun 08, 2017 at 01:18 AM 2
Share

This doesn't work. The OnTriggerExit won't be called when objects are deactivated or destroyed. The way around this is to make a list of the objects you are touching, loop through it in an Update, and when they are null or deactivated, remove them.

avatar image NoxCaos cavrnusdemo · Jun 08, 2017 at 01:25 AM 0
Share

$$anonymous$$aybe in this case it will be better to use Physics.OverlapBox() method to get the list of objects. You just have to setup box same size as trigger

avatar image toddisarockstar NoxCaos · Jun 08, 2017 at 03:28 AM 0
Share

overlapshere or box would work for him but these calls are very heavy on preformance specially when used every frame or often if that's what he needs.

avatar image Sici9 · Feb 04, 2019 at 03:25 PM 0
Share

Using this method, is there a way to see and compare the tags of the objects added to the list?

avatar image CiberX15 Sici9 · Feb 16, 2019 at 05:47 PM 0
Share

Sure. If you only wanted to add objects with a given tag you could check for that on the OnTriggerEnter() function.

if(!TriggerList.Contains(other) && other.gameObject.tag == [whatever tag you are looking for]) { //add the object to the list TriggerList.Add(Other); }

If you wanted to only have one object of any given tag you could do that too, though you would have to for loop through the existing list to check if any of the currently stored objects have the tag or not, which might hurt performance depending on how many items end up in the list at any given time.

avatar image
2

Answer by chris-nolet · Feb 28, 2018 at 09:42 PM

You can use Physics.OverlapSphereNonAlloc() for this purpose. It's available from Unity 5.3 onwards. The results array should be allocated once and re-used, so there's no garbage being generated.

Comment
Add comment · Show 3 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image NoxCaos · Mar 01, 2018 at 12:27 AM 0
Share

Interesting... So I can launch a separate job that will update my list async and this will be more efficient?

avatar image chris-nolet NoxCaos · Mar 01, 2018 at 02:06 AM 1
Share

Hi @NoxCaos. You can call this function as-needed, synchronously. I believe it's fast enough to run in Update(). (This is in contrast to the original Physics.OverlapSphere(), which should not be called every frame, because it allocates memory on the heap.)

avatar image NoxCaos chris-nolet · Mar 01, 2018 at 04:41 AM 0
Share

Okay, I see now. Thank you a lot for that solution

avatar image
0

Answer by Ultroman · Feb 29, 2020 at 03:43 PM

I want to propose a slightly different solution to this. I know it's an old question, with an answer, but the accepted answer doesn't handle the problem of triggers becoming disabled or destroyed, in which case they are never removed from the resulting list of colliders. The second answer (OverlapSphereNonAlloc and the like) are hampered by us having to do those calls for every collider under our rigidbody, instead of being able to rely on the OnTrigger*** functions to easily handle multi-collider triggers. I can see that people are still searching for a solution to this, still commenting on this question and others like it to this day, so I wouldn't call this necro'ing, though others might. Anyway, I only just coded this and haven't tested it, but it's fairly simple code.


Here's my proposal. You might find it a bit much for something like this, but I'll only be needing one of these in my game, so I think it can handle it :)


I use OnTriggerEnter and OnTriggerStay to add and update the state of my currently registered triggers (their value in the _triggerStates Dictionary is set to "true"), and I use FixedUpdate to prune the triggers, removing those that did not fire an OnTriggerEnter or OnTriggerStay last FixedUpdate, as well as those which were destroyed in-between.

 using System.Collections.Generic;
 using UnityEngine;
 
 public class Test : MonoBehaviour
 {
     private Dictionary<Collider, bool> _triggerStates = new Dictionary<Collider, bool>();
     public List<Collider> _currentTriggers { get; private set; } = new List<Collider>();
     private bool _on = true;
 
     // FixedUpdate is first in Unity's execution order.
     // We use it to check the state of the triggers we are currently colliding with.
     // To avoid iterating over the Dictionary, because then I can't remove from it while iterating,
     // I keep the equivalent of its keys in a list next to it. This might not be the most memory
     // efficient, until you realize that it doubles as a constantly up-to-date list of all
     // the colliders we are currently triggering, which is what we wanted to get this thing
     // to produce in the first place. Also, they'll just be references, some bools and some hashes.
     // We shouldn't be handling too many collisions like this, anyway.
     // You can easily create functions to turn it on and off, if you find it to be too intensive.
     private void FixedUpdate()
     {
         for (var i = 0; i < _currentTriggers.Count; i++)
         {
             var trigger = _currentTriggers[i];
             // If the trigger is no more, for whatever reason, remove it.
             if (!trigger)
             {
                 _triggerStates.Remove(trigger);
                 _currentTriggers.Remove(trigger);
                 continue;
             }
 
             // If _currentTriggers has a collider which _triggerStates doesn't have, something
             // weird has happened (it should not be possible), so default to scrapping it.
             // It'll get added again next FixedUpdate if it is still OnTriggerStay'ing.
             if (!_triggerStates.ContainsKey(trigger))
             {
                 _currentTriggers.Remove(trigger);
             }
             else
             {
                 // This is the exciting part. FixedUpdate runs before the OnTrigger***, so we can
                 // check here what the results are after the last OnTrigger*** calls came in.
                 // They all set the state to "true" when adding or stay'ing a trigger, so if its
                 // state is false here, then it is no longer stay'ing, and OnTriggerExit has not
                 // been called to remove it, so we do it here.
                 if (!_triggerStates[trigger])
                 {
                     _triggerStates.Remove(trigger);
                     _currentTriggers.Remove(trigger);
                 }
                 else
                 {
                     // Reset state to "false", so the coming OnTrigger*** calls can update them again.
                     _triggerStates[trigger] = false;
                 }
             }
         }
     }
 
     // Called when a trigger enters
     private void OnTriggerEnter(Collider other)
     {
         //if the object is not already in the list
         if (!_triggerStates.ContainsKey(other))
         {
             //add the object to the list
             _triggerStates.Add(other, true);
             _currentTriggers.Add(other);
         }
     }
 
     // Called every FixedUpdate between OnTriggerEnter and OnTriggerExit (or until the trigger is
     // disabled, in which case OnTriggerExit is not called, which is why we're doing all of this ;) ).
     private void OnTriggerStay(Collider other)
     {
         if (!_triggerStates.ContainsKey(other))
         {
             //add the object to the list
             _triggerStates.Add(other, true);
             _currentTriggers.Add(other);
         }
         else
         {
             _triggerStates[other] = true;
         }
     }
 
     // Called when a trigger exits.
     private void OnTriggerExit(Collider other)
     {
         _triggerStates.Remove(other);
         _currentTriggers.Remove(other);
     }
 
     public void ResetRegisteredTriggers()
     {
         _currentTriggers.Clear();
         _triggerStates.Clear();
     }
 
     public void Toggle(bool on, bool resetCurrentTriggers = true)
     {
         _on = on;
         if(resetCurrentTriggers)
             ResetRegisteredTriggers();
     }
 }
Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

29 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Can't click gameobject when over another trigger? 1 Answer

Triggering platform animation on colliding with Button 0 Answers

Use trigger with player but have a collider with everything else? 3 Answers

How do you go from one scene, to another, then a third and back again ? 0 Answers

Stop object colliders (non-mesh) bouncing on collision 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges