Trouble with detecting collision in the same frame to make smart labels

Hello everyone.

I am having a hard time making “smart labels” for my game so that the user can view the points of interest (POI) with ease.

I’m going to explain some things before getting to the problem:

Contextualization

Billboard
The point of interest is a gameObject with a Canvas with its Render Mode set to World Space. Its role is simply to display the image and name of the space below it. Basically it is a billboard that constantly looks at the camera. It is also a way in which the user can interact with the world, so I added a box collider to it, making it able to detect a ray-cast to then perform some action.

Scenario
It consists of a 3D city and the camera is top down in its standard mode but it can be tilted up to 60 degrees for perspective immersion.

Smart Label Logic
What I did was to set a specific relevance to each point of interest. Then I created a prefab that is placed exactly in the position of the POI. They are responsible for calculating the collisions, that is why they contain a Mesh renderer (which is for visualization only. I choose this instead of Gizmos so I could see them work within the game tab), Rigidbody and Sphere collider to be able to compute the collisions.


When the game starts, I organize the list with the labels by relevance, so that it can be placed in order.

Now, when the user zooms in or out, I resize the Sphere’s and make them collide in order to see which POI’s need to be displayed. As the user zooms out, the sphere’s grow bigger and only the important one’s will show and vice versa.

The ideal situation

When zoom changes:

1: Deactivate all the spheres Colliders
2: Resize all spheres Colliders
3: Activate the game objects that contain the spheres (the Colliders are disabled so that they wont collide!)
4: Activate the game objects that contain the spheres ONE BY ONE in the order of the already sorted list
5: If it collides, deactivate the current (It means it collided with one of higher relevance)
6: if it doesn’t collide, activate it.

Problem
When physics is involved, it wont compute the collision until the next frame. So, if I add this to the update function, it would not get the collisions correctly due to the frame-rate. If I add it to a coroutine and add the sphere, tell it to wait to the next frame and so on, IT WORKS, but takes too long to complete, making it unusable.

I feel like i’ve tried everything… I tried changing to fixed update, using OnTriggerEnter and even Check-sphere. NONE of these have worked.

I really need a direction because I have run out of things to try.

Using layers, you can make colliders on certain layers NOT interact with any other colliders in the physics setup panel under project settings.

Then you can just raycast at it without physics entanglement.

You can even use that same layer in the Raycast (with a layermask created from that layer) to say “I only want to hear that I raycasted at colliders on this layer.”

So you are saying that I keep what i’ve done until step 4, as quoted below. And then instead of checking for collisions, using ray-cast on all directions for each POI?

If that is the case, any idea on how to do that? Wouldn’t it be too expensive?

The point of using layers and unchecking interactions is so you don’t need step 1 above.

You just put all the colliders in and they do nothing with anything because you’ve told the physics so.

Then you look for them with the raycast. That’s it.

Could you be more specific about the raycast check? How would you do this?
I am asking because I have no idea on how to do this.

There are TONS of Youtube tutorials out there on Raycasting.

The Raycast docs even have an actual code example:

Generally you raycast from the user’s eyepoint (camera) in the transform.forward direction.

Put away your current scene work, break out a brand-new test scene, put a sphere in it, and get familiar with how Raycasts work before you tear up your actual game scenes experimenting. It’s really simple and it does work.

I am already familiar with raycast. I was actually referring to this specific case because It just seems a bit too much to cast a ray in 8 directions (front, back, left, right and then diagonals) for each object in order to check for collision. That’s why I asked what you had in mind to see if it was something more simple.

[EDIT]
And also, I forgot to ask. The raycast can check for collisions in the same frame? In case it doesn’t it will result in the same problems I’m currently having.

What exactly are you raycasting all these different directions? If you are doing gaze work you want to raycast from your eye and say “did I hit anything of interest?”

If you’re looking to “light up” or “wiggle” a larger number of things, all of which might be nearish the central view of the player, you don’t really need raycast.

Instead you can iterate the objects in question and compare the vector from your eye to the object with the vector coming straight out your +Z eye, and see if that angle is low enough to consider “yeah, you’re nearly looking at me, I will wiggle.”

That would involve calling this function with the two vectors:

and deciding the angle is below the cone angle you want to say is low enough to wiggle the object.

Raycasts are “right now, right this very second, in the scene now,” not part of the main physics loop.

You are saying “from here, going that way, with the conditions I provide, do I hit something?”

In fact, you can AddComponent a collider onto an enabled GameObject, raycast and see if you hit it, then Destroy the collider immediately. That’s silly, but it will work all day long.

Although inapplicable directly, this might help you think about it in a bigger sense:

@Kurt-Dekker I have just tried what you suggested but using a SphereCast because I assumed that it behaves similarly to the Raycast. it didn’t work.

I get what you are saying, and this is not at all my case.

Do you want me to explain with more details/code what is happening?

I am desperate for help and would really appreciate if someone else could provide me some other insights!

I re-read your lengthy initial description and I guess I just don’t get what you’re trying to do. It seems my suggestion of Quaternion.Angle() would get you what you need, but apparently I misunderstand your intentions.

Perhaps try and start with a stripped-down description, or perhaps reference a video of another game that does exactly this thing, so there is clear communication here.

OK.

So, this is what I have. It keeps all billboards active at all times and changes its size when I zoom in or out.

This is what I want to achieve. It does the same as now (Resizing) but it also activates/deactivates some billboards according to its relevance.


According to the zoom level of the camera

  1. 0% being total zoomed out, camera bounds max
  2. 100% being total zoomed in, camera bounds min

It has to recalculate every time the user passes a threshold which I defined to 10%. That means that it will recalculate at every 10% (0, 10, 20, 30…) all the way up to 80%. When It comes to 80%, it activates all billboards in the map.

It does so by checking the relevance of that billboard and creating a sphere around it, with its size proportional to the relevance.

The issue I am having is to check the collisions and activate/deactivate the correct one’s due to everything I explained above.

I could set a % in which each billboard has to show up/hide but It would not work for me. It has to be a general script because I have several maps and I need it to be automated for each case.

If something is not clear I will be happy to detail it more!