Jump to content

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


Dunbaratu

Recommended Posts

Unity's Physics.RayCast() doesn't seem very reliable when it comes to aiming the ray at ship parts. It works fine for ground terrain or KSC buildings, but when aimed at ship parts it works intermitently. Note, this is NOT (I don't think) a problem with the layers because it hits the SAME part for one or two Update()'s, then in the next update it passes right through it, then in the next Update() it hits it again, then a few updates later it starts passing through it again, and so on.

The problem seems more pronounced when the ship is in motion (I have a laser on the ship aiming at another part of the same ship to measure the distance between them as an Infernal Robotics part moves them farther apart, and when the ship takes off the erroneous "penetrating" raycasts start happening more frequently than when it was on the ground.)

I've tried googling about it and it seems to be that people have trouble with Raycast hitting moving parts and it has something to do with the exact timing of when you call Physics.RayCast(). I find people claiming it's better if you put Physics.RayCast() calls in FixedUpdate() instead of Update(), but that seems like a drastic measure as FixedUpdate is a precious resource I should avoid using, and the rest of my logic about what to do with the raycast is too "expensive" for FixedUpdate() and needs to stay in Update() so it's going to make the programming more complex if I putthe raycasts in FixedUpdate().

Does anyone have good experience with Physics.Raycast() hitting ship parts and know whether or not this claim is really true (that you need to put the raycasts in FixedUpdate() for them to work right?) That's a major undertaking to make that change for my mod and it would be horrible if I went through the work only to find its a red herring.

Unity's own docs for RayCast never mention this, but given the state of Unity's documentation, the fact that it never mentions it is hardly conclusive.

Link to comment
Share on other sites

Take this with a grain of salt as I have not actually run any tests of any sort, but I think you will have to move it to FixedUpdate.

The reasoning behind this is that anything to do with physics, in which I include Raycast, is supposed to happen on FixedUpdate as that is the "physics frame" as opposed to the "GUI overlay frame" that Update is.

Now, I've never been able to explicitly confirm this, but my take away from this is that outside of the FixedUpdate frame, the physics state of objects can not be guaranteed as you are between physics updates and there is no "physics cache" that I am aware of that would provide a guaranteed return to a physics call run outside the FixedUpdate frame.

I can't even think of a test that would reliably support this theory and I have only used RayCast once, but that was for terrain height and I specifically masked out the Parts layer so I would not get returns from Parts and so I had no chance of seeing this when I used it.

That's what I know for whatever value it has to you.

D.

edit: Heh, I got ninja'd. Still, more information never hurts.

Link to comment
Share on other sites

Okay thanks for the replies. I'll start looking into how to make the change. One of the reasons it's ugly is that my logic currently is this to decide if the laser hits something:

FIRST, try Physics.RayCast(). If that finds a hit on a terrain polygon or a ship part, then quit right there and return that, we're done.

SECOND, if Physics.RayCast() failed to find a hit, there might still be a hit far away because planetary terrain that's far from the camera isn't really fully rendered into polygons. It's sort of "holographic" in the sense that RayCasts pass through it. Therefore when Physics.RayCast() finds no hit, fall back on a numeric iterative solver algorithm that takes sample points along the ray to see when the ray first goes below the pqsController's reported terrain altitude for that spot, and where it does, iteratively narrow down with tighter and tighter sample points until the exact spot where it went underground is found.

As you can see that fallback algorithm in the second part is WAAAY too expensive to be doing inside FixedUpdate(). But the decision as to whether or not to do it depends on the result of the raycast in FixedUpdate. Since the ratio of number of FixedUpdate()'s to Update()'s is not 1:1, it may get slightly messy.

Do I have a guarantee that Update() and FixedUpdate() share the same thread, meaning that my Update() method can't be interrupted partway through by my FixedUpdate() method, or visa versa? If so, that would make it easier because then I can just remember the state of the most recent RayCast from FixedUpdate() and just look at it in Update().

Link to comment
Share on other sites

Do I have a guarantee that Update() and FixedUpdate() share the same thread, meaning that my Update() method can't be interrupted partway through by my FixedUpdate() method, or visa versa? If so, that would make it easier because then I can just remember the state of the most recent RayCast from FixedUpdate() and just look at it in Update().

I can't answer your thread question directly, but I will confirm that I just remembered the state of the previous ray to transfer the result from FixedUpdate to Update. In my case all I was transferring was a float for the distance the ray hit but the same logic should work for the data you are also trying to transfer. (I just declared a variable at the class level outside of Update and FixedUpdate and they referenced the variable as needed to read/write it.)

D.

Link to comment
Share on other sites

While working on BDArmory, I ran into a few problems with moving objects. If an object is moving quickly, and you are trying to get it's position, sometimes you have to do something like


target.transform.position + (target.rigidbody.velocity * Time.fixedDeltaTime)

If you set up a LineRenderer to give you a visual of where your Raycast is going, you will see that the faster an object is moving, the further behind "transform.position" is from the object. Adding its delta position over the last physics time step (velocity * fixeddeltatime) corrects for this error.

In some cases, the position is one timestep ahead of where the object actually is, and I would have to subtract the error. (Getting bullets to spawn at the tip of a barrel in BDArmory). This is less often the case though.

-Edit: I just remembered that this was because the spawned object had a high velocity. You wouldn't have to worry about this in your situation.

While working on CameraTools, I found that pointing something (a camera in that case) at a moving target in Update() results in alot of stuttering, and it had to be in FixedUpdate() with the aforementioned error compensation to get it to point directly at the target.

I don't know if this is what your problem is, but I hope it helps.

Edited by BahamutoD
Link to comment
Share on other sites

While working on BDArmory, I ran into a few problems with moving objects. If an object is moving quickly, and you are trying to get it's position, sometimes you have to do something like


target.transform.position + (target.rigidbody.velocity * Time.fixedDeltaTime)

If you set up a LineRenderer to give you a visual of where your Raycast is going, you will see that the faster an object is moving, the further behind "transform.position" is from the object. Adding its delta position over the last physics time step (velocity * fixeddeltatime) corrects for this error.

But how on earth do you know in software which of these situations you're in? I can tell visually by looking of course, but how does the code know whether or not it's the right situations to add the velocity offset or not? is there a cutoff speed where the effect becomes needed?

I tried moving the logic into FixedUpdate and it was drawing the ray in the wrong spot, well offset from the position of the ship. When I have it in Update() it draws in the right spot, but passes through things. When I put it in FixedUpdate, it's not even drawn in the right spot.

Link to comment
Share on other sites

I've tried googling about it and it seems to be that people have trouble with Raycast hitting moving parts and it has something to do with the exact timing of when you call Physics.RayCast(). I find people claiming it's better if you put Physics.RayCast() calls in FixedUpdate() instead of Update(), but that seems like a drastic measure as FixedUpdate is a precious resource I should avoid using, and the rest of my logic about what to do with the raycast is too "expensive" for FixedUpdate() and needs to stay in Update() so it's going to make the programming more complex if I putthe raycasts in FixedUpdate().

I don't think whatever you will be doing will impact the game that much honestly. Every bullet in skillful has a raycast that checks for missed collisions, and there can be literally hundreds at once. All my raycasts are in FixedUpdate and only things like keypresses are in Update.

With the raycasting issue. Not sure what it could be other than perhaps an issue with specific parts which use compound colliders instead of a solid convex mesh collider. But it's more likely from using the raycast in Update.

Perhaps something is in the way of the raycast and it's not able to complete the journey to the target part. Are you logging all the hits so you can see what it's doing? There is also RaycastAll wherein you can save all raycast hits to an array.

//The following code is not 100% correct I'm sure there are typos!

public RaycastHit[] allHits;

//then the raycast

for (var i = 0; i < allHits.length; i++) {for(int i = 0; i < allHits.Length; i++)

{

if (Physics.RaycastAll(firedFromHere, rayDirection, allHits))

{

if(allhits.collider.gameobject.part != null)

{

Debug.Log(allhits.part.name);

}

}

}

Or some such thing... at least then you know what you're hitting. You could even specify that it not look at hits from the part firing the raycast this way. Anyways I also hope this helps in some way, the only real way to do it is with lots of logging, trial and error, etc.

Good luck! :)

Edited by InfiniteDice
Link to comment
Share on other sites

I don't think whatever you will be doing will impact the game that much honestly. Every bullet in skillful has a raycast that checks for missed collisions, and there can be literally hundreds at once. All my raycasts are in FixedUpdate and only things like keypresses are in Update.

Does the drawing of the ray, if I'm showing it visually with a red lineRenderer, have to also be in FixedUpdate? I think the problem may be that. When I raycast in FixedUpdate and then draw the result, the drawing is really far off, appearing about 20 meters ahead of the craft as it orbits, making it very hard to debug what I'm looking at. But then again I'm tying to raycast in FixedUpdate and then Draw in Update.

I think I can do it but the logic is messy because of the fallback to a slow numeric algorithm when the terrain is too far away for raycasts to work (the game unloads the polygon colliders when the terrain is more than about 10-20 km away or so). What I'm trying to do is basically this:

MyRayCastWrapper( stuff );

DrawRay();

Where MyRayCastWrapper( stuff ) is doing the following:

Step 1 - Try Physics.Raycast to hit ground or ship objects near enough to have loaded colliders.

Step 2 - If Step 1 returned false, then fall back to my own homebrewed numeric algorithm to find terrain hits with the distant planet surface by querying the pqsController.

The ugly part is that although Step 1 and the ray drawing may both be fast enough to put in FixedUpdate, there's that annoying Step 2 which really shouldn't be in FixedUpdate because it's computationally expensive, and yet it happens *between* Step 1 and the drawing of the ray. I could wait and draw the ray later but then it's being drawn in the wrong animation frame and thus in the wrong spot.

I think it's doable but messy. I may have to disable the numeric solver, get the solution working for just raycast only, and then work out how to re-enable the numeric solver in the new way the code looks after that.


for (var i = 0; i < allHits.length; i++) {for(int i = 0; i < allHits.Length; i++)
{
if (Physics.RaycastAll(firedFromHere, rayDirection, allHits[i]))
{

That really looks like it's in the wrong order around. Are you sure I'm supposed to be checking how many alllHits there were and THEN for each one of them be calling Raycast on them? Doesn't the raycast come first and allhits isn't even populated until it's been called?

Link to comment
Share on other sites

Okay this is really getting quite infuriating. (Dealing with the API, not you guys. You've been very helpful but the game just isn't cooperating.)

See the screenshots below. The laserbeam keeps toggling between giving a hit of 1.78 meters intersecting the structuralBeam3, versus giving a hit of 3.32 meters intersecting the landingLeg1-2 that's beyond it. Every few updates it flips between these two answers.

The craft is sitting still on the ground. Not Moving. When the laser does miss the 1.78 hit and pass through to the 3.32 hit, I can see clearly the beam passing right through the middle of the closer object, incorrectly failing to detect the hit.

xwH70OA.png

mIB8omX.png

This is the relevant code:


/// <summary>
/// Perform Unity's Physics.RayCast() check when the movement of all the objects is set in stone and they are not moving:
/// Physics.RayCast() is unreliable when called from Update() because objects are moving their positions during their
/// Update()'s and you don't know when during the order of all that your own Update() will be getting called. Therefore
/// Physics.Raycast() has to be called during FixedUpdate.
/// </summary>
public void FixedUpdate()
{
// The location of origin is different in FixedUpdate than it is
// in Update, so it has to be reset in both:
origin = this.part.transform.TransformPoint( relLaserOrigin );
pointing = this.part.transform.rotation * Vector3d.down;

mostRecentUnityRaycastSuccess = false;

if( hasPower && Activated && origin != null && pointing != null)
{
RaycastHit[] hits = null;
hits = Physics.RaycastAll( origin, pointing, MaxDistance, mask );
Debug.Log("num hits = " + hits.Length );
if( hits.Length > 0 )
{
mostRecentUnityRaycastSuccess = true;
float bestDist = Mathf.Infinity;
foreach( RaycastHit hit in hits )
{
Debug.Log("hit.distance = " + hit.distance + ", bestDist = " + bestDist);
if( hit.distance < bestDist )
{
Debug.Log("using new hit.");
bestDist = hit.distance;
mostRecentUnityRaycastResult = hit;
}
}
}
}
}

See the Debug.Log statements? This is what they're showing in the log:

(I've removed all the verbose "(Filename: ....)" lines to make the log clearer to read.)


num hits = 3
hit.distance = 6.966611, bestDist = Infinity
using new hit.
hit.distance = 3.787935, bestDist = 6.966611
using new hit.
hit.distance = 3.323033, bestDist = 3.787935
using new hit.
num hits = 4
hit.distance = 6.966611, bestDist = Infinity
using new hit.
hit.distance = 3.787934, bestDist = 6.966611
using new hit.
hit.distance = 1.778339, bestDist = 3.787934
using new hit.
hit.distance = 3.323035, bestDist = 1.778339
num hits = 4
hit.distance = 6.966611, bestDist = Infinity
using new hit.
hit.distance = 3.787933, bestDist = 6.966611
using new hit.
hit.distance = 1.778339, bestDist = 3.787933
using new hit.
hit.distance = 3.323039, bestDist = 1.778339
num hits = 3
hit.distance = 6.966611, bestDist = Infinity
using new hit.
hit.distance = 3.787933, bestDist = 6.966611
using new hit.

It seems entirely outside my ability to control it - it just sometimes fails to include the structureBeam3 among the hits, even though I'm not doing anything different. And it seems to randomly flip between finding it and not finding it based on who knows what. I'm tempted to punt and just tell people "sometimes it will fail to hit parts and there's nothing I can do about it."

Link to comment
Share on other sites

Okay this is really getting quite infuriating. (Dealing with the API, not you guys. You've been very helpful but the game just isn't cooperating.)

See the screenshots below. The laserbeam keeps toggling between giving a hit of 1.78 meters intersecting the structuralBeam3, versus giving a hit of 3.32 meters intersecting the landingLeg1-2 that's beyond it. Every few updates it flips between these two answers.

The craft is sitting still on the ground. Not Moving. When the laser does miss the 1.78 hit and pass through to the 3.32 hit, I can see clearly the beam passing right through the middle of the closer object, incorrectly failing to detect the hit.

xwH70OA.png

mIB8omX.png

This is the relevant code:


/// <summary>
/// Perform Unity's Physics.RayCast() check when the movement of all the objects is set in stone and they are not moving:
/// Physics.RayCast() is unreliable when called from Update() because objects are moving their positions during their
/// Update()'s and you don't know when during the order of all that your own Update() will be getting called. Therefore
/// Physics.Raycast() has to be called during FixedUpdate.
/// </summary>
public void FixedUpdate()
{
// The location of origin is different in FixedUpdate than it is
// in Update, so it has to be reset in both:
origin = this.part.transform.TransformPoint( relLaserOrigin );
pointing = this.part.transform.rotation * Vector3d.down;

mostRecentUnityRaycastSuccess = false;

if( hasPower && Activated && origin != null && pointing != null)
{
RaycastHit[] hits = null;
hits = Physics.RaycastAll( origin, pointing, MaxDistance, mask );
Debug.Log("num hits = " + hits.Length );
if( hits.Length > 0 )
{
mostRecentUnityRaycastSuccess = true;
float bestDist = Mathf.Infinity;
foreach( RaycastHit hit in hits )
{
Debug.Log("hit.distance = " + hit.distance + ", bestDist = " + bestDist);
if( hit.distance < bestDist )
{
Debug.Log("using new hit.");
bestDist = hit.distance;
mostRecentUnityRaycastResult = hit;
}
}
}
}
}

See the Debug.Log statements? This is what they're showing in the log:

(I've removed all the verbose "(Filename: ....)" lines to make the log clearer to read.)


num hits = 3
hit.distance = 6.966611, bestDist = Infinity
using new hit.
hit.distance = 3.787935, bestDist = 6.966611
using new hit.
hit.distance = 3.323033, bestDist = 3.787935
using new hit.
num hits = 4
hit.distance = 6.966611, bestDist = Infinity
using new hit.
hit.distance = 3.787934, bestDist = 6.966611
using new hit.
hit.distance = 1.778339, bestDist = 3.787934
using new hit.
hit.distance = 3.323035, bestDist = 1.778339
num hits = 4
hit.distance = 6.966611, bestDist = Infinity
using new hit.
hit.distance = 3.787933, bestDist = 6.966611
using new hit.
hit.distance = 1.778339, bestDist = 3.787933
using new hit.
hit.distance = 3.323039, bestDist = 1.778339
num hits = 3
hit.distance = 6.966611, bestDist = Infinity
using new hit.
hit.distance = 3.787933, bestDist = 6.966611
using new hit.
hit.distance = 3.323033, bestDist = 3.787935
using new hit.

It seems entirely outside my ability to control it - it just sometimes fails to include the structureBeam3 among the hits (returning a list of only 3 hits, not the correct 4 hits), even though I'm not doing anything different in that particular update. And it seems to randomly flip between finding it and not finding it based on who knows what. I'm tempted to punt and just tell people "sometimes it will fail to hit parts and there's nothing I can do about it."

Edited by Steven Mading
tail end of my output log was cut off.
Link to comment
Share on other sites

Did you test this with other parts? Not all parts are created equal unfortunately. That could have a few collider boxes in the sides, and nothing where you are shooting the ray at. I'm not saying that's what's happening but just to eliminate that possibility try doing the test on 4 totally different parts with different part shapes.

About the code yes it's a$$ backwards I knew I'd mess it up but I think you understood it anyways. And yes I'd put all of it in FixedUpdate(), get your fps with and without your code running, I don't think you'll see much of a difference.

Link to comment
Share on other sites

Did you test this with other parts? Not all parts are created equal unfortunately. That could have a few collider boxes in the sides, and nothing where you are shooting the ray at. I'm not saying that's what's happening but just to eliminate that possibility try doing the test on 4 totally different parts with different part shapes.

About the code yes it's a$$ backwards I knew I'd mess it up but I think you understood it anyways. And yes I'd put all of it in FixedUpdate(), get your fps with and without your code running, I don't think you'll see much of a difference.

I will if I include the fallback pqs technique in fixedupdate. If all I do is the raytracing it's fast enough in fixedupdate. If I run a recursive iterator that has to take about 500 loop iterations to get down to an answer within 2m of accurate because the only way to detect terrain hits at long distances is to test sample points along the ray, then it won't. I already know it's not even fast enough for plain ole Update(). I had to split the algorithm up across multiple updates, remembering state between them to get acceptable FPS. Note, that's even BEFORE I moved any of it to fixedupdate. The problem of finding the solution of the intercept of a ray with the pqs terrain is NOT a trivial calculation. It requires itrerative approximation.

That's why I have to have half the logic (the stuff using Physics.RayCast) in fixedUPate and the other half (the fallback to pqsCOllider) in Update().

But that's not even related to my problem. Even when dealing with JUST nearby objects using JUST Physics.RayCast in JUST FixedUpdate, Unity is returning inconsistent results where in one FixedUpdate it will hit the part and in the next one it will pass through it to the part behind it *even when nothing moved*.

I suspect that what's happening is that because I get FixedUpates more frequently than Updates, that not all the movement and recalculation of all the KSP parts is finished between fixedUpdates. There is no guarantee that Unity gets its way through ALL the parts' Update()s before the next FixedUpdate. So some have moved and others haven't yet. That's my guess.

As to changing parts - again it's reliably inconsistent - any part has the effect that it tends to pass right through about 1/3 of the time in FixedUpdate.

I've tried falling back on an ugly amount of work to compensate for it - I only need the information up to date once per Update, not once per FixedUpdate - so I'm trying to gather ALL the hits of ALL the fixed Updates that happened between Update()s, and then when the Update() runs, taking the nearest hit among ALL of them. that way as long as it hits the object on at least ONE of the FixedUpdates I don't care that it missed on others. It has to miss on all of them to be a real miss.

Link to comment
Share on other sites

Seems like you know you're stuff. So if 1 in 3 is a fail, why not double up the rays and have 1 in 6 fail. What is an acceptable level of loss? I've fired tons of rays and I don't see 1 in 3 misses even when the bullet is going 1200 m/s. Though if you are scanning something in orbit --> stationary the velocities could be much higher, at that point I can't attest as it is logical that it may be incapable of that accuracy.

I do a raycast lookback on all my bullet rigidbodies, essentially the raycast looks at the step in motion between frames and sees if there was a missed collision. It seems reliable to me (again at up to 1200 - 1300 m/s - I don't require faster than that).

Vector3 movementThisStep = rb.position - previousPosition;

float movementSqrMagnitude = movementThisStep.sqrMagnitude;

if (movementSqrMagnitude > sqrMinimumExtent && doDetectMiss == true)

{

float movementMagnitude = Mathf.Sqrt(movementSqrMagnitude);

RaycastHit hitInfo;

if (Physics.Raycast(previousPosition, movementThisStep, out hitInfo, movementMagnitude, 1))

{

rb.position = hitInfo.point - movementThisStep / movementMagnitude * partialExtent;

lastGoodHitInfo = hitInfo.point;

//rb.position = hitInfo.point - (movementThisStep / movementMagnitude) * partialExtent;

}

}

You're not tracking a physical position over time, you're doing an instantaneous ray. So I realize this might be useless, but it could trigger an idea for you...

There is also something here, about calling from Update but waiting for the FixedUpdate.

http://forum.unity3d.com/threads/moving-colliders-and-raycasts.201740/

Again might not be relevant other than to perhaps trigger an idea.

Edited by InfiniteDice
Link to comment
Share on other sites

Seems like you know you're stuff. So if 1 in 3 is a fail, why not double up the rays and have 1 in 6 fail. What is an acceptable level of loss? I've fired tons of rays and I don't see 1 in 3 misses even when the bullet is going 1200 m/s. Though if you are scanning something in orbit --> stationary the velocities could be much higher, at that point I can't attest as it is logical that it may be incapable of that accuracy.

I do a raycast lookback on all my bullet rigidbodies, essentially the raycast looks at the step in motion between frames and sees if there was a missed collision. It seems reliable to me (again at up to 1200 - 1300 m/s - I don't require faster than that).

Vector3 movementThisStep = rb.position - previousPosition;

float movementSqrMagnitude = movementThisStep.sqrMagnitude;

if (movementSqrMagnitude > sqrMinimumExtent && doDetectMiss == true)

{

float movementMagnitude = Mathf.Sqrt(movementSqrMagnitude);

RaycastHit hitInfo;

if (Physics.Raycast(previousPosition, movementThisStep, out hitInfo, movementMagnitude, 1))

{

rb.position = hitInfo.point - movementThisStep / movementMagnitude * partialExtent;

lastGoodHitInfo = hitInfo.point;

//rb.position = hitInfo.point - (movementThisStep / movementMagnitude) * partialExtent;

}

}

You're not tracking a physical position over time, you're doing an instantaneous ray. So I realize this might be useless, but it could trigger an idea for you...

Have you tried using the algorithm to just fire a bullet through just one thin part rather than through a ship made of multiple parts? It might be that as long as you hit one of the parts of the ship it's a success, whereas I need to hit the *correct* part of the ship to be a success. If I hit the fuel tank in the middle even though there was a panel part in front of it that I should have hit first, then that's a "fail" by my criteria. For firing a bullet to hit a ship, hitting the tank instead of the panel would still look like a good success for your needs. I don't know.

It could also be a very ugly timing issue. It might be that it depends on how many Update()'s happen versus how many FixedUpate()'s happen, and computer speed changes whether or not a full suite of Update()s happen and finish on time before a FixedUpdate().

There is also something here, about calling from Update but waiting for the FixedUpdate.

http://forum.unity3d.com/threads/moving-colliders-and-raycasts.201740/

Again might not be relevant other than to perhaps trigger an idea.

I read that thread before on my previous googling. Sadly, some of the advice is about what order I should be updating the position of "my" objects in, as if I was writing my own Unity game from scratch and had the privilege to do that. This isn't useful in the context of a KSP mod because I'm not in charge of deciding when to update and draw the ship parts, SQUAD is in their proprietary code that I don't know how it was written. And the rest of the advice is quite different because it talks about drawing a raycast from the camera, which I'm not doing.

Sadly I'm suspecting that what's actually happening here is that SQUAD's own code is updating parts in such a way that it's not working right when trying to hit thin parts.

It might explain also why it is that the main game itself has such a hard time with right-clicking on parts working to bring up the menu. That user interface is ALSO dependant on raycasting and it also seems to fail about half the time when I try to click on parts. I have to keep re-trying until I get lucky enough to get it to work.

Link to comment
Share on other sites

Have you tried using the algorithm to just fire a bullet through just one thin part rather than through a ship made of multiple parts? It might be that as long as you hit one of the parts of the ship it's a success, whereas I need to hit the *correct* part of the ship to be a success. If I hit the fuel tank in the middle even though there was a panel part in front of it that I should have hit first, then that's a "fail" by my criteria. For firing a bullet to hit a ship, hitting the tank instead of the panel would still look like a good success for your needs. I don't know.

Yes I can hit small colliders 0.05 thickness at ~1200 m/s +/- using that method. I don't really know your parameters and tolerances you need. ie: If I stack 4 panels on top of one another, I can kill them in order they are stacked top-down.

I think you are already doing something like this... make a ray cast over consecutive fixedupdates, save the results of the raytrace only if it hits that part (if you know the part it's going for) if not, you'd need to also save the (hitpart.name or hitpart.partname - can't remember which is unique) to cross reference later.

After say 3 or 4 fixedupates then update/output the result. If there is no data on one of the scans, it either doesn't factor into the calculation or add the average of the remaining valid hit returns. Then average it again....

So on the click/activation, have the raytrace fire over 3 fixedupdates. This way given your 1 in 3 failure rate you should have at least one number to return.

Edited by InfiniteDice
Link to comment
Share on other sites

Actually, while this is not a solution it will at least help you narrow it down.

Within the same FixedUpdate frame, fire the same ray 5 times. By that I mean fire 5 different rayCast objects, but use exactly the same values.

When you get a miss result, do all 5 rays return a miss? The issue probably lies somewhere in the Parts and how KSP handles them.

Do some rays return good and some return bad? The issue is in rayCast itself somewhere, or a timing issue of some sort.

Can't test this myself as I'm on my mobile but it would narrow down what the actual issue is.

D.

Link to comment
Share on other sites

Actually, while this is not a solution it will at least help you narrow it down.

Within the same FixedUpdate frame, fire the same ray 5 times. By that I mean fire 5 different rayCast objects, but use exactly the same values.

When you get a miss result, do all 5 rays return a miss? The issue probably lies somewhere in the Parts and how KSP handles them.

Do some rays return good and some return bad? The issue is in rayCast itself somewhere, or a timing issue of some sort.

Can't test this myself as I'm on my mobile but it would narrow down what the actual issue is.

D.

I think what he mentioned is that sometimes the position shift during update translates into an automatic miss with any raycast in the FixedUpdate. If that's the case it might not matter how many he uses in the same FixedUpdate. But he'd be more suited to be the judge of that as he's the one knee deep :)

Link to comment
Share on other sites

From my reading of the thread, it seems to be unclear what the cause of this issue is.

I posted that because I believe that if all 5 rays cast in the same frame miss, that means KSP is doing something behind the scenes and so is nothing that we as modders can affect and so we are stuck with it.

If only some of the rays miss, that implies the issues lies in the raycast function or in the timing of Update/FixedUpdate and may be something we can affect. (Or may not, further testing required.)

D.

Link to comment
Share on other sites

So here's some things to try:

  1. Is the behaviour the same with Physics.Raycast() as well as Physics.RaycastAll()? In the past I've had issues with RaycastAll() in my own Unity projects.
  2. Try using Physics.Spherecast() with an appropriate radius, which does what you'd expect it to (raycast with a sphere instead of a point). It's more expensive, but it should get you an idea of what's going on. If you're thinking that there is positional jitter that is causing your error, using a Spherecast will help determine that - if it is hitting but the raycast isn't, there's a small jitter involved. If it's still not hitting
  3. I don't know exactly how the methods you're using to get your laser aim start point and direction are working exactly, but it seems like a far easier way would be to place a transform in your model file (placed and oriented as your laser origin), get it via a standard method, and just use that transform's position and forward parameters to aim the beam. I'm not sure why you're doing otherwise, but as you're raycasting within KSP's physics bubble against things inside the physics bubble, you shouldn't need to do much else. If all else fails, you should try this.
  4. Related to point 3, how are you drawing your LineRenderer (I don't see it in your code)?

Edited by Nertea
Link to comment
Share on other sites

From my reading of the thread, it seems to be unclear what the cause of this issue is.

I posted that because I believe that if all 5 rays cast in the same frame miss, that means KSP is doing something behind the scenes and so is nothing that we as modders can affect and so we are stuck with it.

Sadly, the problem is that you're half right but not 100% right. I get much better results by taking the best hit of all the FixedUpdate raycasts that happen between Update()s, but sadly not 100% perfect results. It still occasionally takes more FixedUpdate()'s to find the hit than are happening between Update()s. And it's not a fixed number of fixedUpdates. Sometimes 2 FixedUpdates is enough to guarantee finding a hit among them. Sometimes it occasionally takes 3 or 4 to get to one where there's a hit. When I say it fails about 1/3 of the time I don't mean that it's perfectly interleaved, as in success, success, failure, success, success, failure, success, success, failure. Sometimes it's more like this:

success, success, success, success, success, failure, success, failure, success, success, success, failure, failure, failure, success, success, success, success. I..e an *average* of 2/3 success, but not nicely interleaved as 2 success, 1 fail, 2 success, 1 fail. During the bits where there's multiple failures in a row, I end up still returning a failure overall to the Update() because none of the FixedUpates() that occurred in that chunk found the hit.

Edited by Steven Mading
Link to comment
Share on other sites

So here's some things to try:

[*]Is the behaviour the same with Physics.Raycast() as well as Physics.RaycastAll()? In the past I've had issues with RaycastAll() in my own Unity projects.

yes. I was using Physics.RayCast() first and then changed to using Physics.RaycastAll() later to see if it would help. Both had the same problem.

[*]Try using Physics.Spherecast() with an appropriate radius, which does what you'd expect it to (raycast with a sphere instead of a point). It's more expensive, but it should get you an idea of what's going on. If you're thinking that there is positional jitter that is causing your error, using a Spherecast will help determine that - if it is hitting but the raycast isn't, there's a small jitter involved. If it's still not hitting

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".

[*]I don't know exactly how the methods you're using to get your laser aim start point and direction are working exactly, but it seems like a far easier way would be to place a transform in your model file (placed and oriented as your laser origin), get it via a standard method, and just use that transform's position and forward parameters to aim the beam. I'm not sure why you're doing otherwise, but as you're raycasting within KSP's physics bubble against things inside the physics bubble, you shouldn't need to do much else. If all else fails, you should try this.

That's what this is:


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

[*]Related to point 3, how are you drawing your LineRenderer (I don't see it in your code)?

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.

Link to comment
Share on other sites

Also, one thing I'm suspicious of is that despite the fact that everyone in the Unity user community says to perform the raycasts in FixedUpdate(), Unity's OWN online documentation examples always show it being done in Update(). Granted Unity's documentation is horrible so it could be wrong, but it does make me suspicious.

See this: http://docs.unity3d.com/ScriptReference/Physics.Raycast.html

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...