So I’m wondering if there is a Spring Modules but with CFrame. I’m trying to do some spring stuff with my viewmodel and it uses Vector3 which can cause problems.

There is TweenService and `:Lerp`

but if you are looking for a spring module there’s Flipper. It’s based around Motors and goals.

I would honestly recommend just doing the first two options.

Although a vector3 usually represents the displacement of a spring, for a swaying viewmodel I believe you can make the vector3 represent the **angular displacement** of the view model rotation, in a similar manner to this:

I’ll see if I can work a solution to this seems interesting.

Here made something, cool to spring up your FPS view model:

It’s a local script which uses Quenty’s spring module to add a spring effect to the otherwise static view model.

Before spring:

After Spring:

Code, insert into your starterCharacter scripts as a local script and test it out. Values for the spring will need adjusting of course.

–Edit: Here’s a better working version with the dampening actually working, messed up the previous CFrame calculation. Still have no idea how to limit the rotation with the spring forces following in suite. Also the video I posted is old and doesn’t contained the fixed changes but am too lazy to reupload so try it out yourself.

Edit 2: Updated it with viewmodel clamping and removed the nan error:

```
local part = Instance.new("Part")
part.Size = Vector3.new(0.5,0.5,2)
part.Anchored = true
part.CanCollide = false
part.Parent = workspace
local cameraOffset = CFrame.new(0.8, -0.6, -2.2)
local camera = workspace.CurrentCamera
local RunService = game:GetService("RunService")
local Spring = require(script:WaitForChild("Spring"))
local ZEROVECTOR =Vector3.new()
local viewmodelSpring = Spring.new(ZEROVECTOR)
viewmodelSpring.Speed = 5
viewmodelSpring.Damper = 0.25 --1 is perfect dampening
local function clampMagnitude(vector, maxMagnitude)
return (vector.Magnitude > maxMagnitude and (vector.Unit * maxMagnitude) or vector)
end
function angleBetween(vector1, vector2)
return math.acos(math.clamp(vector1.Unit:Dot(vector2.Unit), -1, 1))
end
local deltaSensitivity = -2 -- increases force from mouse delta
--if negative force goes in opposite direction, viewmodel is lagging behind
local maxAngle = 30 --degrees
local previousGoalCFrame = CFrame.new()
RunService.RenderStepped:Connect(function(step)
local goalCFrame = camera.CFrame*cameraOffset
part.CFrame = goalCFrame
--Spring stuff
local differenceCF = previousGoalCFrame:ToObjectSpace(goalCFrame)
local axis, angle = differenceCF:ToAxisAngle()
local angularDisplacement = axis*angle
previousGoalCFrame = goalCFrame
local springForce = angularDisplacement*deltaSensitivity
viewmodelSpring:Impulse(springForce)
local partSpringOffset = viewmodelSpring.Position
local axis = partSpringOffset.Unit
local angle = partSpringOffset.Magnitude
--clamp the angle don't want it to speen 360 degrees unless you want it to
--velocity goes wild though
angle = math.deg(angle)
if angle > maxAngle then
--print("Clamped")
--local maxAngularDisplacement = axis*angle
local currentViewModelVelocity = viewmodelSpring.Velocity
local collision = math.sign(currentViewModelVelocity:Dot(axis))
--1 is colliding, -1 is going away from colliding wall normal
if collision > 0 then
local reactionAngle = angleBetween(currentViewModelVelocity.Unit,axis)
local resolve = math.cos(reactionAngle)
local reactionForce = -axis*currentViewModelVelocity.Magnitude*resolve
viewmodelSpring:Impulse(reactionForce)
end
end
angle = math.clamp(angle,0,maxAngle)
angle = math.rad(angle)
if angle > 0.001 then--Nan check checking if there is no spring caused rotation
part.CFrame *= CFrame.fromAxisAngle(axis,angle)
end
end)
```

Woah, what an awesome module! Kinda disappointed I haven’t heard about this module earlier but glad I knew about it today!

Yeah I like the module because it uses os.clock() and cool metatable stuff.

I think an easier way of doing this is to use the mouse delta to get the shoving force direction and magnitude instead of my overly complicated CFrame approach from this really neat FPS tutorial which I should have looked at earlier .

```
-- Let's get some mouse movement!
local mouseDelta = game:GetService("UserInputService"):GetMouseDelta()
self.springs.sway:shove(Vector3.new(mouseDelta.x / 200,mouseDelta.y / 200)) --not sure if this needs deltaTime filtering
--vs my wut CFrame approach
local differenceCF = previousGoalCFrame:ToObjectSpace(goalCFrame)
local axis, angle = differenceCF:ToAxisAngle()
local angularDisplacement = axis*angle
previousGoalCFrame = goalCFrame
local springForce = angularDisplacement*deltaSensitivity
viewmodelSpring:Impulse(springForce)
```

And to convert the spring force into bobbing you can just use CFrame.Angles instead of CFrame.fromAxisAngles, I believe the CFrame Angles approach gets rid of the rolling rotation as well if thats what you are looking for:

```
--tutorial sway method:
local sway = self.springs.sway:update(deltaTime)
self.viewmodel.rootPart.CFrame *= CFrame.Angles(0,-sway.x,sway.y)
--my CFrame from axis angle method:
local partSpringOffset = viewmodelSpring.Position
local axis = partSpringOffset.Unit
local angle = partSpringOffset.Magnitude
part.CFrame *= CFrame.fromAxisAngle(axis,angle)
```

Edit: I do like axis angles a lot.

you literallty just saved me 1000 hours of coding thank you