How would I make a more advanced movement system?

Essentially, I’d like to create a more advanced movement system.

Currently, when you press the W key in Roblox, you instantly start moving at a set velocity. When you stop holding it, you instantly stop.

How would I make it so that the player accelerates when you start holding and reaches the maximum speed potential, and then when they release it it gradually slows down?

The system I’m trying to remake here is slightly like CS:GO’s movement system, where the player model accelerates and decelerates instead of instantly moving forward and stopping.

9 Likes

The way I implemented a movement system in my game might be interesting for you. Check it out here and tell me what you think!

https://www.roblox.com/games/6711634328/Project-Cannon

It uses ApplyImpulse() to move the character, though.

4 Likes

Yes, in fact it is something like that, would you be kind enough to tell me in more detail how you did it?

Edit: i just realised that the models in your game are just spheres so if you could tell me how to apply this to a regular playermodel that’d be great

I’ll try my best to explain it, but here’s the code:

	torso:ApplyImpulse(((mathModule.fixVector(camera.CFrame.LookVector) 
	* (F_FORCE + B_FORCE)) 
	+ (camera.CFrame.RightVector * (R_FORCE + L_FORCE))) 
	* CONST_SPEED 
	- ( Vector3.new(torso.Velocity.X / 2.75, torso.Velocity.Y / 3, torso.Velocity.Z / 2.75))
)
2 Likes

When W key is held, the F_FORCE is 1, else 0
When S key is held, the B_FORCE is -1, else 0

When the LookVector is multiplied by this, it gives a vector direction. I then add this to the horizontal (left/right) part using the same method and multiply it by a constant speed.

I also subtract a percentage of the current velocity from this new velocity to soft cap the speed.

Also, the reason that I have the fixVector() thing is because the LookVector can rotate anywhere, so when the character is looking directly up, there’s basically no movement forwards. So I implemented a math thing to deal with that:

function mathModule.fixVector( vector )

local angle = math.atan2(vector.Z, vector.X)

vector = Vector3.new(math.cos(angle), 0, math.sin(angle))
	
return vector

end
3 Likes

Capsule models will work great for this, I think. You might have to do a little bit of extra math to keep the character upright though.

System I worked on a few years ago is all about speed management. Very heavily influenced by Quake but might also have some things to help you. You are welcome to take a look and see what you can learn- I just set it to allow for copying rn. The movement is handled inside of StarterPlayer > StarterPlayerScripts > Client. You will gain speed etc based on what surface your jump lands you on as well as how much you airstrafe (although my formula is not based on anything other than mouse pos changing).

Here is the place, https://www.roblox.com/games/1108213240/RoQuake-V1-Physics-Demo

4 Likes

I’ve downloaded the place to see the movement script, you can turn copying off, many thanks.

1 Like

Sorry to bother you, but where is the R_FORCE, B_FORCE, F_FORCE, CONST_SPEED and L_FORCE values set?

I set them all at the top of the script

Also (just example, my client code is currently messy):

local function onLeft(actionName, inputState)
if inputState == Enum.UserInputState.Begin then
	L_FORCE = -1
elseif inputState == Enum.UserInputState.End then
	L_FORCE = 0
end
end

I set the CONST_SPEED at the top also

local CONST_SPEED = 60

local F_FORCE = 0

local R_FORCE = 0

local B_FORCE = 0

local L_FORCE = 0
1 Like

Apologies for necrobumping, but this could help new people who come to view this thread.

This is just another solution, but what I did to solve this problem was run a for loop on every basepart descendant and increase the slipperiness (decrease friction). It’s not the best option, but it does the job.

6 Likes

Try this script. I saw a deceleration script on the devforums a long time ago and combined it with a acceleration script:

local Plr = game.Players.LocalPlayer
local Char = Plr.Character or Plr.CharacterAdded:Wait()
local Hum = Char:WaitForChild("Humanoid")
local HRP = Char:WaitForChild("HumanoidRootPart")
local TS = game:GetService("TweenService")

-- configuration
local DefaultSpeed = 1
local MaxSpeed = 10
local AccelerationTime = 0.6
local DecelerationTime = 0.8

-- variables
local IsMoving = false
local AccelTween = nil
local DecelTween = nil
local DV = nil

Hum.WalkSpeed = DefaultSpeed

local function startAcceleration()
	if AccelTween then
		AccelTween:Cancel()
	end

	AccelTween = TS:Create(Hum, TweenInfo.new(AccelerationTime, Enum.EasingStyle.Quad, Enum.EasingDirection.In), {WalkSpeed = MaxSpeed})
	AccelTween:Play()
end

local function startDeceleration()
	if DecelTween then
		DecelTween:Cancel()
	end

	if DV then
		DV:Destroy()
	end

	DV = Instance.new("BodyVelocity")
	DV.MaxForce = Vector3.new(100000, 0, 100000)
	DV.Velocity = HRP.Velocity
	DV.Parent = HRP

	DecelTween = TS:Create(Hum, TweenInfo.new(DecelerationTime, Enum.EasingStyle.Quad, Enum.EasingDirection.Out), {WalkSpeed = DefaultSpeed})
	local DecelTween2 = TS:Create(DV, TweenInfo.new(DecelerationTime, Enum.EasingStyle.Quad, Enum.EasingDirection.Out), {Velocity = Vector3.new(0, 0, 0)})

	DecelTween:Play()
	DecelTween2:Play()

	-- Destroy BodyVelocity if it still exists after deceleration
	delay(DecelerationTime, function()
		if DV then
			DV:Destroy()
		end
	end)
end

Hum:GetPropertyChangedSignal("MoveDirection"):Connect(function()
	if Hum.MoveDirection.Magnitude > 0 then
		if not IsMoving then
			IsMoving = true
			startAcceleration()
		end

		-- If the player is moving, destroy BodyVelocity if it exists
		if DV then
			DV:Destroy()
			DV = nil
		end
	else
		if IsMoving then
			IsMoving = false
			startDeceleration()
		end
	end
end)

1 Like