Im attempting to make a simple FPS viewmodel with dynamic movement, Ive started with tilting the Viewmodel based if youre moving left or right
It mostly works, as it tilts smoothly and returns back to normal as intended, but if I keep walking in a direction, it goes over the max I set?
Code for this:
RunService = game:GetService('RunService')
-- Var
Camera = workspace.CurrentCamera
Thing2Clone = ReplicatedStorage:FindFirstChild('GunTestBasic')
Player = script.Parent.Parent
Character = Player.Character
Humanoid = Character:FindFirstChild('Humanoid')
-- Init
Viewmodel = Thing2Clone:Clone()
Viewmodel.Parent = Camera
-- Tilt Variables
LastTiltCFrame = CFrame.new()
TiltCFrame = CFrame.new()
LeftMax = CFrame.Angles(0, 0, 10)
RightMax = CFrame.Angles(0, 0, -10)
function ViewmodelCalibration()
--////LEFT & RIGHT TILT////--
local Tilt = Humanoid.MoveDirection:Dot(Camera.CFrame.RightVector)
if Tilt < 0 then TiltCFrame = LastTiltCFrame:Lerp(RightMax, 0.0015)
elseif Tilt > 0 then TiltCFrame = LastTiltCFrame:Lerp(LeftMax, 0.0015)
elseif Tilt == 0 then TiltCFrame = LastTiltCFrame:Lerp(CFrame.Angles(0, 0, 0), 0.075) end
LastTiltCFrame = TiltCFrame
--////LEFT & RIGHT TILT////--
Viewmodel:PivotTo(
Camera.CFrame * TiltCFrame
)
end
-- Runservice
RunService:BindToRenderStep("ViewModel", 301, ViewmodelCalibration)
(theres also a few problems with the “Tilt” variable as itll sometimes go left or right even when im just moving forward)
For the interval if you want it to be more accurate with delta time use 1 - 0.0005 ^ dt you can adjust the speed it keeps by changing 0.0005 to be closer or further away from zero
CFrame.Angles measures in radians, not degrees, so a value of 10 is much higher than you might think it is. It can be fixed by putting math.rad around your values:
If you’re trying to make your character turn based on it’s momentum, you’ll need to:
Get the direction of movement
Get the momentum
Modify the momentum. Get rid of the Y value, and clamp the X and Z.
Multiply the direction by the momentum to get the x and z angles
Lerp HumandoidRootPart.RootJoint.C0 to be the originalC0 times CFrame.Angles(x,0,z), amount is dt times some speed value.
-- Services
local RunService = game:GetService("RunService")
-- Constants
local MOMENTUM_FACTOR = 0.02
local MIN_MOMENTUM = 0
local MAX_MOMENTUM = math.huge
local SPEED = 15
-- Function to calculate momentum
local function calculateMomentum(velocity)
-- Calculate momentum based on velocity
return Vector3.new(
math.clamp(math.abs(velocity.X), MIN_MOMENTUM, MAX_MOMENTUM),
0,
math.clamp(math.abs(velocity.Z), MIN_MOMENTUM, MAX_MOMENTUM)
) * MOMENTUM_FACTOR
end
-- Function to calculate angles
local function calculateAngles(direction, momentum, rigType)
-- Calculate angles for rotation based on direction, momentum, and rig type
local x = direction.X * momentum.X
local z = direction.Z * momentum.Z
return rigType == Enum.HumanoidRigType.R15 and {z, 0, -x} or {-z, -x, 0}
end
-- Function to update m6d.C0
local function updateRootJointC0(rootJoint, originalRootJointC0, angles, dt)
-- Interpolate and update the position and orientation of m6d.C0
rootJoint.C0 = rootJoint.C0:Lerp(originalRootJointC0 * CFrame.Angles(unpack(angles)), dt * SPEED)
end
-- Main function
local function main()
-- Get the character
local character = script.Parent
if character:IsA('Model') then
-- Get humanoid and humanoidRootPart
local humanoid = character:WaitForChild('Humanoid')
local humanoidRootPart = character.HumanoidRootPart
-- Determine m6d based on RigType
local rootJoint = humanoid.RigType == Enum.HumanoidRigType.R15 and character.LowerTorso.Root or humanoidRootPart.RootJoint
local originalRootJointC0 = rootJoint.C0
-- Heartbeat connection to update character movement
RunService.Heartbeat:Connect(function(dt)
-- Calculate direction and velocity
local direction = humanoidRootPart.CFrame:VectorToObjectSpace(humanoid.MoveDirection)
local velocity = humanoidRootPart.Velocity
-- Calculate momentum and angles
local momentum = calculateMomentum(velocity)
local angles = calculateAngles(direction, momentum, humanoid.RigType)
-- Update m6d.C0
updateRootJointC0(rootJoint, originalRootJointC0, angles, dt)
end)
end
end
-- Run main function
main()