- Home /
Check for objects inside a Collider?
Hi all, I am trying my make it so when a player interacts with a Trollie any objects tagged with 'Item' that are contained within a box collider on the front of the Trollie, get set as a child of the Trollie and become kinematic etc, I presume I may need to use a foreach() loop that runs though each object, but am unsure of how to check for objects that are within the collider.
I could use onCollisionEnter/Stay but the issue with this is that the objects being attached to the Trollie will lock to it Instantly and not when the Trollie begins it's interaction stage, that means the object will be ripped from the players hands (if the object touches the collider) and then locked to the Trollie, hence why I need all contained objects to be locked after the player Interacts with the Trollie, not when the object interacts with the Trollie, as to interact with the Trollie the player must have their hands free.
I was thinking I could use the onCollisionEnter() alongside a timer that after a short time it then locks the object to the Trollie, though for people like me with OCD I am sure there will be a point where a player would like to nicely stack up their Trollie with objects and if the object is inside the collider for this time before it gets dropped by the player it will be locked in place where it stands possibly floating in mid-air.
Any help to give me an idea on how I would even begin with this Idea would be greatly appreciated
Current Code:
public void interactWithTrollie()
{
if (!isInteractingWithTrollie)
{
//Check for Items contained would go here, before the Trollie gets repositioned and rotated to suit the players looking direction to avoid 'dropping' objects
isInteractingWithTrollie = true;
trollieTrans.SetParent(playerTrollieTrans);
trollieTrans.localPosition = new Vector3(0, 0, 0);
trollieTrans.localRotation = Quaternion.Euler(new Vector3 (operatingAngle.x, 0, 0));
}
else
{
//There is no need to 'unlock' the objects as when the player picks the Item up it will detach from the Trollie and attach to the player.
isInteractingWithTrollie = false;
trollieTrans.SetParent(null);
trollieTrans.eulerAngles = new Vector3(
0,
camRot.eulerAngles.y,
0
);
}
}
Answer by metalted · Dec 07, 2021 at 09:06 AM
You can make use of the OnTriggerEnter and OnTriggerExit functions to keep track of the objects inside of the collider. You add them when they get in, remove them when they go out. Then when you want to interact with the objects, you just interact with the gameobjects in the list. Something like this:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ColliderList : MonoBehaviour
{
public List<GameObject> colliderList = new List<GameObject>();
public void OnTriggerEnter(Collider collider)
{
if (!colliderList.Contains(collider.gameObject))
{
colliderList.Add(collider.gameObject);
Debug.Log("Added " + gameObject.name);
Debug.Log("GameObjects in list: " + colliderList.Count);
}
}
public void OnTriggerExit(Collider collider)
{
if(colliderList.Contains(collider.gameObject))
{
colliderList.Remove(collider.gameObject);
Debug.Log("Removed " + gameObject.name);
Debug.Log("GameObjects in list: " + colliderList.Count);
}
}
}
Thank you for this, I may need to do some testing as I have had trouble with using OnTrigger/CollisionExit in the past with my games Item objects as when the objects are picked up the box collider for them gets disabled (which I believe may never trigger the OnTrigger/CollsionExit function) thus creating a forever growing list.
Never the less I will give this a shot and see if I can work with it.
If you dont want to use the Enter and Exit functions because of that, there are other ways. You could use Bounds.Contains, which just relies on a position. But it requires you to either keep track of all the items in the world using a list or array or something, or get all the gameobjects with a certain tag.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ItemsInsideBounds : MonoBehaviour
{
public GameObject[] items;
public void Start()
{
GameObject[] itemsInsideCollider = GetItemsInsideCollider();
Debug.Log("There are " + itemsInsideCollider.Length + " items in the collider!");
}
public GameObject[] GetItemsInsideCollider()
{
List<GameObject> internalGameObjects = new List<GameObject>();
Collider boundsCollider = GetComponent<Collider>();
for(int i = 0; i < items.Length; i++)
{
if(boundsCollider.bounds.Contains(items[i].transform.position))
{
internalGameObjects.Add(items[i]);
}
}
return internalGameObjects.ToArray();
}
}
https://docs.unity3d.com/ScriptReference/Bounds.Contains.html
Thank you for this, it definitely seems like a viable way to get this idea working, I've had a bit of a play around with it, however for some reason am unable to detect any objects within the collider, is there something I may be missing?
This is a video showcasing the outcome:
https://www.youtube.com/watch?v=gt28zwAfyrE&ab_channel=FuryFight3r
I am using a slightly modified version of what you provided, it may be possible that I have messed something up in the process:
public void interactWithTrollie()
{
if (!isInteractingWithTrollie)
{
GameObject[] itemsInsideCollider = GetItemsInsideCollider();
Debug.Log("There are " + itemsInsideCollider.Length + " items in the collider!");
foreach(GameObject i in itemsInsideCollider)
{
Rigidbody rig = i.GetComponent<Rigidbody>();
rig.isKinematic = true;
i.transform.SetParent(trollieTrans);
}
isInteractingWithTrollie = true;
trollieTrans.SetParent(playerTrollieTrans);
trollieTrans.localPosition = new Vector3(0, 0, 0);
trollieTrans.localRotation = Quaternion.Euler(new Vector3 (operatingAngle.x, 0, 0));
}
else
{
isInteractingWithTrollie = false;
trollieTrans.SetParent(null);
trollieTrans.eulerAngles = new Vector3(
0,
camRot.eulerAngles.y,
0
);
}
}
GameObject[] GetItemsInsideCollider()
{
List<GameObject> internalGameObjects = new List<GameObject>();
Collider boundsCollider = trigger;
for (int i = 0; i < items.Length; i++)
{
if (boundsCollider.bounds.Contains(items[i].transform.position))
{
internalGameObjects.Add(items[i]);
}
}
return internalGameObjects.ToArray();
}
Your answer
