How to Gliding Mechanics / Velocity Relative to Angle

Hey, so once again I’m coming to you guys, the intellectuals of ROBLOX for help.

If you guys have ever played Batman Arkham Knight, you’d know about their gliding mechanic as seen here:

and I had an idea, to implementing it, I decided that I would have a BodyVelocity relative to the HumanoidRootPart and have a set Magnitude that multiplies the LookVector for Velocity. (Done)

then I decided I’d rotate the HumanoidRootPart based on the Camera’s LookDirection (Done)

and now all I had to do was make the gliding realistic…

I wanted to decrease the magnitude over time, to simulate drag and then I wanted to have the magnitude also be edited based on the Angle of direction, so like when the Camera looks up the Magnitude is decreased, but when looking down it increases… that kind of thing to get that whole stalling and diving effect…

My problem is I don’t know the math behind this, I have the logic and idea for it down ( I think ) but the math behind it is kind of beyond me, can someone explain how this would be accomplished in mathematical terms?

4 Likes

Look into the Dot products its a scalar representing the similarity between two vectors.

Use it on 2 unit vectors and you can determine how much of one vectors composition is in the direction of another.

But for this application you should only need the portion relative to worldspace(0,-1,0) which is conveniently your Y component of the look vector
so you can

local perDown = lookVector.Y / lookVector.Mag
speed = baseSpeed*(1-perDown)

perDown is never more than 1
and if its negative (Y being negative) it adds to speed
if positive subtracts from speed

Going straight up makes your speed 0
and going straight down doubles your speed

4 Likes

so i’ll have to do

local LookVector = (Vector3.new(0, -1, 0):Dot(Camera.CFrame.LookVector))
local perDown = lookVector.Y / lookVector.Mag
speed = baseSpeed*(1-perDown)

or is that not how it works? Sorry I’m not the best at math :smile: yet

Edit:

Okay so I just tested it out and it works, I’m mind blown I can’t figure out why it works, I always have these why questions and why something works the way it does and I always get confused when trying to solve these questions if you know what I mean.

You don’t need to dot anything for your use, I showed you the math so you could expand your uses if you want.

What you are looking for is purely the downward magnitude of your movement(which is your lookVector direction)

This is just your (x, y, z) Y part of the vector
+ is up
- is down

So you take that Y part and divide it by the total size which is the .Mag
That gives you the percent of movement that is downward.

1 Like

Ohhh okay!
Thank you so much man you really helped me out… now all I have to do is gradually decrease the BaseMagnitude over time. Thanks!

Also, I’m going into Physics and Pre Calc this year, last year we did Arithmetic math so like dealing with monies and stuff, nothing too advanced… I want to be able to figure out these kinds of concepts on my own, at what Grade do you think I’ll be able to grasp the fundamentals of these?

Vectors is usually covered in physics.

You can print out the return values for functions and play with the inputs to learn more about how it works.

1 Like

Here’s a toy to play with to help visualize the vectors.
Copy and paste code into a script in your workspace and press play.
Add your Vector calculations at the end and use the newVector function to make it show up.

Code
game.Lighting.TimeOfDay = 0

local storage = Instance.new("Folder")
storage.Name = "Vector Stuff"
storage.Parent = workspace
script.Parent = storage

local offset = Vector3.new(0,10,0)
local origin = Vector3.new(0,0,0)

local part = Instance.new("Part")
part.Position = origin+offset
part.Shape = Enum.PartType.Ball
part.BottomSurface = Enum.SurfaceType.Smooth
part.TopSurface = Enum.SurfaceType.Smooth
part.Size = Vector3.new(.1,.1,.1)
part.Anchored = true
part.Parent = storage
part.Name = tostring(origin)
Instance.new("Attachment").Parent = part

local function makeEndPoint(vec)
  local temp = Instance.new("Part")
  temp.Transparency = 1
  temp.Position = vec+offset
  temp.CanCollide = false
  temp.BottomSurface = Enum.SurfaceType.Smooth
  temp.TopSurface = Enum.SurfaceType.Smooth
  temp.Anchored = true
  temp.Parent = storage
  temp.Name = tostring(vec)
  temp.Locked = true
  Instance.new("Attachment").Parent = temp
  return temp
end

local function newVector(vec, vec2)
  if vec2==nil then
    vec2 = vec
    vec = origin
  end
  local endPt = makeEndPoint(vec+vec2)
  local start = storage:FindFirstChild(tostring(vec))
  if start == nil then
    start = part
    warn("Your start vector does not exist; origin used")
  end
  local color = (endPt.Position - start.Position).Unit
  local col = Color3.new(color.X, color.Y, color.Z)
  local beam = Instance.new("Beam")
  beam.Attachment0 = start.Attachment
  beam.Attachment1 = endPt.Attachment
  beam.Color = ColorSequence.new(col)
  beam.FaceCamera = true
  beam.Width0 = 0.1
  beam.Width1 = 0.1
  beam.Parent = endPt
  return {start, endPt}
end

--

local x = newVector(Vector3.new(1,0,0))
local y = newVector(Vector3.new(0,1,0))
local z = newVector(Vector3.new(0,0,1))

--[[
  table newVector(Vector3 vec, Vector3 vec2)  
  vec is the starting position
  vec2 is the vector applied to position vec
  if vec2 is not used
  vec is the vector applied to the origin
]]--

newVector(Vector3.new(1,1,0),Vector3.new(1,1,1))
2 Likes

Alright, I’ll play around with it to get an understanding, thanks for your help lad!