Sliding "Momentum" like in Grace

So I’ve developed a slide system that aims to be a similar to the sliding on the game Grace, and I’ve been having some doubts on how to make something like that.

I’ve been using a BodyVelocity, which from research is pretty antiquated, but I don’t seem to see any other alternatives, since many of the others I’ve tried like LinearBodyVelocity / AngularBodyVelocity just make the player not have a gravity.

The biggest problem I have is just that the player gets stuck to walls and cannot get “unstuck” until they stop sliding, and I’d like that to not happen at any case

So if anyone has any idea on how to make something like this, it would help a lot!

(Footage and Script below)

local plr = game.Players.LocalPlayer
local char = plr.Character
local uis = game:GetService("UserInputService")

local root = char.HumanoidRootPart
local camera = workspace.CurrentCamera

local rp = RaycastParams.new()
rp.FilterType = Enum.RaycastFilterType.Exclude
rp.FilterDescendantsInstances = {char}

local dS = 16
local cS = 0
local hasStarted = false

local s = char.Humanoid:LoadAnimation(script.slidin_anim)
local can = true

char.Humanoid.StateChanged:Connect(function(ol, new)
	print("d")

	if new == Enum.HumanoidStateType.Freefall then
		if math.abs(char:WaitForChild("HumanoidRootPart").AssemblyLinearVelocity.Y) > 10 then
			can = true
		end
	else
		can = false
	end
end)

while task.wait() do
	if (uis:IsKeyDown(Enum.KeyCode.LeftControl) or uis:IsKeyDown(Enum.KeyCode.RightControl)) and char.Humanoid.FloorMaterial ~= Enum.Material.Air then	
		local i = 30
		
		local slide = Instance.new("BodyVelocity")
		slide.Velocity = char.HumanoidRootPart.CFrame.LookVector * i
		
		slide.MaxForce = Vector3.new(1,0,1) * 30000
		slide.Parent = root
		
		script.slide_sfx:Play()
		
		repeat
			script.slide_sfx.PlaybackSpeed = 1 + i/100
			s:Play()
			char.Humanoid.CameraOffset = Vector3.new(0,0,0):Lerp(Vector3.new(0, -1.5, 0), 0.25)
			slide.Velocity = char.HumanoidRootPart.CFrame.LookVector * i
					
			local deltaY = char.HumanoidRootPart.Velocity.Y;
			local deltaX = (char.HumanoidRootPart.Velocity*Vector3.new(1,0,1)).Magnitude;
			local r = workspace:Raycast(char.HumanoidRootPart.Position, -Vector3.yAxis * 25, rp)
			
			if deltaY/deltaX > 0 and can == false then
				if r then
					print(r.Instance)
					print(r.Material)
					
					if (r.Instance:IsA("Part") and r.Instance.Shape == Enum.PartType.Wedge) or (r.Instance:IsA("WedgePart")) then
						i /= 1.025
					end
				end
				
				i /= 1.005
			else
				if can == false then
					i *= 1.02
				end
			end

			task.wait()
		until not uis:IsKeyDown(Enum.KeyCode.LeftControl) or i < 0

		s:Stop()
		script.slide_sfx:Stop()
		
		char.Humanoid.WalkSpeed = 16
		game.Debris:AddItem(slide, 0.05)
		
		repeat
			char.Humanoid.CameraOffset = Vector3.new(0,0,0):Lerp(Vector3.new(0, 0, 0), 0.25)
			
			task.wait()
		until char.Humanoid.CameraOffset == Vector3.new(0,0,0)
	else
		hasStarted = false
		
		cS = 0
	end
end
4 Likes

Did you ever end up finding out how to fix this?

i think i just resorted to using a linear velocity instead of a body one, since that one is very outdated

Holy fast reply, ight. Have a nice day or night

1 Like

I know it’s very late, but I really like how it turned out and I’d like to do something similar in my game. That said, I have a question: ¿How do you get the animation to rotate the player’s legs 90 degrees into the air? I can’t pass from 70 degrees or so

hm uhh i don’t know what u mean here…

could you specify the idea a bit? so i can try to help

I mean that animations typically have a limit on how much a part of the body can be rotated, mostly to avoid unrealistic positions (for example, you can’t have an animation where the player"s leg rotated 180º into the air).

I was also making a sliding system when I came across your post, and I needed to make a placeholder animation, and I wanted to rotate the body 90º in order for it to adhere to the ground (although I eventually settled in a simple sitting animation like yours for now). I eventually figured out that with platformstand = true the animation rotation limit didn’t affect the animation. I guess that also works with the Freefall humanoid state.

Anyways, I did end up ditching the project because it was too complicated for my skill level, but thanks for your slide script because it was a really good reference for when I was stuck

oh really?
i just use the default roblox animator and i really can just put something where i want, weird

and also no problem!

Idk, maybe it’s just a skill issue on my end, but that’s what I found.

Anyways, thanks for everything

1 Like

so uh, I have almost finished this,

I just need to know how to add a downward force or something, so the character stays in the slope
if anyone knows how to do that, tell me
(I’ve used a linear velocity now)

Sorry for being late and a bit too insistent but anyways. I thought that for adding downwards velocity in a slope you could make a raycast going straight down to the player, enough to detect when there’s a slope below the player. Then, if the raycast detects something (in this case a part), you can access its normal. The normal of a wall/floor/anything 3D, in case you didn’t know, is a vector drawn in the direction is pointing. A 3D objects has many normals, as many as faces, as every face faces one direction. Because of that, if the raycast detects a floor, its normal will be a vector facing upwards. However, if it’s a slope, it will be a vector facing in a diagonal direction (that is, x and z aren’t 0). Using that, you can easily check for a slope, (x and/or z aren’t 0), it’s direction (the normal vector without the y parameter) and how steep it is (I think it’s the greater the x and z values the steeper, but you’d have to check). Anyways, in this case you only need the steepness, which you can convert into a number (e.g. if what I said was correct, steepness = normal.x + normal.z, but any method you find is also valid) and apply a downwards velocity based on that number, that is, the greater the steepness, the greater the downwards force. That or, to simplify, you could just check if it’s a slope and apply a downwards force regardless of the steepness. I don’t know if both of them could work well with how your sliding system works, but if you’re stuck with what to do, try this. Although, as far as I’m aware, you still need the normal to check if you’re on a slope, though.

That’s all, hope it helps.

1 Like

now it WORKS but only when there is no animation, I don’t know why it’s like that

both scripts im using
animate.rbxm (1.7 KB)
characterController.rbxm (3.2 KB)

May be an issue with animation priorities?

I’ve tried changing its priority to Idle, Movement, Action, and Core.

And it still breaks, unless I don’t put any animation.