I have a BasePart with zero friction that I want to inherit the velocity of the BaseParts beneath it. When it comes to linear velocity, all I have to do is add the velocities of the BaseParts, then add whatever additional velocity I want on top of it in order to achieve my goal.
function FixedUpdate(_, deltaTime) --connected to RunService.Stepped local baseVelocity = Vector3.new() for _, part in pairs(GroundedParts) do if part.CanCollide then baseVelocity = baseVelocity + part.Velocity --there could be a better way to handle velocity by getting the average of all of the velocities but i'm too lazy to do that right now end end local additionalVelocity = Vector3.new(10, 0, 0) FinalVelocity = additionalVelocity + baseVelocity Movement.Velocity = FinalVelocity --Movement is a BodyVelocity parented to the Part end
I can also do the same thing with angular velocity and rotations, although I use a BodyGyro instead of a BodyAngularVelocity to lock the X and Z axes of rotation and make it easier to make the part face at an angle.
function FixedUpdate(_, deltaTime) --same function as before except I removed all of the unnecessary parts so this is easier on the eyes I guess local baseRotVelocity = Vector3.new() for _, part in pairs(GroundedParts) do if part.CanCollide then baseRotVelocity = baseRotVelocity + part.RotVelocity end end FinalRotation = FinalRotation * cfa(0, baseRotVelocity.Y * deltaTime, 0) Rotation.CFrame = FinalRotation end
However, I face an issue when trying to convert the angular velocity into linear velocity. No matter what I try, the rotation always seems slower or faster than the linear velocity, destroying the effect. The only thing I've seem to have gotten correct is how to calculate the direction of the linear velocity, which is perpendicular to the vector between the part that inherits the angular velocity and the part that has the angular velocity.
local function perpendicular(v) return Vector3.new(v.Z, 0, -v.X) --roblox apparently has a "right-handed" cartesian coordinate system so i have to do this which is just a negated form of Vector3.new(-v.Z, 0, v.X) end local radius = ((Character.Position - part.Position) * Vector3.new(1, 0, 1)).Unit local tangent = perpendicular(radius).Unit --there could be a better way to do this using the cross product between the y axis and the radius but i'm just going to leave it like this for now
How am I supposed to calculate the magnitude to multiply the direction by? I know that it somehow involves the angular velocity itself (which is why nothing spins when a part has an angular velocity of 0, 0, 0), but what else should I throw in there, and why?
NOTE: sorry for the bad grammar it's almost 8 pm
It seems that I was over-complicating this question for anyone to understand, so I've figured out a solution and posted it here. Converting angular velocity to linear velocity was actually easier than I thought.
In order to convert angular velocity into linear velocity, we must first get the direction of the linear velocity, which is perpendicular to the distance between the part we want to apply the angular velocity to and the part with the angular velocity.
--just imagine that part2 is the part we want to apply the velocity to and part1 is the part that has the velocity local function perpendicular(v) return Vector3.new(v.Z, 0, -v.X) end local radius = (part2.Position - part1.Position) * Vector3.new(1, 0, 1) local tangent = perpendicular(radius).Unit --this is the direction that we want the linear velocity to go in
Now that we have the direction of the linear velocity, we need to find the magnitude to multiply it by. Fortunately, the formula for the length of an arc is helpful here. We can treat the linear velocity as a line tangent to a circle that has a magnitude equivalent to the length of an arc with a central angle equivalent to the angular velocity on the Y axis.
local radius = (part2.Position - part1.Position) * Vector3.new(1, 0, 1) local tangent = perpendicular(radius).Unit --this is the direction that we want the linear velocity to go in local magnitude = radius.Magnitude * part.RotVelocity.Y --this is the length of the arc, multiplying the radius by theta, which is the part's rotational velocity on the y axis
All we have to do now is to multiply the magnitude by the direction, which gives us what I think is a nice and clean solution.
baseVelocity = baseVelocity + magnitude * tangent
Here's how it turned out.
It's funny how I spent a week trying to figure this out before going to ScriptingHelpers and then thought of a solution just a few hours after waking up the next day.