How could I find out if an objects vector3 hits between 2 points without raycasting in a 3D game?
Hello,
I'm making this system in unity which basically involves these transform objects that make up these splines/paths. The player object may be in front of or behind these splines and can be placed on the spline based on if the player finds these transform nodes in an overlap boxcast. However, the issue comes into play when I try to test if this vector3 that comes off the player is hitting these nodes. Basically there's this imaginary line (That's not a raycast because the Unity API doesn't support line colliders in 3D), that is say infinite or just really long, I want to basically figure out if this imaginary line hits somewhere on the lines between each of these transform points. What kind of math or part of the API is involved to make this calculation work?
The pic below shows that the player is on this other spline. This line comes off the player and goes into the BG when some nodes show up in the overlap Box. What I'm trying to find is that the player is able to find that the forward line hits between Node A and Node B. This cannot be achieved with a raycast so I need to basically get the position (Node B - Node A) and then find that the forward line hits that range and return that point. Thoughts?
Example,
Answer by streeetwalker · Sep 22, 2020 at 02:50 PM
OK, at this site: http://geomalgorithms.com/a05-_intersect-1.html you'll find a C++ that determines the intersection of a plane and a line segment. (look for the function "intersect3D_SegmentPlane()"
The code is easy to convert to C# - took me just a few minutes. I've tested it and it works perfectly no matter how you rotate the player.
The basic idea is to define a plane that is aligned with the player's forward and up direction (YZ Plane) and passes through the player. ( using the players transform.right and the players position - a plane can be defined by a point on a plane and a normal vector to the plane ).
Then you can use the code to determine if the plane intersects a line segment defined by the points on your spline, and if it does get the point of intersection. If you have multiple spline segments to check, you can iterate over them and call the function for each.
To implement the code, I created a class variable to hold the intersection point if there is one - you see the C++ code uses a variable pointer as a parameter for the function - I didn't remember how to do that in C# so I took the easy way out.
The function returns 1 if there is an intersection, 2 if the line is in the plane, and a 0 if there is no intersection. The image above shows my test in the editor, using OnDrawGizmos to draw the line segment between two empty transforms, and a sphere for the point of intersection (all in red).
First I call the function and get the return value, and if it is a 1 then I know the class variable holds the intersection point.
How do you represent the params in your C# script (specifically Segment)? Also in converting it to C#, should Vectors be Vector3 in the representation?
Well you could define a data structure to hold both points for the segment and the plane, like they did in C++, but i just split them up. It's more efficient to split them up - It is slower to pack your data into a structure and then dereference its members when you need to get at them later. (For the plane, I guess I could have just passed the player transform, because all of the information to define the plane is in that.)
Yes, vector in C++ is Vector3.
Here is my function declaration:
GetSegmentIntersectPlane( Vector3 p0, Vector3 p1, Vector3 planePoint, Vector3 planeNormal )
There is also a way to mimic the variable pointer 'I' from the script, but I don't recall in C# - maybe 'out' before the parameter name? I just skipped looking that up and set a Vector3 class variable in 2nd to last line of the function code, like this:
intersectionPoint = p0 + sI * u; // compute segment intersect point
Also note in c++, 'fabs' is '$$anonymous$$athf.Abs' and I think the S$$anonymous$$ALL_NU$$anonymous$$BER should probably be 0.000001f - a c# float gets 7 decimal digits at maximum.
One last note: this function will report an intersection even if the point is behind your player. I didn't do this in my code, but You will probably want to add an extra if statement either in the function or after you get the intersectionPoint outside the function that tests the Vector3.Dot product of your players forward vector and the intersectionPoint. If the result is negative then you know the intersection point is behind the player.
Your answer
Follow this Question
Related Questions
Trying match Unity Animation Curve with Hermit Spline. Ger Weird behaviour.... 0 Answers
Unity Math is Wrong for Some Reason 0 Answers
How can I detect a collision between any 2 points of a path/spline? 1 Answer
Making joint aim in the same direction as the main camera, regardless of joint axis 0 Answers