How to get angle of elevation relative to the world?

–PROBLEM–

Howdy, lets say that a plane constantly changes its tilt up or down. How would I be able to find the angle of elevation given the length of the plane relative to the world, no matter the orientation of the plane.

image
(The wanted angle would be in degrees)


–SOLUTIONS I’VE TRIED–

  • DOT PRODUCT
    I’ve tried using dot product, but given that there is no fixed length for the opposite and adjacent angle as the plane would be constantly changing its tilt, it hasn’t work for me at least on how I implemented it.
    image
    (platform is the plane part)

  • RAY CASTING
    I’ve also thought of using ray casting but I feel like there is a better way than ray casting since there can be many edge cases that go along with it, for example what if the plane is not over a part, or what if the plane casts a ray that is thousands of studs away.
    This post on finding an angle of a wedge part has a somewhat similar approach to what I want to accomplish, but given that it’s ray casting, it won’t work for me.
    (if for some reason nothing else works, I will have to resort to ray casting)

  • RELATIVE TO A PART, NOT THE WORLD
    Another solution I have been given, but wouldn’t work for me is this:
    image
    Given that there wouldn’t be a “v2” and it would only be relative to the world, I couldn’t find a way to reshape the formula given to fit my case.

  • TO EULER ANGLES / TO ORIENTATION
    Just to add to the pile of solutions give than haven’t worked, I was suggested on using:
    image
    This didn’t work as it gave me the X and Z, which is not what I wanted, only the angle.


Any way to solve this would be greatly appreciated!

2 Likes

That shouldn’t matter.

You almost had it with your first try.

image

I added a green :green_square:vector that has a different length but same direction as the hypotenuse / span of the plane. It’s clear from the drawing that it has the same angle. So any vector that has the same direction as the plane will do. The perfect vector for this is its LookVector. This will also work no matter what pitch, yaw or roll the plane has, so in all situations. Except maybe if the plane is upside down? Depends which angle you’d want in that situation.

I also added the purple UpVector :purple_square: to the drawing to illustrate why your first attempt wouldn’t have worked - you’re trying to get the angle between two vectors that are always going to be perpendicular, so that can’t be the right solution. And an orange :orange_square: arrow that represents “horizontal”, or “no pitch / aoe”). This is going to change with the yaw, so we have to get it from the CFrame of the plane.

Anyway, here’s how you get the angle:

local elevation_angle
local facing = Platform.CFrame.LookVector
local horizontal_facing = (facing * Vector3.new(1, 0, 1)) --Remove the vertical component

if horizontal_facing.Magnitude == 0 then
    --If the plane is straight up/down, handle degenerative cases
    if facing.Y > 0 then
        elevation_angle = math.pi/2
    else
        elevation_angle = -math.pi/2
    end
else
    elevation_angle = math.acos( facing:Dot(horizontal_facing) )
end

It’s really a one-liner at the bottom of the code, but I included some logic for checking if the plane is going straight up/down, in which case horizontal_facing would be (0, 0, 0), and facing:Dot(horizontal_facing) would be undefined and the elevation_angle would be NaN because of division with 0 IIRC.

If you want some more info about how the math works, check out this: Best way to get the angle between two vectors?

4 Likes

Wow, thanks! Will definitely be trying it out!

58229bcaafa7c72abb94c521f42b9084

Perfection!
Here I used it on my car system which now tells what the angle of the slope the car is on now!

You can also use Orientation if you want to.