I have been working on a game for over a year now, but I keep giving up because I am not able to find a suitable solution to the problem that I am having. About a year ago I started positing topics about realistic gliding physics, but I never found a suitable answer. I then just decided to base my system off of the physics of an object on a ramp. While this worked pretty well for testing, It is no longer suitable for me to use as the release date gets closer. I have tried all sorts of things to get the desired effect which is what is seen in the Roblox game Bird Simulator by Avian Skies, so I know that it is possible in Roblox, and another place that it is seen is in Minecraft’s elytra functions. I have found the code that runs in MC every tick, and transcribed it to Roblox, however, it does not have the desired effect.
TL;DR: I am looking for help to make some sort of gliding system, does not need to be realistic, but I am hoping for it to feel fun to test out, such as the one found in Bird Simulator.
My test for the ramp based physics is here:
local player = game:GetService("Players").LocalPlayer
local realchar = player.Character or player.CharacterAdded:Wait()
local humanoid: Humanoid = realchar:WaitForChild("Humanoid")
local rootPart = realchar:WaitForChild("HumanoidRootPart")
local cam = workspace.CurrentCamera
-- start of actual stuff
local gravity = 10
local friction = 0.03
local angOff = math.rad(-75)
local velocity = 0
local maxVel = 250
game:GetService("RunService").Heartbeat:Connect(function(deltaTime)
if fly and humanoid.Health > 0 then
local lv = cam.CFrame.LookVector
local sin = -lv.Y
local cos = math.sqrt(1 - sin * sin)
local a = (gravity * sin) - (friction * gravity * cos)
velocity = (velocity + a * deltaTime)
velocity = math.clamp(velocity, -maxVel, maxVel)
local disp = (lv * (velocity * deltaTime))
local newPos = disp / 0.28
local pCF = (rootPart.CFrame + newPos).Position
rootPart.CFrame = CFrame.lookAt(pCF, pCF + lv) * CFrame.Angles(angOff, 0, 0)
end
end)
game:GetService("UserInputService").InputBegan:Connect(function(inputObject, gameProcessEvent)
if inputObject.KeyCode == Enum.KeyCode.E then
fly = not fly
rootPart.Anchored = not rootPart.Anchored
humanoid.PlatformStand = not humanoid.PlatformStand
velocity = 0
end
end)
and for the Elytra based:
-- Based on this: https://gist.github.com/samsartor/a7ec457aca23a7f3f120, and the actual decompiled minecraft source code
local player = game:GetService("Players").LocalPlayer
local cam = workspace.CurrentCamera
local char = player.Character or player.CharacterAdded:Wait()
local root = char:WaitForChild("HumanoidRootPart")
local humanoid = char:WaitForChild("Humanoid")
local atan2, asin = math.atan2, math.asin
local cos, sin = math.cos, math.sin
local pi = math.pi
local sqrt = math.sqrt
local angOff = math.rad(-75)
local function getHDistSqr(vec: Vector3): number
return vec.X * vec.X + vec.Z * vec.Z
end
local d = 0.08
local isFlying = false
local vel = Vector3.zero
game:GetService("RunService").RenderStepped:Connect(function(dt)
--total += dt
if isFlying then
--if total >= t then
local lv = cam.CFrame.LookVector
local pitch = asin(lv.Y) -- float8
-- local yaw = atan2(lv.X, -lv.Z)
local movement: Vector3 = vel -- cty6
local lookAngle: Vector3 = lv--calculateViewVector(pitch, yaw) -- cty7
local horizontalLook = sqrt(getHDistSqr(lookAngle)) -- double9
-- get the horizontal vel squared
local horizontalVel = sqrt(getHDistSqr(movement)) -- double11-- will always be zero for now
local pitchCos = cos(pitch)
pitchCos *= pitchCos -- float15
movement = movement + Vector3.new(0, d * (-1 + pitchCos * 0.75), 0)
--movement = movement + Vector3.new(0, -d * (pitchCos * 0.06), 0)
if movement.Y < 0 and horizontalLook > 0 then
local yacc = movement.Y * -0.1 * pitchCos -- double16
local x = lookAngle.X * yacc / horizontalLook
local y = yacc
local z = lookAngle.Z * yacc / horizontalLook
movement += Vector3.new(x, y, z)
end
if pitch < 0 then --and horizontalLook > 0
local yacc = horizontalVel * -lv.Y * 0.04
local x = -lookAngle.X * yacc / horizontalLook
local y = yacc * 3.2
local z = -lookAngle.Z * yacc / horizontalLook
movement += Vector3.new(x, y, z)
end
if horizontalLook > 0 then
local x = (lookAngle.X / horizontalLook * horizontalVel - movement.X) * 0.1
local y = 0
local z = (lookAngle.Z / horizontalLook * horizontalVel - movement.Z) * 0.1
movement += Vector3.new(x, y, z)
end
movement *= Vector3.new(0.99, 0.98, 0.99)
vel = movement
root.CFrame += vel
local pos = root.Position
root.CFrame = CFrame.lookAt(pos, pos + lv) * CFrame.Angles(angOff, 0, 0)
end
end)
game.ContextActionService:BindAction("asdfasdfasd", function(_, state: Enum.UserInputState)
if state == Enum.UserInputState.Begin then
isFlying = not isFlying
root.Anchored = isFlying
humanoid.AutoRotate = not isFlying
humanoid.PlatformStand = isFlying
end
end, false, Enum.KeyCode.E)
If anyone has any ideas, I would love to hear them and try to put them to use!!!