Raycast based vehicle sliding down slope

so i have everything working except the friction of the “wheels” to keep it from sliding on a slope, as shown in the video

i got no clue how to fix this anybody got any thoughts?

code: (using vector forces)

function module:calculateSlip(dt, hit)
	local right = self.attach.CFrame.RightVector -- where the vector is pushing
	local velocity = getVelocityAtPoint(self.attach.Parent, self.attach.WorldPosition) -- simple velocity getting
	velocity = self.attach.Parent.CFrame:VectorToObjectSpace(velocity) -- transform to local space (global space is weird)
	
    -- just get the friction
	local props = nil
	if hit.CustomPhysicalProperties then
		props = hit.CustomPhysicalProperties
	else
		props = PhysicalProperties.new(hit.Material)
	end
	
	local mass = ((self.attach.Parent.AssemblyMass + self.mass) * workspace.Gravity) -- simple math for mass
	local frictionForce = (-velocity * props.Friction * mass) * dt -- simple force calculation (velocity / dt doesnt work correctly)
	
	return right * frictionForce
end
3 Likes

I think you could just mess with the friction properties in CustomPhysicalProperties

1 Like

i dont want to do that. thats not the issue im trying to fix it from sliding on normal parts.
im not going to go through every part in the game and change its friction that doesnt solve the issue
even at 2 friction (the max) still slides down the slope

ice of course it should slide down but not plastic

im looking for some math to push it while its on a slope (i cant find anything)

Why is the friction multiplied by the right vector?

I believe it should be in opposite direction of motion such as .Velocity and just friction force which I have done for my vector force raycast movement system although it’s for a character.

I would also suggest using an exponential function to decrease the friction force at low speeds in order to stabilize the vehicle.

    local isMoving = unitXZ.X == unitXZ.X and xzSpeed > 0.001 -- NaN check also speed check to avoid very slow speed numbers into formula 1e-19 and such

    local totalDragForce = ZERO_VECTOR

    local flatFrictionScalar
    if onGround and isMoving then
        --This equations allows vector forces to stabilize
        --"Decrease flat friction when low speed"
        --Constant friction when above velocity is above 2 usually
        flatFrictionScalar = model:GetAttribute("FlatFriction")*(1.0-math.exp(-2*xzSpeed))
        totalDragForce += -unitXZ*flatFrictionScalar
    end

Also there is no need to multiply with dt for force, you let the Roblox physics engine input dt and solve in by itself.

its multipled by right to make sure its pushing in the right direction, without it, it pushes in weird directions

it is already the opposite of the velocity thats was “-velocity” is doing.

im using “* dt” because for some reason without it the force is way too much and the car starts going into space

ill try your solution when i get home (few hours from now)

what will flat friction be, is that just the grip of the tires? or the friction of the part or something else

edit: i do want the car to side as it normally would (down a slope forwards/backwards) but not side on its side like its doing right now.

so the only friction that needs fix is the friction on the x axis, the z axis is completely fine

Flat friction is a constant variable and is basically the product of friction coefficient and mass together in one value, just a flat value which is more easily controllable to see.

Kind of like this value:

Probably caused by multiplication with .Velocity

.Unit should be enough for the direction if you multiply with velocity you will get drag force instead.

ok thanks for clearing that up

im going to assume isMoving is just if the velocity on x or z is more than a really small number (0.01 or 0.001)

because if its a check for the throttle being more than 0 there will be no friction when the car is pushed by a player, or bumped into a wall, etc

Yes it is, you can check it in Running.lua of my physics character controller for the full code which handles XZ movement.

1 Like

using this it will no longer slide on the x axis BUT it does this weird shaking issue after it stopped

probably an issue with some code (will edit this if i fix) but heres a video
again i want it to roll down the slope BUT NOT SIDEWAYS

old
function module:calculateSlip(dt, hit, hitPos, normal)
	local right = self.attach.CFrame.RightVector
	local velocity = getVelocityAtPoint(self.attach.Parent, self.attach.WorldPosition)
	velocity = self.attach.Parent.CFrame:VectorToObjectSpace(velocity)
	velocity = Vector3.new(velocity.x, 0, velocity.z)
	
	local props = nil
	if hit.CustomPhysicalProperties then
		props = hit.CustomPhysicalProperties
	else
		props = PhysicalProperties.new(hit.Material)
	end
	
	local mass = ((self.attach.Parent.AssemblyMass + self.mass) * workspace.Gravity)
	--local frictionForce = (-velocity * props.Friction * mass) * dt
	
	local xzSpeed = velocity.Magnitude
	local unitXz = velocity.Unit
	
	local dragForce = Vector3.new()
	local isMoving = unitXz.X == unitXz.X and xzSpeed > 0.001
	
	local flatFrictionScalar
	if isMoving then
		flatFrictionScalar = (props.Friction * mass) * (1 - math.exp(-2 * xzSpeed))
		dragForce += -unitXz * flatFrictionScalar
	end
	
	return right * dragForce
end

what this is basically doing is im applying the right friction force but the forward friction force is calculated differently to allow sliding forwards/backwards down a slope

code for forward friction

-- this includes the throttle, i will add comments for just the forward friction/rolling friction 
function module:calculateMotor(dt, hit, throttle)
	local forward = self.attach.CFrame.LookVector -- vector
	local velocity = getVelocityAtPoint(self.attach.Parent, self.attach.WorldPosition)
	velocity = self.attach.Parent.CFrame:VectorToObjectSpace(velocity) -- velocity
	
	local props = nil -- friction coefficient 
	if hit.CustomPhysicalProperties then
		props = hit.CustomPhysicalProperties
	else
		props = PhysicalProperties.new(hit.Material)
	end
	
	local currentSpeed = velocity.Z -- get current speed on the Z
	local mass = ((self.attach.Parent.AssemblyMass + self.mass) * workspace.Gravity) -- mass
	local frictionForce = (currentSpeed * props.Friction * mass) * dt -- main force (from old code)
	
	local speed = self.maxSpeed * throttle -- ignore this
	speed *= (mass) * dt -- ignore this
	
	if (throttle > 0 and math.abs(currentSpeed) < self.maxSpeed) or (throttle < 0 and math.abs(currentSpeed) < self.maxSpeed / 2) then
		return (forward * speed), (frictionForce * forward) -- second one is the friction force
	end
	
	return (forward * 0), (frictionForce * forward) -- second one is the friction force
end

ignore everything in old, i changed some stuff

the friction force is now calculated in one function and just using different unit vectors

function module:calculateSlip(dt, hit)
	local right = self.attach.CFrame.RightVector
	local forward = self.attach.CFrame.LookVector
	
	local velocity = getVelocityAtPoint(self.attach.Parent, self.attach.WorldPosition)
	velocity = self.attach.Parent.CFrame:VectorToObjectSpace(velocity)
	velocity = Vector3.new(velocity.x, 0, velocity.z)
	
	local props = nil
	if hit.CustomPhysicalProperties then
		props = hit.CustomPhysicalProperties
	else
		props = PhysicalProperties.new(hit.Material)
	end
	
	local mass = ((self.attach.Parent.AssemblyMass + self.mass) * workspace.Gravity)
	--local frictionForce = (-velocity * props.Friction * mass) * dt
	
	local xzSpeed = velocity.Magnitude
	local unitXz = velocity.Unit
	
	local dragForce = Vector3.new()
	local isMoving = unitXz.X == unitXz.X and xzSpeed > 0.001
	
	local flatFrictionScalar
	if isMoving then
		flatFrictionScalar = (props.Friction * mass) * (1 - math.exp(-2 * xzSpeed))
		dragForce += -unitXz * flatFrictionScalar
	end
	
	return right * dragForce, -forward * dragForce
end

this code still causes the shaking

In your code, you are already calculating the friction force using this formula, with props.Friction representing the coefficient of friction and mass representing the normal force. The only thing you need to do is apply this friction force to the object in order to slow it down and prevent it from sliding on a slope.

To do this, you can simply add the friction force to the object’s velocity in the opposite direction of the velocity. For example:

velocity = velocity + frictionForce

This will apply the friction force to the object and slow it down, helping to prevent it from sliding on a slope.

yes i know, i do that already thats what all the vector forces are
the new problem is shown in the video above your message
it is shaking after slowing down

I think it’s shaking after slowing down due to friction. This can be caused by a for some reasons:

  1. The object may experience external forces that are causing it to shake. For example, if the object is in contact with other objects that are moving or colliding with it, this can cause it to shake.

  2. The object may be experiencing internal forces that are causing it to shake. For example, if the object has a high center of mass or is not evenly balanced, this can cause it to shake when it comes to a stop.

  3. The friction force may be too strong or too weak, causing the object to shake as it slows down.

To fix the shaking problem, you may need to adjust the friction force or add additional forces to stabilize the object. Here are a few suggestions:

  1. Try adjusting the coefficient of friction ( props.Friction in your code) to see if a different value produces better results. You may need to experiment with different values to find the right balance.

  2. Try adding a damping force to the object to dampen the oscillation. This can be done by adding a force in the opposite direction of the object’s velocity. For example:

local dampingForce = -velocity * dampingCoefficient
velocity = velocity + dampingForce

You can adjust the damping coefficient ( dampingCoefficient ) to control the strength of the damping force.

  1. Try adding additional forces to stabilize the object, such as a force that pushes the object towards the ground. This can help to keep the object from oscillating when it comes to a stop.

there cant be any external forces
the center of mass is exactly in the middle of the base

all of the forces are simulated through math nothing is colliding with anything. as far as roblox knows this is a floating brick

i dont want to go through every part in the game and change its friction property just to make the cars work, that isnt realistic and its also annoying when i bring in other things that need normal physics

adding a damping to the friction wont solve that i tried

1 Like

That’s pretty odd then I wouldn’t expect that…

@Arylist @dthecoolest ok update

i solved the issue. thank you both for the help but the main issue was it was the suspension force

so the reason why it was moving sideways in the first place was because the suspension force was relative to the car making it sideways while on a slope and pushing in the opposite direction of the slope

i fixed it by setting the suspension vector force to be relative to the world then because that wasnt enough. it did fix that issue with sliding while on the spawnpoint but if the car went onto a ramp fully (making it tilt) it would go flying

to solve this i went back to by old code (from the original post) and it just solved it. idk why but it works so im not complaining

again thank you two for helping me out a lot, in the end it was just a dumb solution

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.