Need help adding spring limit to my FPS viewmodel sway

Im working on viewmodel sway system using Hookes law, based on @EgoMoose tutorial that you can see here:

Heres how it works so far:

The problem is that when you move your mouse too far, the viewmodel cant catch up and eventually you’ll see the end of the arms. (And it just doesnt look that good.)
I want to apply a “length” limit to the spring so the viewmodel stays close to the crosshair while keeping the springy motion.

This is the code i use for my viewmodel rendering

local postarget = camera.CFrame.p
local anglecurrent, anglevelocity, angletarget = WeaponSystem.CurrentRig.PrimaryPart.CFrame.LookVector, Vector3.new(), camera.CFrame.LookVector
	WeaponSystem.CurrentRender = RunService.RenderStepped:connect(function(deltaTime)
		deltaTime = deltaTime*60
		local k, friction = 0.05*deltaTime, 0.3
		local armscf = WeaponSystem.CurrentRig.PrimaryPart.CFrame
		local cameracf = camera.CFrame
		--This is the spring logic, it calculates the LookVector for my CFrame.
		local angledistance = (angletarget - anglecurrent)
		local angleforce = angledistance * k
		anglevelocity = (anglevelocity *(1-friction))+angleforce
		anglecurrent = armscf.LookVector+anglevelocity
		--Make CFrame components
		local forwardVector = ((cameracf.p+anglecurrent) - (cameracf.p)).unit
		local CameraupVector = cameracf.UpVector
		local rightVector = forwardVector:Cross(CameraupVector)
		local upVector = rightVector:Cross(forwardVector)
		--Set CFrame
		WeaponSystem.CurrentRig:SetPrimaryPartCFrame(CFrame.fromMatrix(cameracf.p, rightVector, upVector))
		angletarget = cameracf.LookVector
	end)

I know it sounds like im asking for code, but im not good at physics and i tried for at least a week to find a solution that i could understand…
I searched a lot of articles about Hookes law, tried other spring techniques and nothing really worked for me.
I didnt want to cheaply ask for help here, but i dont have many options now.

I would greatly appreciate any help!

4 Likes

Well, looks like nobody knew how to help me, but luckly i found a solution myself.
Ill explain it in case somebody will have a similar problem.
Heres the code:

local postarget = camera.CFrame.p
local anglecurrent, anglevelocity, angletarget = WeaponSystem.CurrentRig.PrimaryPart.CFrame.LookVector, Vector3.new(), player.Character.Camera.CFrame.LookVector
local anglemaxdistance = 0.15
WeaponSystem.CurrentRender = RunService.RenderStepped:connect(function(deltaTime)
	deltaTime = deltaTime*60
	local ak, afriction = 0.05*deltaTime, 0.175
	local armscf = WeaponSystem.CurrentRig.PrimaryPart.CFrame
	local cameracf = camera.CFrame
	if Character.isSprinting then 
		cameracf = cameracf*CFrame.Angles(math.rad(350), 0, 0) 
	elseif WeaponSystem.Gun.isADS then
		ak, afriction = 0.05*deltaTime, 0.4
		cameracf = cameracf * WeaponSystem.Gun.Model.Sight.SightPos.Offset.Value
	end
	--Spring
	angletarget = cameracf.LookVector
	local angledistance = (angletarget - anglecurrent)
    -----This is the solution-----
	local maxdistance = angledistance.unit*anglemaxdistance
	if angledistance.magnitude > maxdistance.magnitude then
		angledistance = maxdistance
		anglecurrent = cameracf.LookVector - angledistance
	else
		anglecurrent = armscf.LookVector
	end
    -----
	local angleforce = angledistance * ak
	anglevelocity = (anglevelocity *(1-afriction))+angleforce
	anglecurrent = anglecurrent+anglevelocity
	--Make CFrame components
	local forwardVector = ((cameracf.p+anglecurrent) - (cameracf.p)).unit
	local CameraupVector = cameracf.UpVector
	local rightVector = forwardVector:Cross(CameraupVector)
	local upVector = rightVector:Cross(forwardVector)
	--Set CFrame
	WeaponSystem.CurrentRig:SetPrimaryPartCFrame(CFrame.fromMatrix(cameracf.p, rightVector, upVector))
end)

My solution was to set the Vector target before any spring calculations, then calculating maxdistance between our target and current angle. If the distance is higher than max - set the distance to max and set current angle at maximum position.

Heres how it looks now:

Tbh, im dissapointed of myself that i couldn’t think of it faster, but i hope this will help somebody.

21 Likes