Need help scripting a skydive system

So uhm, how do I make like the turning radius feel a bit heavier and have the player tilt to the side they move? I’m not exactly sure how to explain, but I think you understand what I mean.

That makes a lot of sense now. I didn’t take that into account before.

You could have Humanoid.AutoRotate turn off, then control the direction the player faces using an AlignOrientation.

I would program the AlignOrientation to slowly point the character towards the direction they’re moving.

Then, I would also program something to scale the character’s walk speed based on how close their MoveDirection is to the direction they’re facing (e.g. use Humanoid.MoveDirection:Dot(HumanoidRootPart.CFrame.LookVector) for how close the two directions are).

1 Like

What does :Dot() do and how will I use it in this situation?

I also have this boolean call ‘RoundEnded’ which checks if the round is over. So, like this:

					table.clear(Winners) -- clears the table of previous winners.
					hasClearedTable = true
					RoundEnded.Value = true
					task.wait(3)
					RoundEnded.Value = false
RoundEnded.Changed:Connect(function(newValue)
	if newValue == true then
		LinearVelocity.Enabled = false
		Humanoid.JumpPower = defaultJumpPower
		ContextActionService:UnbindAction("SpeedBoost")
		if SkydiveAnimationTrack.IsPlaying then
			SkydiveAnimationTrack:Stop(0.5)
		end
	end
end)

Is this what I should be doing?

For two unit vectors, the Dot between them returns a value between [-1, 1], depending on how close the two vectors are to the same direction. If they point exactly the same direction, it returns 1, if they point exactly the opposite, it returns -1, if they are perpendicular, it returns 0.

1 Like

Yeah that looks good.

1 Like

I might need to reduce the task.wait(3) because it feels a bit delayed.

1 Like

Do you know why the force isn’t applying when the player is skydiving if they press J?

HumanoidRootPart.AssemblyLinearVelocity = HumanoidRootPart.CFrame.UpVector * appliedImpulse

That looks correct. I would use :ApplyImpluse instead though. Also make sure that appliedImpulse is something like desiredVelocityChange * hrp.AssemblyMass

Oh… I just set it to -50. Let me change it real quick.

" The sum of the mass of all the parts in this part’s assembly. Parts that are Massless and are not the assembly’s root part will not contribute to the AssemblyMass."

This makes sense. And it was what @hya123456h said earlier I believe?

2 Likes

It still doesn’t work, but I’ll keep trying. Maybe it’s because there’s already an AssemblyLinearVelocity being applied.

I made most of a sky diving system based on Tear’s of the Kingdom’s:

SkydiveSystemTest-ezgif.com-optimize

Here is a place file:
SkydiveSystem.rbxl (58.9 KB)

Currently it still uses the default character movement. I’m planning on writing up some aerodynamic (inspired) equations to make the horizontal motion be based on the air hitting the diver then probably open sourcing it.

I’m also planning on swapping the default falling animation for this one:

Feel free to use what’s there though. I don’t have any timeline for finishing it so please don’t wait on me.

1 Like

Why not use FluidDynamics? It’d allow you to create a more realistic gliding system.

1 Like

That looks nice! I will take some notes of that and see what I can change/add to my system.

Also, whenever the player jumps this fires and it causes some strange things to happen:

Skydive.OnClientEvent:Connect(function()
	print("skydive fired")
	Humanoid.StateChanged:Connect(function(oldState, newState)
		print("state changed")
		if newState == Enum.HumanoidStateType.Freefall then
			LinearVelocity.VectorVelocity = Vector3.new(0, -diveSpeed, 0)
			LinearVelocity.Enabled = true
			Humanoid.JumpPower = 0
			ContextActionService:BindAction("SpeedBoost", Boost, true, Enum.KeyCode.J, Enum.KeyCode.ButtonY)
			ContextActionService:SetTitle("SpeedBoost", "Boost")
			ContextActionService:SetPosition("SpeedBoost", UDim2.new(0.2, 0, 0.5, 0))
		end
	end)
end)

Do I even have to fire a RemoteEvent at this point, just to catch when the player is actively skydiving? Or Can I just check when the state is changed.

Ok, so here is my full Skydive system currently (might convert this to a module later to make it a more clear to read):

local Player = game.Players.LocalPlayer

local Character = Player.Character or Player.CharacterAdded:Wait()

local Humanoid = Character:FindFirstChild("Humanoid")

local HumanoidRootPart = Character:WaitForChild("HumanoidRootPart")
local RootAttachment = HumanoidRootPart:WaitForChild("RootAttachment")

local diveSpeed = 30
local defaultJumpPower = 50
local appliedImpulse = math.floor(HumanoidRootPart.AssemblyMass / 6)

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RemoteEvents = ReplicatedStorage:FindFirstChild("RemoteEvents")
local Skydive = RemoteEvents:WaitForChild("Skydive")

local Values = ReplicatedStorage:FindFirstChild("Values")
local Booleans = Values:WaitForChild("Booleans")
local Strings = Values:WaitForChild("Strings")

local UserInputService = game:GetService("UserInputService")
local ContextActionService = game:GetService("ContextActionService")

local Animations = script:WaitForChild("Animations")
local SkydiveAnimation = Animations:WaitForChild("SkydiveAnimation")
local SkydiveAnimationTrack = Humanoid.Animator:LoadAnimation(SkydiveAnimation)

local debounce = false

local LinearVelocity = Instance.new("LinearVelocity")
LinearVelocity.Attachment0 = RootAttachment
LinearVelocity.ForceLimitMode = Enum.ForceLimitMode.PerAxis
LinearVelocity.VectorVelocity = Vector3.new(0, 0, 0)
LinearVelocity.MaxAxesForce = Vector3.new(0, math.huge, 0)
LinearVelocity.RelativeTo = Enum.ActuatorRelativeTo.World
LinearVelocity.Enabled = false
LinearVelocity.Parent = HumanoidRootPart

local function Boost(actionName, inputState, inputObject)
	if inputState == Enum.UserInputState.Begin then
		LinearVelocity.VectorVelocity = LinearVelocity.VectorVelocity * Vector3.new(0, appliedImpulse, 0)
		SkydiveAnimationTrack:Play(0.5)
	elseif inputState == Enum.UserInputState.End then
		LinearVelocity.VectorVelocity = Vector3.new(0, -diveSpeed, 0) -- resets the impulse applied to the humanoidrootpart.
		if SkydiveAnimationTrack.IsPlaying then
			SkydiveAnimationTrack:Stop(0.5)
		end
	end
end


local StateChangedConnection
StateChangedConnection = Humanoid.StateChanged:Connect(function(oldState, newState)
	if newState == Enum.HumanoidStateType.Freefall then
		if Player:GetAttribute("InRound") then -- if the player is currently InRound.
			LinearVelocity.VectorVelocity = Vector3.new(0, -diveSpeed, 0)
			LinearVelocity.Enabled = true
			Humanoid.JumpPower = 0
			ContextActionService:BindAction("SpeedBoost", Boost, true, Enum.KeyCode.J, Enum.KeyCode.ButtonY)
			ContextActionService:SetTitle("SpeedBoost", "Boost")
			ContextActionService:SetPosition("SpeedBoost", UDim2.new(0.2, 0, 0.5, 0))
		else
			StateChangedConnection:Disconnect()
		end
	end
end)



Player:GetAttributeChangedSignal("InRound"):Connect(function()
	if not Player:GetAttribute("InRound") then -- if the player is not InRound; in the lobby.
		LinearVelocity.VectorVelocity = Vector3.new(0, 0, 0)
		LinearVelocity.Enabled = false
		Humanoid.JumpPower = defaultJumpPower
		ContextActionService:UnbindAction("SpeedBoost")
		if SkydiveAnimationTrack.IsPlaying then
			SkydiveAnimationTrack:Stop(0.5)
		end
	end
end)




--[[Skydive.OnClientEvent:Connect(function()
	Humanoid.StateChanged:Connect(function(oldState, newState)
		print("changed")
		if newState == Enum.HumanoidStateType.Freefall then
			LinearVelocity.VectorVelocity = Vector3.new(0, -diveSpeed, 0)
			LinearVelocity.Enabled = true
			Humanoid.JumpPower = 0
			ContextActionService:BindAction("SpeedBoost", Boost, true, Enum.KeyCode.J, Enum.KeyCode.ButtonY)
			ContextActionService:SetTitle("SpeedBoost", "Boost")
			ContextActionService:SetPosition("SpeedBoost", UDim2.new(0.2, 0, 0.5, 0))
		end
	end)
end)--]]


--[[RoundEnded.Changed:Connect(function(newValue)
	if newValue == true then
		LinearVelocity.VectorVelocity = Vector3.new(0, 0, 0)
		LinearVelocity.Enabled = false
		Humanoid.JumpPower = defaultJumpPower
		ContextActionService:UnbindAction("SpeedBoost")
		if SkydiveAnimationTrack.IsPlaying then
			SkydiveAnimationTrack:Stop(0.5)
		end
	end
end)--]]

I need a better name than “SpeedBoost” too lol. Also, what is lerping? It confuses me…

Also, if I were to add obstacles to the skydiving, how would this work? because if they kill the player they can just instantly fall to the target.

Lerping just returns a value in-between two values. For example, lerping in 1D looks like this:

local function lerp1D(one, two, alpha)
    return one * (1 - alpha) + two * alpha
end

This returns a value that’s alpha*100 percent between one and two.

It’s used for smoothly moving between values.


This is up to you. If you’re worried about the parts falling, make sure to add a check for the target to make sure the player is alive.

You could do lots of things for obstacles:

  • The player losses when they hit a obstacle
  • The player gets a parachute that slows them down to 0 fall speed until they aren’t above the obstacle anymore
  • The player exits skydiving and must walk/run off the obstacle, and it takes a bit to regain their speed
  • etc
1 Like

What I could do is have the player bounce back upwards, when they get hit by an obstacle that has that specific ‘attribute’.

1 Like

That would be cool!

1 Like