How is this done?

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!!!

1 Like

Just a little bump. Hoping for a suitable solution!

so first what you want to achieve is pretty advanced i don’t have direct solution because you didn’t point out the problems so why is it not going as to planned? do you want to make a glider or how is it suppose to be? in minecraft im sure it glides what i suggest if you use toolbox mabey you can find a good glider and use thier technique

I have tried the toolbox, but none of the things that I have been able to find have been even remotely what I want. The problem with the firs one, the one that is based on ramp physics, lets the player start to fall backwards, and the one based on the elytra has forces too high, and the angles seem to change the speed in unexpected ways.

So does anyone have a way that they would approach this that might work?

well at some point like this it is all about messing around with values and see what works the best. maybe try tweaking the code a bit until you are satisfied, that is how I usually get the resaults I want.

I have not tried to create this but after looking at your code examples it seems like if you could employ using a LinearVelocity attached to the HumanoidRootPart it would give a more realistic or natural feel then anchoring it and just moving the character around. Would definitely take time and experimentation to get it the way you’d like it.

Edit: Just as a quick test I realized you’d need to also add LinearyVelocity to both of the legs as otherwise it would be swinging down in air.

My actual script as a spring to move the character so it is a lot smoother. The scripts that I posted were just the base scripts that work with no dependencies. The math done in them should also be the same thing that you would get with a LinearVelocity.

1 Like

try to do

make the hortizentalVelocity value in the if pitch < 0 statement negative like this

local yacc = -horizontalVel * -lv.Y * 0.04

i tried it with my own and it works
the the velocity atleast

edit: don’t forget to change the constraint value, it will make the player fall very very uncontrollably fast when facing down diagonally