Hey there! I have a problem that is way too advanced for me.
Basically, I have a part with absolutely no friction. How would I stop this part from sliding down a slope?
This is what I tried to do:
local movement = -rayNormal
part:ApplyImpulse(movement)
This obviously doesn’t really seem to work, so are there any other ways to achieve this?
Any help is appreciated!
And how would I translate this into a force? This is what I tried to do:
local rVector = (-Vector3.yAxis):Cross(rayNormal)
local movement = CFrame.fromMatrix(part.Position, rVector, rayNormal).Position
local finalVector = movement*deltaTime
part:ApplyImpulse(finalVector)
Sorry if it’s a simple thing, I’ve never really worked with Roblox forces before.
I would like to know your usecase - why do you want to prevent a frictionless object from sliding down a slope? That makes very little physical sense. Applying a force to counteract gravity would prevent it from being pulled downward, but it would also disable the gravitational forces applied to it entirely; this would result in the part flying away into oblivion anytime it comes into contact with another part.
Either way, you can get the force of gravity applied to a part as such:
local gravityForce = part:GetMass() * workspace.Gravity
The reason I’m doing this is for a movement system. I just push a part towards a move direction and use :ApplyImpulse to move it forward/apply a counterforce. The main problem I am facing is that the part always slides down slopes since I made it frictionless. But of course, this poses a problem, as the player just slides down slopes very easily. The player has to be frictionless to make sure it glides around the ground properly. I explained it like this because I thought it might be a bit easier to understand.
Ah, thanks for clarifying. That’s actually a pretty nasty problem I never quite figured out how to fix in my own (currently broken) physics system. There are most likely better ways of going about this, but I would just decouple from Roblox’s physics system entirely and calculate the player’s physics manually. Or manually set the player’s position when they have a non-zero movement input. It is a dirty solution, but movement in most video games doesn’t actually make much sense because we don’t just slide on the ground when moving in real life, we apply several complex forces in several directions to propel ourselves forward.
I’m thinking of this as a player on ice and when you bump into say an ice block the block get launched away from the player where the block is then free to slide around based on it’s velocity. You want the blocks to stop moving after a certain amount of time(what condition?) regardless of the surface it’s resting on? Am I even close to picturing this correctly?
A part still has physics when anchored, it’s just fixed in space. While anchored you can still collide/touch it and other parts will react with it but it will not react to them. As soon as you un-anchor it, it goes back to reponding to physics forces.
On touched/short raycast (however you find your part) un-anchor the part (if anchored) and lauch it as you do. The part moves as you have it now. Set a cooldown, re-anchor it and the part “freezes” in place. Watch the parts velocity after launch and when below a certain value i.e. pretty much not moving or the cooldown expires or both, verify it’s touching the ground (if that’s what you want) then anchor it in place. Possibly un-anchor again afterwards depending on how you want the part(s) to settle.
Again, I could be thinking way too simple but anything else I can think of off the top (without seeing the code/knowing more) is likely to be more of a trick the engine vs use the engine features.
So you want gravity to pull the part towards the surface so that it doesn’t go flying, but you don’t want gravity to pull it parallel to the surface?
You could calculate the direction of the gravity component parallel to the surface using the cross product method @dthecoolest suggested. However, another option is projecting gravity to the plane by subtracting the gravity component that is perpendicular to the plane so that only the parallel component will remain. The component perpendicular to the plane is the component parallel to the plane normal.
So, to project a vector to a plane, we need to first project it to the plane normal vector and then subtract this projection from it.
Dot product of a vector u and a unit vector v tells how many coordinate units we move in the direction of v when we move from the start point of u to the end point of u. So by multiplying v with this dot product, we get the component of u that is parallel to v.
local function projectVectorToVector(vectorToProject: Vector3, vectorToProjectTo: Vector3): Vector3
local unitOfVectorToProjectTo: Vector3 = vectorToProjectTo.Unit
local projectedVector: Vector3 = vectorToProject:Dot(unitOfVectorToProjectTo) * unitOfVectorToProjectTo
return projectedVector
end
local function projectVectorToPlane(vectorToProject: Vector3, planeNormalVector: Vector3): Vector3
return vectorToProject - VectorProjection.projectVectorToVector(vectorToProject, planeNormalVector)
end
local function getGravitySlidePreventionForce(part: BasePart, surfaceNormal: Vector3): Vector3
local gravity: Vector3 = part:GetMass() * Vector3.new(0, -workspace.Gravity(), 0)
local gravityProjectedToPlane: Vector3 = projectVectorToPlane(gravity, surfaceNormal)
return -gravityProjectedToPlane
end
You can use a VectorForce instance to apply this force. You’ll need to update the force when the surface normal changes. BasePart:ApplyImpulse should not be used for this if I’ve understood correctly what you want.