The idea here is mostly straightforward.
Using the default Roblox physics engine, players lose all velocity a few seconds after jumping (provided they let go of directional keys), which can tend to be less than optimal for games based around momentum. Is there a simple way to make sure that the player keeps moving in the air even after they stop pressing any keys.
I already have some basic ideas for this, such as:
BodyVelocities / BodyMovers
The humanoid state type “Physics”
I have a slight idea on how to check if the player is grounded or not, and it appears that using a bodymover might be the better option if RunService is going to be used.
While there have been some other posts regarding this topic, most of them may be outdated or have been left unanswered.
If anyone has any information on how to perform this please reply, thanks.
The animations aren’t really what I’m concerned with for the physics state. It’s mostly because since I’m using RunService for ground checks, changing the state to physics keeps rapidly toggling the state. Is there any way to only toggle it once per ground check?
I was thinking connecting the event to a humanoid.Jumping then just waiting for the humanoid’s floormaterial to switch back from nil, however I do not know if this works.
Alright, so it looks like this works, however physics state is a bit weird and does not do what I thought it would do, which is conserver momentum mid air
Maybe it could just be the code, however:
local RS = game:GetService("RunService")
local plr = game.Players.LocalPlayer
local chr = plr.Character
local hum = chr:WaitForChild("Humanoid")
RS.RenderStepped:Connect(function()
if hum.FloorMaterial == Enum.Material.Air then
hum:SetStateEnabled(Enum.HumanoidStateType.Physics, true)
else
hum:SetStateEnabled(Enum.HumanoidStateType.Physics, false)
end
end)
I think you still need to use SetState as well to cause the humanoid to be in the physics state. Also have you tried this on the server rather than the client? I’m not sure exactly how the replication works for humanoid state but I can imagine it may override local changes.
Ok so that works now, all I need to do now is just to figure out how to disable the physics mode only once considering how everything runs on a runservice loop
Trying to set the player’s state to running just makes them essentially trip and not be able to get back up
Alright so I have just looked it up and looks like there is a way to detect general state changes, so I’ll try using that
So it looks like after the player jumps I need to find another method to check if the player is grounded, as the new state is physics. I think there is a way to check if a property changes so I can connect that to potentially the statechanged and see if the floormaterial changes then I can disable physics
The player just jumps once then gets stuck on the floor, any ideas on how to fix it?
local RS = game:GetService("RunService")
local Debris = game:GetService("Debris")
local plr = game.Players.LocalPlayer
local chr = plr.Character
local root = chr:WaitForChild("HumanoidRootPart")
local hum = chr:WaitForChild("Humanoid")
hum.StateChanged:Connect(function(old, new)
if new == Enum.HumanoidStateType.Jumping then
hum:ChangeState(Enum.HumanoidStateType.Physics)
elseif new == Enum.HumanoidStateType.Physics then
hum:GetPropertyChangedSignal("FloorMaterial"):Connect(function()
if hum.FloorMaterial ~= Enum.Material.Air then
hum:ChangeState(Enum.HumanoidStateType.Physics)
end
end)
end
end)
just wanted to say youve probably already figured this out but uhh it stops working after the point were it checks if new == physics it gets past that but hum:GetPropertyChangedSignal(“FloorMaterial”):Connect(function() breaks the rest
local oldVelPref = 140 -- Determines how strongly to maintain momentum, higher values maintain old velocity, but can cause wall sticking.
local airAcceleration = 2 -- Determines how quickly to accelerate in the air
local RunService = game:GetService("RunService")
local char = script.Parent
local Humanoid = char:FindFirstChildWhichIsA("Humanoid")
local RootPart = Humanoid.RootPart or char:WaitForChild("HumanoidRootPart")
Humanoid.FreeFalling:Connect(function(active)
while Humanoid:GetState() == Enum.HumanoidStateType.Freefall do
local oldVel = RootPart.AssemblyLinearVelocity
local dT = RunService.PostSimulation:Wait()
local curVel = RootPart.AssemblyLinearVelocity
-- Allows mid-air control
local moveVel = Humanoid.MoveDirection*Humanoid.WalkSpeed
local addVel = Vector3.new(
curVel.X > 0 and math.max(moveVel.X-curVel.X, 0) or math.min(moveVel.X-curVel.X, 0),
0,
curVel.Z > 0 and math.max(moveVel.Z-curVel.Z, 0) or math.min(moveVel.Z-curVel.Z, 0)
) * dT * airAcceleration -- Gradual acceleration
local pref = oldVelPref * dT
RootPart.AssemblyLinearVelocity = Vector3.new(
math.clamp(oldVel.X, curVel.X-pref, curVel.X+pref),
math.max(curVel.Y, -200),
math.clamp(oldVel.Z, curVel.Z-pref, curVel.Z+pref)
) + addVel
end
end)