Smooth Movement on Character?

Soooo, someone has asked this question before : Creating "custom character movement" (smoothly moving between slopes) but it was never answered.

I’m having a problem where if you were to traverse up a slope, it would either be very glitchy or stop you.
Someone suggested me a workaround which is to change the velocity of the parts like a conveyor but it’s still somewhat glitchy.

As you know, Speed Run 4: Speed Run 4 🍩😋[UPDATE] - Roblox was able to accomplish this smooth movement but I really don’t know how they were able to achieve it?

My guess is that he used body force or something to make it more smooth but for now, I honestly have no clue how he was able to do this? Any ideas on how this was done?

17 Likes

Yep, this was done with BodyForce.

If you know the surface your character is standing on, project Humanoid.MoveDirection onto that surface’s normal plane, then move in that direction. This could be done either by setting velocity or using an “impulse” in the BodyForce, e.g., for .1 seconds, provide 10x the amount of acceleration you need to get to the target velocity.

When I did this stuff for Vurse, the characters were fully custom, so the BodyForce was also responsible for keeping the player off the ground. If you do something similar, make sure you offset gravity appropriately.

16 Likes

Why did the characters need to be custom and what did you add on them? Did you just add a bodyforce to like the humanoidrootpart inside the custom character and use it when needed?

1 Like

He had a lot grander request than smooth slope walking (walking upside down and all that… don’t think that ever made it into the game).

And yes, added a BodyForce + BodyGyro to the HRP. I updated them every tick.

1 Like

Thank you! I’ll see what I could do now :smile:

1 Like

Uhhh, if you don’t mind me asking… What values did you use for BodyForce and BodyGyro?

1 Like

I would understand what the BodyForce is for but what is the BodyGyro for?

1 Like

In my case, I put the character in physics mode and controlled it manually. If you just need to make running up/down slopes smoother, you can definitely do without it.

@3rdhoan123, bodyforce should be proportional to the character’s mass.

1 Like

If you don’t mind (you don’t have to tho), could you provide a pseudo-code? I’ve been trying to attempt it but it would always either send me flying into the air or just not work at all. :sweat_smile:

1 Like

I think you can use the cross product from the surface normal provided by the ray and the BodyForce's current force to figure out a new axis to turn the force in, and use the dot product to find how large the change in angle should be. Probably something like this:

local BodyF = -- the bodyforce
local hit, contact, normal = workspace:FindPartOnRay(...)

local axis = BodyF.Force.Unit:Cross(normal)
local dot = BodyF.Force.Unit:Dot(normal)

-- the closer to 0 for dot, the softer the angle
local angle = math.asin(dot)
-- you can probably also use math.pi/2 - math.acos(dot)

if axis ~= Vector3.new() then
    BodyF.Force = CFrame.fromAxisAngle(axis.Unit, angle) * BodyF.Force -- * 10 ?
else -- force is perpendicular to normal
    BodyF.Force = CFrame.Angles(math.pi/2,0,0) * BodyF.Force.Magnitude
end

I’m sorry that this isn’t pseudocode since it is too technical for me to explain, as I’m trying to connect the dots too.

This would of course be applied in a loop, checking for hit's existence first. I can’t test this because I’m on mobile, so I may be absolutely wrong with this solution!

Edit: If the BodyForce pushes you further into the slope, try negating axis or angle. They will both do the same thing though, so personal preference.

7 Likes

Sorry to bump this, but I’m having the same problems, and this thread doesn’t fully help me understand how to fix them :grimacing:

Your example on the second last line

BodyF.Force = CFrame.Angles(math.pi/2,0,0) * BodyF.Force.Magnitude

Yields an error, invalid argument #2 (Vector3 expected, got number)

2 Likes

BodyForce.Force requires a Vector3. Additionally, you’re trying to multiply a CFrame, which simply isn’t possible in the way you’re doing it.

Essentially, since you’re intending to define an angle for the Vector using CFrame.Angles(), you can use this to construct a directional unit vector, and finally multiply this new vector by the Force’s magnitude.

A unit vector is a vector with a magnitude of 1.

local UnitVector = CFrame.Angles(math.pi/2,0,0) * CFrame.new(0, 0, -1)
UnitVector = UnitVector.Position

BodyForce.Force = UnitVector * Length

The Length variable is equivalent to the BodyF.Force.Magnitude from your code snippet.

2 Likes

Hi! I’m having this issue, is there a way to do this with the original player’s avatar?

Instead of characters instantly stopping, how can I make it smooth? - Help and Feedback / Scripting Support - DevForum | Roblox

1 Like

Sorry to bump this, but I’m having the same problem, but I managed to fix them.

What I did is just like @blobbyblob said, added BodyForce + BodyGyro to the HRP and updated them every tick. There was Two BodyForces used in this situation. One is for “Gravity”, and the second one is for controlling the character while running up slope (The most important one).

Here’s a Video of my art.

2 Likes