So the question is pretty straight to the point,

What’s the best way to make gun sway?

Should I use an animation?

I saw someone mention using sine waves.

What’s the best way?

Thanks in advance

So the question is pretty straight to the point,

What’s the best way to make gun sway?

Should I use an animation?

I saw someone mention using sine waves.

What’s the best way?

Thanks in advance

14 Likes

Animations would work on loop. You could also generate random numbers and tween / cframe stuff in the respective direction.

2 Likes

Ill try animations. I’ll loop it and use easing in and such. Thanks!

1 Like

Usually gun sways are done using damped harmonic oscillators (springs) or spring constraints. Animations wouldn’t really accomplish what you need since they’re concrete and tweening would require custom easing implementations and overrides.

2 Likes

What I did is use sin waves to generate smooth recoil.

```
local mult = 1
local swayOffset = CFrame.new()
local lastCameraCF = workspace.CurrentCamera.CFrame
function renderloop() --bind this camera render loop
local rotation = workspace.CurrentCamera.CFrame:toObjectSpace(lastCameraCF) --get cframe delta.
local x,y,z = rotation:ToOrientation() --I'm sure there are better ways to get rotation but this will work for now.
swayOffset = swayOffset:Lerp(CFrame.Angles(math.sin(x)*mult,math.sin(y)*mult,0), 0.1) --calculate the sway using SIN
gun.CFrame = gun.CFrame * swayOffset --apply the sway
lastCameraCF = workspace.CurrentCamera.CFrame --update the last cframe
end
```

This *should* get you nice and smooth recoil to any object you apply it to. Here is a video of it being applied in my framework (mult = 6):

(Sorry for not having tabs in the code example, when I pressed tab it didn’t want to place it.)

76 Likes

Hey there!

I’m a little new to scripting. I’ve binded your curve function, but I’m not sure how to get the lastCameraCF. Help?

Thanks!

1 Like

I think just before the loop, you can write this line:

`lastCameraCF = workspace.CurrentCamera.CFrame --update the last cframe`

Then you should have the initial camera CFrame. I don’t remember exactly what I did anymore, I remember changing a lot and adding to it a little.

4 Likes

I am going to get my toes cut off for bumping this topic but, I’m not exactly sure how to implement this into my existing framework, if I multiply the gun CFrame by swayoffset it does nothing.

My code:

```
local mult = 6
local swayOffset = CFrame.new()
local lastCameraCF = workspace.CurrentCamera.CFrame
local rotation = workspace.CurrentCamera.CFrame:toObjectSpace(lastCameraCF) --get cframe delta.
local x,y,z = rotation:ToOrientation() --I'm sure there are better ways to get rotation but this will work for now.
swayOffset = swayOffset:Lerp(CFrame.Angles(math.sin(x)*mult,math.sin(y)*mult,0), 0.1) --calculate the sway using SIN
lastCameraCF = workspace.CurrentCamera.CFrame --update the last cframe
local guncf = (
lastCameraCF*swayOffset*
gunset.camcoord* -- General gun offset
script.Walk.Value* -- Walk animation offset
script.Aim.Value* -- Aim offset
roffset* -- Reload offset
recoil -- And the reload offset
)
loadout.current:SetPrimaryPartCFrame(guncf) -- Loadout.current is the players current gun, for context
```

Removing every other offset applied doesn’t make a change either. I can’t tell what I messed up?

Also this is put in a renderstepped function, and the swayoffset is changing, since it will print the cframe if I print it

2 Likes

just use

```
local function getBobbing(addition, speed, modifier)
return math.sin(tick() * addition * speed) * modifier
end
```