Jump to content

Does anyone have experience with why Physics.RayCast sometimes passes through parts?


Dunbaratu

Recommended Posts

This isn't workable in this case because I don't hardcode which part I'm trying to aim at. Its "return the hit on whichever part you hit that's nearest".

Not sure if you get what I mean. Use Spherecast and see if it works. Test multiple radii. If it works, you can eliminate possibilities for what's wrong. If a radius of 0.5 is hitting and 0.4 isn't, you know that something is off by 0.5.

That's what this is:


origin = this.part.transform.TransformPoint( relLaserOrigin );
pointing = this.part.transform.rotation * Vector3d.down;

Yeah, but why not use a much simpler formulation that's more flexible? Eliminates possibilities for error.


Transform castPoint = FindModelTransform(nameOfGameObject);
origin = castPoint.position;
pointing = castPoint.forward; //blue axis of transform in Unity

(Note that I don't remember offhand the calling syntax for FindModelTransform because it's a KSP, not Unity method)

It's done during Update(), using a recalculation of origin and pointing (since the location of things can be different during Update()), but capping the distance of the line at whatever the distance result of the raycasts in FixedUpdate were. So FixedUpdate is picking the distance of the hit, then Update() is drawing using that distance. I don't think that will make much difference but I could move the drawing code to fixedupdate too. The problem isn't the drawing, but the calculation of the distance is missing the hit entirely.

Well, what you're doing to visualize is kinda useless then. I'd say you want to visualize exactly where your ray is starting from and pointing - if you're running your visualization code from things updated every frame (Update), it will be inconsistent with what's actually going on.

As to your last point... The biggest problem with using raycasts in Update isn't that it's necessarily *wrong*, but that Update runs every frame (up to the FPS cap) and that FixedUpdate runs every physics frame, which are less frequent and always happen at intervals of Time.fixedDeltaTime. Doing 60 raycasts per second is not great for performance... especially when it adds up with multiple objects doing this.

Basically if you run a physics-based calculation every actual frame, you could get correct results, but you might not. More likely you'd get the same result for a few frames before the next physics update tick went through.

Link to comment
Share on other sites

Not sure if you get what I mean. Use Spherecast and see if it works. Test multiple radii. If it works, you can eliminate possibilities for what's wrong. If a radius of 0.5 is hitting and 0.4 isn't, you know that something is off by 0.5.

But it would differ from the actual problem in a massively important way - I'd be the one creating the sphere that I'm aiming the ray at, and the problem is dependent on the timing of my raycast's positioning versus the parts' positioning. If I'm the one in control of setting both the ray and the sphere it's hitting then I'm not really exposing where the problem is happening because I'll be deciding when the sphere moves. The frustrating thing I'm having with most of the google-able advice is that it's written for people writing their own unity game from scratch and telling them how to interleave the movement of their objects with the raycasting to try hitting them. As I'm not in charge of when SQUAD choses to move the parts around and what the timings on that is (nor can I even discover what it is because it's not public source code), such advice doesn't work in my case.

Or do I not understand what you're asking to do?

Yeah, but why not use a much simpler formulation that's more flexible? Eliminates possibilities for error.


Transform castPoint = FindModelTransform(nameOfGameObject);
origin = castPoint.position;
pointing = castPoint.forward; //blue axis of transform in Unity

(Note that I don't remember offhand the calling syntax for FindModelTransform because it's a KSP, not Unity method)

I agree with the principle to do it as simply as possible to remove the unknown variables, but that does not look simpler than what I did. Not to my eyes. FindModelTransform is adding an unknown I'm not in control of. Getting the transform of the part directly from Unity like I did is less of an unknown.

Well, what you're doing to visualize is kinda useless then. I'd say you want to visualize exactly where your ray is starting from and pointing - if you're running your visualization code from things updated every frame (Update), it will be inconsistent with what's actually going on.

I should be clear that the linerenderer isn't just there for debugging purposes. It's intended to be visible to the end-user as the laserbeam. And I was told you do your animations in Update() because it's what runs every animation frame. As the linerenderer changes a bit each frame (making a pulsating effect where the line changes thickness and opacity each frame), it should be getting updated at animation frame rate, not physics frame rate.

I could add a second linerenderer for debugging that's NOT the one the user will see in the end, and update it during fixedupdate().

As to your last point... The biggest problem with using raycasts in Update isn't that it's necessarily *wrong*, but that Update runs every frame (up to the FPS cap) and that FixedUpdate runs every physics frame, which are less frequent and always happen at intervals of Time.fixedDeltaTime. Doing 60 raycasts per second is not great for performance... especially when it adds up with multiple objects doing this.

The assumption that framerate is always faster than physics updates is false. On computers with high speed and good graphics cards it is. On less powerful machines it is not. The default physics rate is always 25 FixedUpdate()'s per second regardless of computer speed, while Update() rate depends on the quality of your machine and your video card and can be either faster or slower than 25 FPS depending on the computer. My computer is not a super awesome gaming machine. It's a macbook pro laptop that's been repurposed to run Windows instead of MacOS. I get about 20 FPS when part count is low. Worse when it's high.

In my case, putting work in Update() makes it impact the system *less* than putting it in FixedUpdate. If you see back in the thread, I've been consistently describing a situation in which more than one FixedUpdate() happens between Update()'s.

In a way I'm sort of glad my machine is not great. Otherwise I might not have experienced the problem and might have released a mod that's broken on slow machines and not realized it.

Link to comment
Share on other sites

But it would differ from the actual problem in a massively important way - I'd be the one creating the sphere that I'm aiming the ray at, and the problem is dependent on the timing of my raycast's positioning versus the parts' positioning. If I'm the one in control of setting both the ray and the sphere it's hitting then I'm not really exposing where the problem is happening because I'll be deciding when the sphere moves. The frustrating thing I'm having with most of the google-able advice is that it's written for people writing their own unity game from scratch and telling them how to interleave the movement of their objects with the raycasting to try hitting them. As I'm not in charge of when SQUAD choses to move the parts around and what the timings on that is (nor can I even discover what it is because it's not public source code), such advice doesn't work in my case.

Or do I not understand what you're asking to do?

Sorry, didn't think I needed to explain Spherecast. Imagine a raycast, but instead of moving a single point through the scene and tracking collisions, it moves a sphere, which is necessarily wider. Think of it as throwing a beachball instead of a golf ball. If you're missing with the golf ball, and the beach ball hits, you have some idea of where the target must be.

I agree with the principle to do it as simply as possible to remove the unknown variables, but that does not look simpler than what I did. Not to my eyes. FindModelTransform is adding an unknown I'm not in control of. Getting the transform of the part directly from Unity like I did is less of an unknown.

The method I describe would give you the transform of an aiming point, specified in the Unity Editor which would be superior to the getting the transform of the part itself and then adding an offset, and then giving it a rotation. I can tell you that the code I directed you to is pretty ironclad, all it (seems to) to do is traverse the GameObject hierarchy and gets the transform with the corresponding name in the part. Never had any problem using it, and I use it for raycasting in Near Future Solar.

I should be clear that the linerenderer isn't just there for debugging purposes. It's intended to be visible to the end-user as the laserbeam. And I was told you do your animations in Update() because it's what runs every animation frame. As the linerenderer changes a bit each frame (making a pulsating effect where the line changes thickness and opacity each frame), it should be getting updated at animation frame rate, not physics frame rate.

I could add a second linerenderer for debugging that's NOT the one the user will see in the end, and update it during fixedupdate().

Ok, sure. You should indeed draw your user-facing line renderer in Update, but that's not helping me fix your problem :P.

The assumption that framerate is always faster than physics updates is false. On computers with high speed and good graphics cards it is. On less powerful machines it is not. The default physics rate is always 25 FixedUpdate()'s per second regardless of computer speed, while Update() rate depends on the quality of your machine and your video card and can be either faster or slower than 25 FPS depending on the computer. My computer is not a super awesome gaming machine. It's a macbook pro laptop that's been repurposed to run Windows instead of MacOS. I get about 20 FPS when part count is low. Worse when it's high.

In my case, putting work in Update() makes it impact the system *less* than putting it in FixedUpdate. If you see back in the thread, I've been consistently describing a situation in which more than one FixedUpdate() happens between Update()'s.

In a way I'm sort of glad my machine is not great. Otherwise I might not have experienced the problem and might have released a mod that's broken on slow machines and not realized it.

I'm not saying that it's faster, but it will frequently be faster. I'm saying it's inconsistent. Seems what you want to do is run it less frequently than FixedUpdate, and running it in Update because it's slower on *your* system is pretty bad practice. Say you ran it on mine, with 2 part ship. I get pretty nice framerates there and it would run way more than needed. I highly recommend running it either in FixedUpdate, using a frame counter to only run it every 3rd or 4th frame or so, or run it in a coroutine.

Link to comment
Share on other sites

Sorry, didn't think I needed to explain Spherecast. Imagine a raycast, but instead of moving a single point through the scene and tracking collisions, it moves a sphere, which is necessarily wider. Think of it as throwing a beachball instead of a golf ball. If you're missing with the golf ball, and the beach ball hits, you have some idea of where the target must be.

Wow if that's what it does then it's named very weirdly. Because what you're describing would be better called a cylinder cast - a raycast with a diameter to it.

At any rate, I'll try adding a second linerenderer during FixedUpdate, and then when the raycast misses, I'll leave the linerenderer behind and start a new one next FixedUpdate rather than moving the old one - that should leave behind lines hanging in space on all occasions where there was a missed cast. The misses are so fast and short that just updating the same linerenderer would not actually be visible since I have a slow framerate (it might move it back to the right spot before rendering a frame).

The method I describe would give you the transform of an aiming point, specified in the Unity Editor which would be superior to the getting the transform of the part itself and then adding an offset, and then giving it a rotation.

It's not just "a" rotation. It's *the* very rotation of the part itself, gotten from the same transform as the transform that got the point. Is there a way to tell the Unity editor to put a marker at a location inside my model and give it a name I can reference later, rather than the location of the model as a whole? I don't know the Unity editor well enough to know if there's a way to name a specific spot within the editor and reference it later in the C# code rather than the transform of the model as a whole.

I can tell you that the code I directed you to is pretty ironclad, all it (seems to) to do is traverse the GameObject hierarchy and gets the transform with the corresponding name in the part. Never had any problem using it, and I use it for raycasting in Near Future Solar.

The problem is that naming a subset of the model with its own separate name is not a thing I've done before. I don't know where it is in Unity.

Ok, sure. You should indeed draw your user-facing line renderer in Update, but that's not helping me fix your problem :P.

I'm not saying that it's faster, but it will frequently be faster. I'm saying it's inconsistent.

It's not what you said the first time. You gave no qualifiers and just said it *IS* faster. BOTH assumptions are inconsistent. The assumption that Update() is slower is no less wrong than the assumption that it's faster. A proper solution would have to use neither of those two assumptions, which is what I'm trying to do. I'm using Update() over FixedUpdate() only because of the consequences of what would happen if I take longer than I should. If I take longer than I should in Update() the result is stuttering animation but still correct numbers. If I take longer than I should in FixedUpdate() the result is more catastrophic than that. As I understand it, Unity enforces the FixedUpdate rate by aborting code partway through if it's taking too long. That doesn't just make things stutter, it makes them incorrect.

Seems what you want to do is run it less frequently than FixedUpdate, and running it in Update because it's slower on *your* system is pretty bad practice. Say you ran it on mine, with 2 part ship. I get pretty nice framerates there and it would run way more than needed. I highly recommend running it either in FixedUpdate, using a frame counter to only run it every 3rd or 4th frame or so, or run it in a coroutine.

Edited by Steven Mading
Link to comment
Share on other sites

The code is just too full of spaghetti mess at the moment with lots of my false starts and patchy rework trying to figure out what's going on, so I just checked it in to github as it is and I'll branch it and try again starting over with smaller simpler code that doesn't do much but the minimum that recreates the problem. Either the problem won't recreate, or it will with a small enough amount of code that I can actually show the whole thing to people. I'll take out everything about the numeric pqs solver, and everything about trying to average multiple hits over several FixedUpdates, and just show the basic situation - a FixedUpdate that should find the hit, and doesn't.

There's a lot of extraneous side issues in the thread cluttering up the actual problem.

Edited by Steven Mading
Link to comment
Share on other sites

Dude, no need to bite my head off. I'm just trying to help you solve your problem. You asked why the doc example doesn't specifically use FixedUpdate, and I answered that.

It's not just "a" rotation. It's *the* very rotation of the part itself, gotten from the same transform as the transform that got the point. Is there a way to tell the Unity editor to put a marker at a location inside my model and give it a name I can reference later, rather than the location of the model as a whole? I don't know the Unity editor well enough to know if there's a way to name a specific spot within the editor and reference it later in the C# code rather than the transform of the model as a whole.

Yes, that's what I was saying, you're adding steps with potential error in them. Create a GameObject in the editor, place it as a child object of the object you put the PartTools exporter on, and name it something logical eg "raycastOrigin" - you can get the positional element of the gameObject (the Transform component) by using that FindModelTransform(gameObjectName) function. You can access that Transform component's very useful properties then, such as direction vectors and position.

Wow if that's what it does then it's named very weirdly. Because what you're describing would be better called a cylinder cast - a raycast with a diameter to it.

Not really. A cylindrical cast would have a "cap" at the beginning and the end, with the swept area looking more like a capsule. So you might call it a CapsuleCast... of course, that's actually a different thing.

can query the physics update time but not the FPS rate time, as the FPS rate is fluid anyway and depends on what's being executed)

Time.deltaTime gives you the time the last Update() took.

As I understand it, Unity enforces the FixedUpdate rate by aborting code partway through if it's taking too long.

Nah, the code will be completed just fine. It'll just cause lag if it takes longer than the update period. The behaviour you describe would be very... bad for Unity as an engine :P.

Link to comment
Share on other sites

Dude, no need to bite my head off. I'm just trying to help you solve your problem. You asked why the doc example doesn't specifically use FixedUpdate, and I answered that.

Sorry. Why I didn't think you were trying to answer that question, but instead were talking about what I described doing in my code, is because saying that putting the code in Update() is something that only "usually" works isn't really a good defense of what Unity did in their documentation.

It's just that it puts me in the uncomfortable position that in order to believe that raycasts are meant to go into FixedUpdate, I have to believe that the user community who says this are *better* informed about how Unity works than the very person (presumably who works for the company) who wrote Unity's own documentation. I know Unity's docs are bad but I thought they were only bad in the sense that there's a lot of omitted details, rather than being bad in the sense of including details that are wrong, which is even worse than omitting them.

Yes, that's what I was saying, you're adding steps with potential error in them.

I have zero doubt that there is no error in what I did there. Either the coordinate I hardcoded within the model space is in the right place or it's not. It's not going to be in the right place 70% of the time and the wrong place the other 30%.

That being said, if it can be embedded into the model file then it's a better place to put it not because of the claim that it's a potential place for the error I'm getting, nor because I am "adding steps", which I'm not, but to make it easier to keep things consistent when there's future changes to the model. The decision as to the shape of the model and the decision as to where to start the ray within the model's local coordinates would then be in the same place so the two decisions are edited adjacent to each other within the Unity editor. The reason to make the change is to accommodate future edits, not for the current problem which has nothing to do with it.

I'm not "adding steps" by doing the work of manually choosing a ray origin point outside the Unity editor instead of inside it. It's still a manual hardcoded decision either way. It's just better to make that decision in the same place as the place where the model is edited because then it's easier to notice that if one changes the other should be changed too.

(on spherecast/cylindercast)

(This isn't a disagreement with you, but with Unity for choosing terms that clash with each other.) Maybe I'm not making the clash clear. "Spherecast" is apparently being used by Unity to mean "extrude a shape along a line, and in this case the shape is a sphere. The resulting shape of the check ends up being a capsule". That makes it sound like the verb "to cast" means "extrude the named shape along a line to see what it hits". But that's utterly contradicted by the name "Raycast". If that was what "to cast" meant, then "Raycast" should have been called "pointcast" instead. It's a point, casted along a line, the result of which ends up being a ray in the end. If "cast" really meant "extrude along a line to see what it hits" then that would mean if you call something a "raycast" it would actually be half of a flat plane shape - a ray that's been extruded along a line.

That's why I was saying "spherecast" is the wrong term. Because the word "Raycast" has already established that when you say "FOOcast", the FOO in the word is describing the final shape the check will have, not the shape you're going to extrude to get the final shape. Looking at it that way, a "spherecast" would mean a sphere-shaped check, not a capsule-shaped check. Thus why I said "cylinder" was a better term. Granted, "capsulecast" is a better term than both cylindercast and spherecast, for the reasons you gave. But I'd say that between "spherecast" and "cylindercast", that "spherecast" is the one that's more incorrect. *if* "raycast" is a name that is taken as sacrosanct and needs to be left alone.

Alternatively the contradiction could be handled by going the other way and keeping the name "spherecast" but then changing "raycast" to "pointcast".

The contradiction is in whether "casting FOO" means to extrude the named shape FOO along a line as you check for intersections, or whether FOO is the description of the final shape itself, and 'cast' just means to check for intersections with the shape that was named FOO, as-is.

That contradiction is why I didn't get what "spherecast" meant. "Cast" in "spherecast" means something different to what "cast" in "Raycast" means, apparently.

Nah, the code will be completed just fine. It'll just cause lag if it takes longer than the update period. The behaviour you describe would be very... bad for Unity as an engine :P.

Then Unity's claim that it *reliably* runs FixedUpdates on a rigid schedule is a claim they really shouldn't be making. It is entirely at the mercy of all the MonoBehaviors in the whole game to make sure they run very fast short code. If Unity doesn't abort FixedUpdates that are taking too long, then it cannot claim to be certain about them being executed on a reliable timescale.

Edited by Steven Mading
Link to comment
Share on other sites

This thread is quite old. Please consider starting a new thread rather than reviving this one.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...