Need help scripting a skydive system

You can write your topic however you want, but you need to answer these questions:

  1. What do you want to achieve? Keep it simple and clear!
    Hello developers! I am currently designing a skydive game, where you fall of from a point and you maintain your speed and slowly make your way down to the bullseye.
  2. What is the issue? Include screenshots / videos if possible!
    I’m using VectorForce, and I’m not seeing a difference in the system when I do:
VectorForce.Force = Vector3.new(0, HumanoidRootPart:GetMass() * workspace.Gravity, 0)

Why does the difference only become noticeable on the y-axis after a force of 1500?
3. What solutions have you tried so far? Did you look for solutions on the Developer Hub?
I have tried using LinearVelocity, but the character just didn’t move for some reason. I found this post saying that I should VectorForce could work for wind resistance:

1 Like

You get more control if you edit the HumanoidRootParts AssemblyLinearVelocity manually in a RunService loop

With this you could just keep the Y velocity at a constant speed and keep or boost the other axes’ velocities to achieve the sky diving effect, without having to bother with adjusting vector forces.

1 Like

It’s affected because 1500 is over the total mass of the character not just the humanoid root part

2 Likes

Here is what I would recommend:

  • Use a LinearVelocity to control the falling speed. LinearVelocities apply forces to make an assembly match a certain speed. You can set the LinearVelocity.ForceLimitMode to PerAxis, then set the LinearVelocity.MaxAxesForce to something like (0, 99999999999, 0). This makes it so the speed on the Y axis is controlled by the LinearVelocity.VectorVelocity (e.g. you could use a value of (0, -40, 0) here to fall at -40 studs per second).
  • Play a skydiving animation on the character. (No need to actually rotate the character, just make an animation that does it for you!)
  • To determine when the player hits the ground, use downwards raycasts every frame, a Humanoid.Touched connection, or use a Humanoid.StateChanged connection, so that you can stop the animation and destroy the linear velocity when this happens.
1 Like

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.