Raytracing/Gravity Script

I’m trying to work out a way to make it so that with a press of a button, the game will search the area that is above the player for a surface and then flip them around so that is the new floor. Basically, gravity flipping. This is easy if it’s just square rooms (just flip the sign of the gravity variable), but I don’t want to leave it at such a simple answer. Angled walls/ceilings should be workable as well. Aka:


-


----
-----
------
-------
----^—
----|----\ p = Player controller
p_\

The perferated slant should be a valid wall as well.

My idea of how to solve this was to use ray tracing to see what the surface above the player is like. I would send up three ray traces which form an equalateral triangle around the player.

----/
—/–
–/----\ Pretend this is even remotely close to being an equalateral triangle.
-/–p–
/_____\

The above picture is a top down view of the player. Each corner would be a ray trace going upwards. They each go up a certain amount and if ALL of them hit something, we start figuring out what angle faces out from that new triangle. This isn’t too hard. Create a vector that is from the midpoint of two of the hit points to the other part of the triangle.

-----v HERE
----/
—/–
–/----\
-/------
/_____
------^ Here

I get the angle between the two and then add 90 degrees to that and I have the new facing. From there, I just have to disable the player’s controls and then interpolate the movement and rotation of the player so that they will land facing the right direction.

So I THINK I have the basic idea, but I haven’t the slightest clue where to begin with coding this. I just started unity…12:00 this afternoon? I don’t really know the limits/abilities of Unity. Is this a feasible solution?

Also, I was looking at Physics.Raycast and it says that it needs two Vector3s, but the documentation says they are just vectors. If I have no idea where this should end, how do I tell it “above the player?” This has to work from any floor/wall/ceiling, so the global XYZ plain isn’t going to be sufficient. Is there an XYZ plain that follows the player specifically? Essencially, is there a way to get it so that Z is ALWAYS the direction that is above the player, no matter how much I rotate the player and screw with gravity?

I know this is a ton. Thanks for any help =)

EDIT:

Realized there’s an easier way to do it other than a triangle. Instead, it could just be two lines. One in back of the player and one in front. Basically, skip all the midpoint stuff.

Yeah, it’s reasonable.

What you want is called a cross product.

Your triangle idea is perfect, because you need TWO vectors for a cross product. And those two vectors can NOT be parallel (the cross product of parallel vectors is a zero vector… or infinite possibility).

When the cross product gives you is a ‘normal vector orthogonal (perpendicular) to both input vectors’.

cross product is not transitive, the order you do it in changes if the ‘normal’ will be facing out or in. This is actually how facing normals of a polygon works. When you create a polygon the vert order defines the vector order defines the cross product order defines the facing direction defines which side of the polygon receives the texture (unless you do double-sided that is).

so, lets say you have the 3 tri points A,B,C

Vector3 AtoB = (B - A).normalized;//make unit vector
Vector3 BtoC = (C - B).normalize;//make unit vector
Vector3 normal = Vector3.Cross(AtoB, BtoC);//get normal, this is the facing direction of the triangle

Here’s some info on cross product:

just remember that the facing direction depends on the order that you calculate the cross product. So if the gravity is ‘opposite’ of what you expect, just change the order of the cross product. To be consistent always cross in the same direction around the tri… counter-clockwise or clockwise.

An easy way to get three points for your triangle (and avoid mid-points and the sort).

ray 1 pos : player.transform.position
ray 2 pos : player.transform.position + player.transform.forward
ray 3 pos : player.transform.position + player.transform.right

for more accuracy you could even do it twice in a row, with the back and left as well. Getting two normal vectors. And if they’re different, just get the average between the two normals. This could happen when you’re standing between to polygons on a changing slope.