Trying to simulate weapon sway

I want to achieve weapon sway for my first person game. I have this update event that is executed upon screen refresh, and this positions a local model of the player’s arms to the player’s camera

local function onUpdate(dt)
	viewModel.Head.CFrame = camera.CFrame
	-- update every frame so the arms stay in place when the player aims down sights
	updateArm("Right")
	updateArm("Left")
	updateArm("LeftGrip")
end

I then made a table containing CFrame values, and the current camera CFrame is added to it on screen refresh. The update then puts the viewModel at the last index of the list - 1 to make a delay between the camera movement and the viewModel adjusting.

local CposQueue = {}

local function onUpdate(dt)
	CposQueue[#CposQueue + 1] = camera.CFrame
	
	viewModel.Head.CFrame = CposQueue[#CposQueue - 1] or CposQueue[1];
	-- update every frame so the arms stay in place when the player aims down sights
	updateArm("Right");
	updateArm("Left");
	updateArm("LeftGrip");
end

The problem is, this simply isnt smooth.

https://i.gyazo.com/0379d9515d5fbb56e5ac52bfd07e7fb1.mp4

Is there perhaps anyone who knows how to fix this? I would be very greatful!

1 Like

Well, looking at your code, you should be using TweenService and tweening the CFrame of the head

1 Like

Will TweenService work when used on every frame update?

Every frame update? That’s a lot, I don’t really know, but tweenservice grants smoothness (I don’t know if tweenservice will break the computer if you use it too fast)

I will attempt to integrate this. Wish me luck!

1 Like

TweenService does not appear to be moving my viewModel in any way
@VegetationBush

local function onUpdate(dt)
	CposQueue[#CposQueue + 1] = camera.CFrame
	
	
	local info = TweenInfo.new(0.1)
	local goal = {CFrame = CposQueue[#CposQueue - 1] or CposQueue[1]}
	local newTween = Tween:Create(viewModel.Head, info, goal)
	
	newTween:Play();
	-- update every frame so the arms stay in place when the player aims down sights
	updateArm("Right");
	updateArm("Left");
	updateArm("LeftGrip");
end

Do you know why this is?

If anyone knows how to use TweenService in this context, is there anything wrong with this script, or is there some problem with making a Tween every screen update?

I think the problem is is that you are creating too many tweens at once, and the tweens are overriding each other, so I would suggest lowering this line

to something like this:

local info = TweenInfo.new(0.05)
1 Like

This has not worked ;-;
The weapon is still floating in space, no motion of any kind is being applied to it

It looks fine. I’d assume since it’s running so many times a second it keeps overriding the previous tween, causing it to not look like it’s moving.

One thing you could try is to bind the newly created tween object to a Completed event, then when that function runs you could set a variable to true. In your function which I assume is bound to a RenderStep, you could have it check to see if that variable isn’t assigned to, and if so, set it to true and run which ever tween you want. Then, when that tween finishes it’s execution, the Completed event will fire and then you’d set that variable accordingly to get another tween to play.

This might help. Even if this isn’t the reason this code isn’t working, this will help you in terms of getting it to not override other playing tweens; it should run smoother.

1 Like

This, though very thoughtful (thank you), has not worked ;-;

I added in an output that confirms that the viewmodel has not moved in any way. The finished event is firing, new tweens are being made, its just that for some reason, they simply arent moving the model.

The only other option is to decrease the amount of updates(so don’t update it every frame) and/or decrease the animation time.

I tried that, but it did still did not move. Somewhere in there, i am doing this incorrectly. I will look at examples and see if i am making any mistakes.

I tried Instantiating a CFrame Value and then tweening its value, constantly setting the CFrame of the viewModel to that value. For some reason, this works very well while directly tweening the model does not (my guess is that the Head part in the viewModel has motor6ds connected to it, and this could take priority over the tween).

3 Likes

Try to use CFrame:Lerp(), you can learn more about it here: