Inconsistant travel distance using AssemblyLinearVelocity

I’m using the AssemblyLinearVelocity property in order to create a dashing system for my game.
I’m not using BodyVelocity as it proves to be unreliable for fast paced fighting games, since it has a small delay between the client who creates it and others clients.
The issue is that the distance travelled by dashing is much bigger when the player is in the air, as there is no friction with the ground. I already tried removing friction for all body parts but it did not fix it.
Here’s my code :

function force.createDash(character,length,speed,yVelocity,side)
	local rootPart = character:FindFirstChild("HumanoidRootPart")
	local connection = RunService.RenderStepped:Connect(function()
		local velocity
		if side then
			velocity = rootPart.CFrame.RightVector * speed + Vector3.new(0,yVelocity,0)
		else
			velocity = rootPart.CFrame.LookVector * speed + Vector3.new(0,yVelocity,0)
		end
		character:FindFirstChild("HumanoidRootPart").AssemblyLinearVelocity = velocity		
	end)
	task.wait(length)
	connection:Disconnect()
end

(I’m setting the property itself rather than using ApplyImpulse, as the problem is even worse otherwise)

Here is what it looks like in game :

Have you tried using a linear velocity instead?

Not sure I tried that, I’ll look into it and uptade the topic.

1 Like

So I’ve tried using a linear velocity with this code

    local Att = Instance.new("Attachment")
	Att.Parent = rootPart

	local LV = Instance.new("LinearVelocity")
	LV.MaxForce = 500000
	LV.Attachment0 = Att
	LV.VectorVelocity = (rootPart.CFrame.RightVector * speed ) + Vector3.new(0,yVelocity,0)
	LV.Parent = rootPart
	task.wait(length)
	LV:Destroy()

Unfortunately, the result is still the same.

I normally use a VectorForce and I think it should solve your problem, the main problem is that in the air the character has no friction so he can more freedly slide.

Where are the speed and yVelocity values from?

The code is in the function createDash from the initial message, they’re passed as arguments. In my testing the yVelocity is always set to 0 so it’s irrelevant.

Try multiplying the force by the mass of the character

That’s basically my problem, the distance travelled in the air is different and if the velocity is quite high, then the difference is very noticeable and problematic.

By multiplying by the mass of the character, the distance is increased both when dashing on the ground and in the air, so it doesn’t seem to solve much.

Then reduce the force being multiplied to the mass of the object. And how are you finding speed?

To multiply by the mass I use the following line

velocity = rootPart.CFrame.RightVector * (speed*rootPart.AssemblyMass) + Vector3.new(0,yVelocity,0)

Changing the force here doesn’t help in any way because the speed in the air will always be higher than the speed on the ground, in a way multiplying by the mass just results in an higher speed but doesn’t solve much.

The speed is an arbitrary value which is chosen randomly pretty much, in the first comment I used a speed of 70 and a length of 0.3 to achieve the effect.

Ok way I’m going to describe is how I do it on my games, and it’s kind of a pain (but works). In your RenderStepped connection, check if the player is on the ground (can be done with raycasts down or maybe checking the humanoid.FloorMaterial to see if it’s Air. Then from there, if it’s in the air you check the current velocity local iterateVelocity = character.PrimaryPart.AssemblyLinearVelocity and adjust the new force based off the speed it’s going. Velocity = Distance/Time

I’m not sure how you obtain the distance or time for your velocity. Do you maybe have an example ?

Distance and time are constants, so how much distance you want to travel with the dash in a set amount of time. (5 studs in 1 second)

Yes but Distance/Time doesn’t result in a vector which is required when setting the AssemblyLinearVelocity. Do you multiply this result to the current velocity ? I’m slightly confused.

Sure, Distance/Time doesn’t result in a vector but that’s why you multiply it by the characters LookVector (direction)

So how is it different from what I’m currently doing ?
If the player is in the air, I would do something like

velocity = rootPart.CFrame.LookVector * (Distance/Time)

Right ?
Isn’t that what I’m doing already with the speed value ?

It’s different from what you’re currently doing because the distance and time are going to be variables in the loop. time is the elapsed time since you started the dash and distance is the remaining distance to the destination

local goalFrame = CFrame.new(0, 0, -5) --Dashes the player 5 studs infront
local maxDashTime = 1 --the amount of time you want the player to dash, so for this example 1 second

local elapsedTime = 0
local distanceOffset = 5
local goalDistance = character.PrimaryPart.CFrame * goalFrame

local connection = nil
connection = RunService.Heartbeat:Connect(function(step)
    elapsedTime+=step --new time
	distanceOffset = (character.PrimaryPart.CFrame.Position - goalDistance.Position).Magnitude --new distance

    if elapsedTime >= maxDashTime then --When 1 second is elapsed, close connection
        connection:Disconnect()
        connection = nil
    end
end)
1 Like

I’ll take a look at this tomorrow as it’s getting late for me, thanks for your help.

1 Like