How could I make sway like this?

So for I while, I’ve been sticking to springs for sway. For a while now, I’ve been looking at @BIackShibe’s work. I really like how he did his weapon sway. It looks like something from a Triple A game.

I was wondering, how could I create an effect like this?

What I’m talking about: https://www.youtube.com/watch?v=_3WQmQkL2-M

My current sway: https://www.youtube.com/watch?v=X1d7j3RiXWs

1 Like

Problably you need to adjust the CFrame, And Add some waits, Also what do you mean by sway?, All I saw was First-Person movment…

Mhm. I’m wondering how he managed to stop the weapon from going off camera. Notice when I move the mouse all the way to the left, the weapon only goes to a certain point before stopping. Kind of limiting how far the weapon goes.

Also, sway is first person movement.

What is you’re current script right now?

Does that matter? I use springs and just shove the springs according the mouse delta. Sorry if I sound rude

Have you considered using mouse.Target?, My approach on this would be to allways check the Mouse.Target and change the CFrame for it from there, It also looks like you’re having problems with the Gun when you move yourself…, Is that true?

1 Like

Maybe try this out?

local lastCameraCF = workspace.CurrentCamera.CFrame;
local mult = 6;
local cfAng = CFrame.Angles
local sin = math.sin
local swayOffset = lastCameraCF

local function sway() --bind this to camera render loop
    local rotation = workspace.CurrentCamera.CFrame:toObjectSpace(lastCameraCF);
    local x, y, z = rotation:ToOrientation();
    swayOffset = swayOffset:Lerp(cfAng(sin(x)*mult, sin(y)*mult, 0), *.1)
    self.viewmodel.HumanoidRootPart.CFrame *= swayOffset;
    lastCameraCF = workspace.CurrentCamera.CFrame;
end
2 Likes

Hmm. It seems to give the error, Expected identifier when parsing expression, got “*” on line 10.

Any ideas?

EDIT: realized you just had an extra * by 0.1

EDIT2:

SO this is what I get: https://www.youtube.com/watch?v=s1Cu-s8-GlQ

And this is my code:

local lastCameraCF = workspace.CurrentCamera.CFrame;
local mult = 6;
local cfAng = CFrame.Angles
local sin = math.sin
local swayOffset = lastCameraCF

function handler:update(deltaTime) --bind this to camera render loop
	self.deltaTime = deltaTime
	
	Main = Main:Lerp(self.MainCF, 0.2)
	
	local rotation = workspace.CurrentCamera.CFrame:toObjectSpace(lastCameraCF);
	local x, y, z = rotation:ToOrientation();
	swayOffset = swayOffset:Lerp(CFrame.Angles(sin(x)*mult, sin(y)*mult, 0), .1)
	self.viewmodel.PrimaryPart.CFrame = swayOffset;
	lastCameraCF = workspace.CurrentCamera.CFrame;
	
	self.viewmodel.PrimaryPart.CFrame = self.camera.CFrame * Main
end

Ignore main, that’s just used to CFrame the viewmodel properly.

Was that the intended result?

Yes I have considered mouse.Target, but I thought there would be an easier solution with mouseDelta.

And no, I don’t have issues when I move myself.

You actually seem pretty close, the difference is in the damping and frequency. Increase the frequency to speed up the movement, and increasing the damping ratio to ≥ 1.

1 Like

I am pretty close?!? Hmmm. Also what do you mean by frequency. Do you mean like the mousedelta and stuff. I just don’t know how I’m close to achieving that.

Do you mind explaining a little more deeply?

Thanks for the reply!

Springs have a few different properties, above I am referring to the springs frequency and damping.

Based on the code you have shared above, it looks like you’re lerping to a goal rather than using an actual spring.

There’s some examples on GitHub you can find such as https://github.com/Fraktality/Spring/blob/master/Spring.lua which you can use instead.

The library doesn’t work with CFrames directly so you’ll need to adjust your code as necessary to use vectors or numbers.

1 Like

(if I didn’t unlock the gun from the center of the screen, the sway would be indentical to yours btw)

use a lot of educated guesses, your main tools being sin(), lerp values (the stuff that makes the gun go down when you look up), CFrame:ToWorldSpace, and CFrame.Angles


(I have no guarantees to the code above being a product of a sober human being)

4 Likes

Wow, a response from the doggo himself. Thank you so much! I guess I have to learn how to unlock the gun from the center of the screen.

Also, thanks a lot for the screenshot, it’ll help me get a better understanding on where to start.

Again, thank you for the response!

That’s a bad way to say the gun just has a box of rotation it revolves around, you just store separate x and y coordinates you influence with mouse delta and clamp to add walls and move the gun based off of

1 Like

Ahh, I noticed that! So you’re saying that I store x/y coordinates for the box, and don’t let the mousedelta go past that? Or like at least minimize the mousedelta to that?

minimize the coordinates themselves
self.directionalModifier = Vector3.new(math.clamp(self.directionalModifier.x, xM, xMX), math.clamp(self.directionalModifier.y, yM, yMX), self.directionalModifier.z)
9123912319th ugly line in the :update() function

1 Like

Back again, with yet another problem.

I found that I could make the viewmodel face towards mousedelta/200 and it works quite well.
The issue is, I cannot seem to reverse the sway, meaning that the sway goes reverse to where I look. So I if I were to look to the right, the gun would move to the left.

Example: https://www.youtube.com/watch?v=0p3-P2p--1E

Code:

local mult = 6;
local cfAng = CFrame.Angles
local sin = math.sin


function handler:update(deltaTime) --bind this to camera render loop
	local lastCameraCF = workspace.CurrentCamera.CFrame;
	local swayOffset = lastCameraCF
	
	self.mouseTarget = Player:GetMouse().Target
	self.mouseHit = Player:GetMouse().Hit
	
	
	local mouseDelta = game:GetService("UserInputService"):GetMouseDelta()
	if aiming == true then mouseDelta = mouseDelta * 0.1 end
	
--	print(mouseDelta.x)
	
	local deltaCF = CFrame.new(mouseDelta.x/200, mouseDelta.y/200, 0)
	
	self.unlockedSway = deltaCF
	
	
	
	self.deltaTime = deltaTime
	
	Main = Main:Lerp(self.MainCF, 0.2)
	
	local rotation = workspace.CurrentCamera.CFrame:toObjectSpace(lastCameraCF);
	local x, y, z = rotation:ToOrientation();
	swayOffset = swayOffset:Lerp(CFrame.Angles(sin(x)*mult, sin(y)*mult, 0), .1)
	self.viewmodel.PrimaryPart.CFrame = swayOffset;
	lastCameraCF = workspace.CurrentCamera.CFrame;
	
	self.viewmodel.PrimaryPart.CFrame = self.camera.CFrame * Main
	
	--deltaCF = CFrame.new(math.clamp(deltaCF.x, 0, 0), math.clamp(deltaCF.y, 0,0), deltaCF.z)
	
	print(deltaCF.x)
	
	 
	--self.viewmodel.PrimaryPart.CFrame = self.viewmodel.PrimaryPart.CFrame:ToWorldSpace(CFrame.new(deltaCF.Position.x,deltaCF.Position.y,deltaCF.Position.z))
	
	--self.viewmodel.PrimaryPart.CFrame *= CFrame.Angles(0,-self.unlockedSway.Position.x,-self.unlockedSway.Position.y)
	
	--self.viewmodel.PrimaryPart.CFrame = CFrame.new(self.unlockedSway.x,self.unlockedSway.y,self.unlockedSway.z)
	
	--self.viewmodel.PrimaryPart.CFrame *= CFrame.Angles(-deltaCF.Position.y,-deltaCF.Position.x,-deltaCF.Position.z)
	
	self.viewmodel.PrimaryPart.CFrame = CFrame.new(self.viewmodel.PrimaryPart.Position, self.unlockedSway.Position)
end

Changing mousedelta to negative doesn’t seem to do anything.

Edit: I haven’t clamped stuff yet, just trying to “unlock” the gun.

CFrame.new(mouseDelta.x/200, mouseDelta.y/200, 0) => CFrame.new(-mouseDelta.x/200, mouseDelta.y/200, 0)?