Detecting if a certain 'tag' object is near another one?

Hello,

I am trying to solve the problem of having an object with a certain tag being detected by another one. Both objects are moving.

However, I want the detecting object to have a very large radius (its an outdoor environment and the object should be able to ‘see’ fairly far). This is a problem as both ‘trigger’ and normal ‘collision’ colliders are extremely performance killing when I use an OnTriggerStay or OnCollisionStay function.

function OnCollisionStay (other : Collision) {
    if (other.gameObject.tag == "Support") {
		foundTarget = true;
		targetPos = Vector3(other.transform.position.x,other.transform.position.y,other.transform.localPosition.z+10);
	}
}

Is there a better approach to detecting such an object without bringing FPS down from 100 frames per second to 1 frame per minute?

The normal way is to have a spatial management which manages the objects and their surrounding so you basically always know whats in proximity and alike. OctTrees and similar are normally an approach here and you would only add objects that are generally of any interest at all so you would not look at all and then look if they meet the requirement, you would search by the requirement (ie the tag) and then only check those right from the start

As oyu have it now, it might even be faster to do a distance check against the content of GetGameObjectsWithTag() result array.

You could use the sphere cast at times you need it, just ensure to put the whole static world into the non-cast layer

That being said: if you try to do it in realtime every frame, it will never work out.

Thanks for the quick reply dreamora. I believe that the GetGameObjectsWithTag() is exactly what I’m looking for. I knew that what I was doing was potentially extremely CPU intensive, I just didn’t see an alternative. Thanks very much!

This get is pretty intense as well.
Optimally you wouldn’t use such a thing, you would add a component to all these objects that are meant to see each other and make these component register themself against some form of a manager.
in its simplest form this would just be a list, static, on the component itself. (static ensures that all the instances of this class have 1 global list shared).

then you can just use foreach( ??? _others in others) to go through all in the list and check for distances.
or if you are willing to do some LINQ magic, you would use the others.foreach() method to let it evaluate a given predicate for every member in the list.

On this component add

private static List<"this class name"> others = new List<...>();

void Awake()
{
  others.Add(this);
}

Unfortunately I’m going to have to bring this back up with somewhat the same issue. Right now, performance is fine, and the code works more or less. One thing that does not however work is the maximum distance the raycast travels.

function AllocateTarget() {
	if (Time.time - nullifyRate > nextNullifyTime)
	nextNullifyTime = Time.time - Time.deltaTime;
	// Keep firing until we used up the fire time
	while( nextNullifyTime < Time.time)
	{
		var targets = GameObject.FindGameObjectsWithTag ("Support");
		foundTarget = false;
		for (var other in targets) {
			if (Physics.Raycast (transform.position, other.transform.position, 150)) {
				if (other.tag == "Support") {
					foundTarget = true;
					//Debug.DrawLine(transform.position, Vector3(other.transform.position.x+Random.Range(-1,1),other.transform.position.y+Random.Range(-1,1),other.transform.position.z+Random.Range(-1,1)), Color.white);
					targetPos = Vector3(other.transform.position.x+Random.Range(-1,1),other.transform.position.y+Random.Range(-1,1),other.transform.position.z+Random.Range(-1,1));
				}
			}
		}
		nextNullifyTime += nullifyRate;
	}
}

Here I am going through a small list of what can be at the most 3 objects with the tag ‘Support’. I then go through each one and raycast to see if it is within a certain distance. If it is, then the position of that object is recorded in a variable for further use.

However, there is a problem. I’ll demonstrate with this scenario:
Object 1 is 50 meters away from the raycast origin.
Object 2 is 1000 meters away from the raycast origin.
Object 3 is also 1000 meters away from the raycast origin.

If the max raycast length is 100 meters, then object 1 is sighted and its position is recorded. However, object 2 and 3 are sometimes recorded as well, regardless of being out of range. If ALL objects are out of range then none are recorded.

Is this a bug or am I doing something wrong? I’ve gone over my code a few times and can’t solve this.

I’m aware that I am checking for the same tag twice, but there are problems if I don’t do this. I also use localPosition on the Z axis as I need to compensate for the speed of the object.

a wonder that the performance is fine. Using a loop and FindGameObjectsXXXX is rather costly, even more so if you afterwards to additional raycasts.
What makes no sense here is that you do “if(other.tag …)” cause other isn’t the thing you found with raycast.
you would need to have a RaycastHit object you pass into the raycast to find the hit and then ask the hit object if it has tag support

thats what gives you the wrong reporting here.