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