I want my character to lean backwards depending on how quickly they are falling through the air. Whenever I try setting the CFrame of the character it flings them. Preferably, I don’t want to use BodyGyro to achieve this.
I think I can do something with the Y magnitude I got but I have no clue what else to do.
So, for what you’re doing, you’d actually want to manipulate the CFrame of the Character.HumanoidRootPart's Motor6D instead of changing it’s angle directly. This way, it won’t fling the player or glitch the player out when the HumanoidRootPart is modified. You’re also on the right track with using the Y velocity.
And in order to continuously change the angle, we have to connect it to a RunService.Heartbeat. The reason why we have to connect it to Heartbeat is because we want it to be fired AFTER each physical frame has been processed.
Now we know what thing’s we’d have to use, how do we start calculating and putting it to action? What you’d want to do is:
Get the original CFrame of the Motor6D
Clamp the angle to a certain degree, since it’ll look weird if the player spins while in the air.
When they’re not falling, if HumanoidRootPart.AssemblyLinearVelocity.Y >= 0, have it go back to its original angle.
Now, this script can be parented to StarterPlayer.StarterPlayerScripts/StarterCharacterScripts.
local RunService = game:GetService("RunService")
local Player = game.Players.LocalPlayer
local Character = Player.Character or Player.CharacterAdded:Wait()
local Humanoid = Character:WaitForChild("Humanoid")::Humanoid
local HumanoidRootPart = Character.PrimaryPart
local RootM6D:Motor6D = Character.LowerTorso.Root -- If Character is R15
or HumanoidRootPart.RootJoint -- If Character is R6
local OriginM6DCF = RootM6D.C0 -- The original CFrame of the motor. (we're using this later)
local FallProperties = {
maxLeanDegrees = 45, -- In degrees. This may not be realistic
elapsedFallTime = 0.2, -- This helps interpolate the sudden change of degrees when they're falling.
elapsedRecoverTime = 0.1, -- This helps interpolate the time it takes to go back to it's original rotation.
-- I'm really bad at explaining this but, interpolation is basically smoothing out the products of
-- two items via multiplying them (between 0 to 1 usually). You should search it up to fully
-- grasp it's purpose.
}
RunService.Heartbeat:Connect(function()
-- This is how we'll know they're actually falling down instead of jumping/going up.
if HumanoidRootPart.AssemblyLinearVelocity.Y <= 0 then
local yMagnitude = (HumanoidRootPart.AssemblyLinearVelocity * Vector3.new(0,1,0)).Magnitude
local momentum = math.clamp(yMagnitude, 0, FallProperties.maxLeanDegrees)
RootM6D.C0 = RootM6D.C0:Lerp(CFrame.Angles(math.rad(momentum),0,0), FallProperties.elapsedFallTime)
else
RootM6D.C0 = RootM6D.C0:Lerp(OriginM6DCF, FallProperties.elapsedRecoverTime)
end
end)