How to make smooth first person arms?

I am working on a knife system, and to spoof it up a bit, I’ve added a first person arms for players who prefer first to third person gameplay. Currently it follows the knife animations, though it is static in that it sticks with the camera. Which is fine on its own, but I would like to go one step further to make it prettier.

So, my goal is to have smooth, fluid motion in the arms whenever the player turns his or her camera to the left or the right.

The game KAT has a good demonstration of what I am aiming for:

I have tried using TweenService and linear interpolation (though may have been incorrectly, I’m not sure). Each method I have tried results in sorta what I want, but it’s not smooth. It is very choppy and visibly hard to watch.

If you have any suggestions or have any tips on ways to achieve this, I would be very grateful. Thank you.

  • Galactiq
2 Likes

What you are looking for is commonly called “weapon sway”
This is how I would implement it:

  1. Find how much the camera has moved compared with the last frame
  2. Interpolate arms accordingly
local oldCamraCFrame = CFrame.new()
local swayCFrame = CFrame.new()

game.RunService.RenderStepped:Connect(function()

  --Step 1
  local x,y,_ = OldCameraCFrame:ToObjectSpace(workspace.CurrentCamera.CFrame):ToEulerAnglesXYZ()
  SwayCFrame = SwayCFrame:Lerp(CFrame.Angles(x,y,0), 0.1)
  OldCameraCFrame = workspace.CurrentCamera.CFrame

  --Step two
  --However you set the arms model cframe, just * the SwayCFrame to it
  armsModel.CFrame = workspace.CurrentCamera.CFrame * SwayCFrame 

end)

Outcome:

Hope this helps!

4 Likes

See I thought it would be something like this, however it’s still choppy looking. The code in KAT has it very smooth, which is the goal. Thank you for your answer!

Edit: I will go ahead and implement it and see how it looks.

It might look choppy because I used Gyazo (A .gif maker) to record the clip.
If it’s still too choppy after implementation, you could always play around with the second parameter on the :Lerp() function.

There are many issues with this code. I do appreciate your response, however it is not what I am looking for.

It goes the opposite way I desire (turning left should make the knife shift right, not left as well).(fixed)
It is very choppy.
When moving quickly, it bugs out.

KAT uses springs.
An FPS tutorial has a very good implementation of springs to get the same style of movement sway.

Hope this helps!

3 Likes

Yep this is exactly it, that tutorial is really good I learnt a lot from it. This should be the answer.

However if you are interested in only the spring portion I have isolated it and created an script to play around with. (With my own CFrame rotation method which is similar yet different)

Example code here see edit 3, lots of variables to play around with and tune it:

However @RazorWinds_Dev was also on the right track

Yep the tutorial also does that. Though the tutorial uses mouse delta which also coincidentally correlates with the camera movement.

		-- 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)
2 Likes

I can never look at that style and not think of half life.
Great stuff, thanks for sharing!

1 Like