Raycast rarely fails, for no discernible reason

Hi there,
I’ve been weeks looking for what may be causing this, without a slightly idea of what could it be.
I’m using raycasts for bullet hit-testing on a retro-fps game. The odd thing is that common colliders works, when raycasts, after some time of playing, starts to fail here and there.
I’ve tried drawing it’s path, checking frame-by-frame, without any hit of what could it be.

The raycast in this case is checking it’s path against a capsule collider. I’ve tried using Update(), also FixedUpdate(). Tried Raycast, and RaycastAll. On my last attempt, my raycast code is as follows:
RaycastHit[ ] hits;
hits = Physics.RaycastAll(testPos, testDir, mag, bulletHitAbles); //bulletHitAbles is a layermask

When the error kicks, zero hits are returned.
This same bullet hits successfully a static mesh collider later (scenary/walls), after skipping/not-hitting the capsule collider (which is not static, also, it’s not moving or moving very slowly).

While testing, I’ve added other capsule colliders behind this target, and the bullets hits those capsules without any problem.

While testing, I’ve removed the Physic Material that was set on the capsule collider of this target, and the shots were successful again. But I’m not sure if it’s related, or if it was luck, since it’s very hard to replicate this case.

Do someone knows what may be going on? I’m almost sure that Physic Material is not part of the hit-testing. Maybe the surrounding mesh colliders trigger some unexpected cases?

Is there any possibility of debugging deeper into the raycast itself?

Thanks,

Hi,

You can for example begin by use Draw.DebugRay to visualize the rays when running the game in the Editor.
Then you will at least see if the rays are going in the direction, and with the length as you think.

Also check for any errors logs in the console.

No errors on console. I would LOVE to see one!
I’m also drawing lines and debugging details frame-by-frame. The raycast passes through the collider, but no collision is registered.

How do you check if it’s a hit? The hits output is an array from Physics.RaycastAll. So I guess the length is 0 when no hit. Otherwise you have to loop through the array to get all of them.

Yep! Checking the length too. Zero. No hit.
I’m almost thinking on debugging the whole physical data on the Scene view, to make a gif of it. Something like “raycast world pos, world dir, magnetude, layermask - capsule world pos, capsule height/radius, capsule layer”
PRoblem is, it’s difficult to make this bug happen. Sometimes it happens in 15 minutes of gameplay, sometime it takes more than a hour.

Are you sure the invisible colliders are in the places, with the shapes as you think? It’s not always the case if they are children to parents with scalings, and rotations, and offsets, differing from 1,1,1 - 0,0,0 - respectively 0,0,0.

And what distances are you talking about? Perhaps to far away objects may fall through the net by rounding errors, or to large angular steps if your rays are sweeping over a sector.


Played the game for more than a hour to get this.
The blue line is the raycast line.

It clearly crosses the capsule collider, visually.
On the first screenshot, it outputs the ray start/end points:
on a frame, it was:
–ray start pos: (-10.8, 2.8, 740.3) ray endpos: (-7.0, 2.5, 739.1)
Next frame, it was:
–ray start pos: (-7.0, 2.5, 739.1) ray endpos: (-3.2, 2.2, 737.9)
Next one:
–ray start pos: (-3.2, 2.2, 737.9) ray endpos: (0.6, 1.9, 736.8)

Next, I’ve drag-dropped this game object to the root, to check it’s global position on the inspector:


Copy-paste from my editor, the character had not moved much (almost nothing):
Vector3(-3.74492645,0.999999762,738.147217)

The line crossed the capsule collider, but the raycast failed.
This is my debug.draw code:
Debug.DrawLine(testPos, testPos + testDir.normalized * mag, Color.blue, 0.1f);
This is my Raycast call:
hits = Physics.RaycastAll(testPos, testDir, mag, hitLayermask)
which returned zero hits.
I’ve recorded this test and upoaded here:

(please ignore the Trail Renderer, it’s purely cosmetic)

Perhaps just to file a bug report then? Unless something else is going on in the scripts like fiddling with the layer masks, or suppressing errors with try catch statements.

1 Like

Thanks! Did that.
https://fogbugz.unity3d.com/default.asp?1418064_dr1i1kgaubmr3na0

Is it possible to “deeper debug” into raycast calls? This problem have been haunting me for quite some time, and I’m clueless on where to go.

Just a hunch: are you moving any colliders using the transform functions instead of the rigidbody.MovePosition or AddForce etc.?

if so, the colliders could be out of sync, so what you see in the editor is not actually what the ray casts inside the physics engine see.

You could try using the Physics Debug window to see what the physics engine is seeing. In 2022.1 and newer there is a function to automatically debug draw simple queries.

Pure speculation ahead:
Since you mentioned that you need to play for a long time before the issue reproduces, my initial gut feeling tells me that something’s drifting away and is no longer where you expect it to be. One example that I’ve seen is moving Colliders, attached to a Rigidbody, manually every frame, after a while, the attached colliders slowly drift away due to constant mass distribution recalculations and numerical instabilities/inaccuracies accumulating.

1 Like

possible, but the characters are almost tottally iddle, the only moving thing is the raycast bullet

Unity 2022 have that? Pretty cool! I’m just worried that it’s still a pre-release, and my game is a early access title but… do you think it could help visualizing what’s going on?
8114978--1051274--debugs.jpg
For example on this picture (I’ve played almost 2 hours to get this) (also, sorry the bad language)
The enemy is stationary.
The raycast mathematically penetrated the character controller (it’s position and properties are on the Inspector, the Raycast data is on the Console, also on screen/gizmos as the blue line)
RaycastAll hits nothing. There’s not even a Layermask set, just:
RaycastHit[ ] hits2 = Physics.RaycastAll(testPos, testDir, mag);
This character used rigidbody model before, using a capsule collider as collider. This error also happened to it’s rigidbody version.

I’ve added a sphere collider to it’s character on this play session, and the raycast bullet hit it successfully.
Removed it, no hit detected.
Added a capsule collider, hit confirmed
Removed it, no hit detected.
Is perhaps a collider ifself that’s… marked to be skipped on hittest/queries? Or it is really… “somewhere else”? The problem is that, without it’s collider, this character would fall from the ground, so… it’s working. The same character that used a rigidbody (and no character controller at all) got the same error.

Extra findings:
-OverlapSphere works

I’ve filled a bug report weeks ago, without my project. The test process is way demanding to ask anyone to go deep on it.

So are you moving them by setting their transform? I’m pretty sure the colliders are not where you expect them to be. I also had that in my game and disabling and enabling the collider that was not working fixed the problem, because I assume it is then instantly synced with the transform position.

You mentioned that without a collider, the characters are falling, so I assume they have rigidbodies. If so: next time the bug happens, please disable/enable the collider in question. If it works after that, you can be pretty sure the position is out of sync.
Then you should go through the code that moves the character in any way, even the transforms that contain child colliders and such.

Good luck with this, I know that can be incredibly frustrating

2 Likes

I’d say don’t upgrade your project just for that, the query drawing doesn’t do anything that you can’t do with Gizmos or Handles which you are already drawing for your raycasts.

But please try using the Physics Debug window when this issue occurs. It draws shapes just how PhysX sees them and you’ll get the ground truth for where everything is. The green collider gizmos that are in your screenshots can be wrong if your colliders are out of sync, shearing, etc.

How about applying some automated testing to your game, or bug reported project?

For example make the players moving around, as in the game, and constantly shooting rays at their expected positions. For example player.transform.position. And record any misses. Or stop, and freeze the simulation if the ray misses, to make it easier to check whats going on.

8115989--1051505--debug phy.jpg
Allright! Well, this is with the Physics Debug enabled, enemy selected, and the raycast crossing it. Or there’s some detail that I may be missing out?

That looks cool but, the issue is that it really uses lots of playtime to achieve, and the project is way big now. But I wonder if I should build a “coliseum” just for watching NPC skirmishes, maybe I should do one next time.

ps: found out that OverlapSphere works, added it to my last post.

8115989--1051508--top phy.jpg

Hi @tjmaul ! I’ve skipped your reply dont know why. You’re pointing interesting things…
I’ve recently changed the movement from rigidbody to character controllers, so I’ve mixed some things.
Actually, I’m using charactercontroler.Move() to move the characters.

I’ve disabled/enabled the charactercontroller (since it is a collider itself I think?) and the result is what you expected: the character is hit-able once again!

But after a while (maybe because the enemy walked a bit) the character is not hit-able anymore. I have to disable/enable it’s character controller again.

This position out of sync is new to me. My game have some eventual slowdowns by Physics.SyncRigidbodyTransform (or at least it’s what the profiler says). Maybe it is related?

May I ask a last thing? What do you mean by:
Then you should go through the code that moves the character in any way, even the transforms that contain child colliders and such

Thanks a lot, really!

I’m not familiar with your setup, but from the screenshots it seems like the character has limbs with colliders attached to them, too. I also assume they’re moved by an animator, right? Unfortunately I don’t know the implications of using the character controller and animator wrt. collider position updated. I sticked to my own rigidbody based character controller, so I can’t comment on that. I made, however, the mistake of having some colliders in my game updating their transform while the game was paused (timeScale = 0) which had the effect that my raycasts (in my case drag & drop) didn’t work. That was because they weren’t at the position I assumed them to be and the editor gizmos didn’t show me that. I resolved that using Physics.SyncTransforms()

Some thoughts:
My understanding is that there are basically two worlds: The world you can see in the editor and the physics world. Unfortunately it’s not always clear in which direction data flows: You can update a game objects transform and an attached collider will be moved in the physics world, too.

Then there are rigidbodies. They’re moved by physx and their position and rotation data flows into the game objects transform.

The way I setup my worlds is as follows: Obstacles that don’t move have colliders and are marked static (I think this is not stricly necessary but I think it’s good practise), obstacles or characters that move on a path that is calculated by you (as in: being programmed, not affected by gravity and collisions) should have kinematic rigidbodies and should be moved through the rigidbody methods (MoveRotation, MovePosition). Lastly, dynamic objects (with rigidbody, isKinematic: false) should only be manipulated by AddForce/AddTorque.

This will ensure that the data flow (transform → physics world VS physics world → transform) is always clear and the two worlds stay in sync.

Talking of which: this might be interesting:

and this maybe too:

As for the slowdowns: If they happen from time to time, that is definitely strange.

2 Likes