Sway Spring not bouncy enough

Hey guys, im trying to make a gun framework. I’ve gotten pretty far, my only problem is the sway right now. It’s too instantaneous. I can’t make it any bouncier. It pretty much goes back to the same place instantly. Any help?

Here are some videos:

https://i.gyazo.com/d3b58afce93ff868350166b643bb7120.gif

this is what i currently have.
How do i make it a little more bouncy? Changing the springs script and messing with that has not worked at all.

springs script:

-- Constants

local ITERATIONS	= 8

-- Module

local SPRING	= {}

-- Functions 

function SPRING.create(self, mass, force, damping, speed)
	local spring	= {
		Target		= Vector3.new();
		Position	= Vector3.new();
		Velocity	= Vector3.new();
		
		Mass		= mass or 5;
		Force		= force or 5;
		Damping		= damping or 0;
		Speed		= speed  or 4;
	}
	
	function spring.shove(self, force)
		local x, y, z	= force.X, force.Y, force.Z
		if x ~= x or x == math.huge or x == -math.huge then
			x	= 0
		end
		if y ~= y or y == math.huge or y == -math.huge then
			y	= 0
		end
		if z ~= z or z == math.huge or z == -math.huge then
			z	= 0
		end
		self.Velocity	= self.Velocity + Vector3.new(x, y, z)
	end
	
	function spring.update(self, dt)
		local scaledDeltaTime = math.min(dt,1) * self.Speed / ITERATIONS
		
		for i = 1, ITERATIONS do
			local force			= self.Target - self.Position
			local acceleration	= (force * self.Force) / self.Mass
			
			acceleration		= acceleration - self.Velocity * self.Damping
			
			self.Velocity	= self.Velocity + acceleration * scaledDeltaTime
			self.Position	= self.Position + self.Velocity * scaledDeltaTime
		end
		
		return self.Position
	end
	
	return spring
end

-- Return

return SPRING

Script for the gun:

local Player = game:GetService("Players").LocalPlayer

local fps = 0

Player.CharacterAdded:Connect(function(Character)
	
print(Player.Name.." has joined the Game")

local Camera = game.Workspace.CurrentCamera
local Humanoid = Character:WaitForChild("Humanoid")
local Viewmodel = game.ReplicatedStorage.viewmodel:Clone()
local vhum = Viewmodel:WaitForChild("Humanoid")
local CXAS = game:GetService("ContextActionService")

local repWeapon = game.ReplicatedStorage.weapons.MP7
local weapon = repWeapon:Clone()

local aimCount = 0
local camCount = 0

local speed = 1
local modifier = 0.5
local offset = weapon.Handle.CFrame:Inverse() * weapon.AimPart.CFrame

local holdAnim = Humanoid:LoadAnimation(weapon.animations.hold)
local aimAnim = Humanoid:LoadAnimation(weapon.animations.aim)
local lastAnim = holdAnim
local replicatedStorage = game:GetService("ReplicatedStorage")
local spring = require(replicatedStorage.modules.spring)

local shooting = false
local aiming = false
local LightsFX = false



lastAnim:Play()


weapon.Parent = Viewmodel
Viewmodel.Parent = Camera


local joint = Instance.new("Motor6D")
joint.C0 = CFrame.new(1, -1.5, -2)
joint.Parent = Viewmodel.rootPart
joint.Part0 = Viewmodel.rootPart
joint.Part1 = weapon.Handle

local idleAnim = vhum:LoadAnimation(weapon.animations.idle)
idleAnim:Play()

game.ReplicatedStorage.RemoteEvents.setup:FireServer(repWeapon)

local ShootingCoroutine = coroutine.create(function()
	while wait(60/weapon.config.rpm.Value) do
		if shooting then

			weapon.weaponRootPart.Flash:Emit(50)
			weapon.weaponRootPart.Smoke.Enabled = true
			LightsFX = true
			else
				
			LightsFX = false
			weapon.weaponRootPart.Smoke.Enabled = false
			weapon.weaponRootPart.Flash:Clear()
		end
		if LightsFX then
			weapon.weaponRootPart.Light.Enabled = true
			wait (60/ weapon.config.rpm.Value)
			weapon.weaponRootPart.Light.Enabled = false
		end
		
	end
end)
coroutine.resume(ShootingCoroutine)

local AimingCoroutine = coroutine.create(function()
	while wait() do
		if aiming == true then
			idleAnim:Stop()
			modifier = 0.1
		end
		if aiming == false then
			if idleAnim.IsPlaying == false then
				idleAnim:Play()
			end
			modifier = 0.5			
		end
	end
end)
coroutine.resume(AimingCoroutine)

local TiltRoutine = coroutine.create(function()
	while wait(0.1) do
	game.ReplicatedStorage.RemoteEvents.tiltAt:FireServer(math.asin(Camera.CFrame.LookVector.y));
	end
end)
coroutine.resume(TiltRoutine)

local function aimDownSights(aiming)
	local start = joint.C1
	local goal = aiming and joint.C0 * offset or CFrame.new()
	
	
	lastAnim:Stop();
	lastAnim = aiming and aimAnim or holdAnim;
	lastAnim:Play();

	aimCount = aimCount + 1
	local current = aimCount
	for t = 0,101,10 do
		if current~= aimCount then break end
		game:GetService("RunService").RenderStepped:Wait()
		joint.C1 = start:Lerp(goal, t/100)
		end
end

local function updateArm(key)

	local shoulder = Viewmodel[key.."UpperArm"][key.."Shoulder"];
	local cf = weapon[key].CFrame * CFrame.Angles(math.pi/2, 0, 0) * CFrame.new(0, 1.5, 0);
	shoulder.C1 = cf:inverse() * shoulder.Part0.CFrame * shoulder.C0;
end


local function onDeath()
	Viewmodel.Parent = nil
end

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

local function onUpdate(deltaTime)
	 fps = fps + 1
	print("this has ran "..fps.." times.")
	
	
	local Velocity = Character.HumanoidRootPart.Velocity
	local VelocityMagnitude = Velocity.Magnitude
	local Springs = require(game.ReplicatedStorage.modules.spring)
	
	if VelocityMagnitude > 50 then
		VelocityMagnitude = 50
	end
	
	Springs.walkCycle = spring.create()
	Springs.sway = spring.create()
	Springs.fire = spring.create()
	

	
	local movementSway = Vector3.new(getBobbing(10,speed,modifier),getBobbing(5,speed,modifier),getBobbing(5,speed,modifier))
	local mouseDelta = game:GetService("UserInputService"):GetMouseDelta()
	
	Springs.sway:shove(Vector3.new(mouseDelta.x / 200,mouseDelta.y / 200))
	Springs.walkCycle:shove((movementSway / 25) * deltaTime * 60 * VelocityMagnitude)
	
	local sway = Springs.sway:update(deltaTime)
	local walkCycle = Springs.walkCycle:update(deltaTime)
	local fire = Springs.fire:update(deltaTime)
	
	
	
	Viewmodel.rootPart.CFrame = Camera.CFrame
	Viewmodel.rootPart.CFrame = Viewmodel.rootPart.CFrame * CFrame.Angles(0,-sway.x,sway.y)
	
	Viewmodel.rootPart.CFrame = Viewmodel.rootPart.CFrame:ToWorldSpace(CFrame.new(walkCycle.x / 2,walkCycle.y / 2,0))
	Viewmodel.rootPart.CFrame = Viewmodel.rootPart.CFrame * CFrame.Angles(0,walkCycle.y,walkCycle.x)
	
	weapon.weaponRootPart.CFrame = weapon.weaponRootPart.CFrame * CFrame.Angles(0,walkCycle.y,walkCycle.x)
	weapon.weaponRootPart.CFrame = weapon.weaponRootPart.CFrame * CFrame.Angles(0,-sway.x,sway.y)
	weapon.weaponRootPart.CFrame = weapon.weaponRootPart.CFrame * CFrame.new(0,0,fire.z)
	
	updateArm("Right");
	updateArm("Left");
	
	if shooting then
		local ran = math.random(0,10)/8
		Springs.fire:shove(Vector3.new(ran,ran,ran))
	end
end

local function handler(actionName, inputState, inputObject)
	if actionName == "Shooting" then
		if inputState == Enum.UserInputState.Begin then
			shooting = true
			else
			shooting = false
		end
	end
	if actionName == "Aiming" then
		if inputState == Enum.UserInputState.Begin then			
			aimDownSights(true)
			aiming = true
			else
			aiming = false
			aimDownSights(false)
		end		
	end
end



Humanoid.Died:Connect(onDeath)
game:GetService("RunService").RenderStepped:Connect(onUpdate)
CXAS:BindAction("Shooting", handler,true, Enum.UserInputType.MouseButton1)
CXAS:BindAction("Aiming", handler,true, Enum.UserInputType.MouseButton2)

end)

Any help? Thanks

You’ll need to understand how the various coefficients affect how the spring will behave in order to adjust it to your liking.
This is roughly how the various coefficients affect the behavior, to my knowledge:

Mass

  • How ‘heavy’ the spring should behave. E.g. a mass at 1 would behave like paper.

Force

  • Determines with how much force the spring will shove.

Damping

  • How ‘bouncy’ the spring behaves. The less the damping is, the more bouncy it gets.

Speed

  • How quickly the spring will recover.
1 Like

i already know plenty about that. I turned damping down to 0 and 4 it doesnt make a difference. I have a part thats using the current spring to move around and it bounces fine. Its specifically the weapon thats not bouncing with sway.

Your explanation is pretty vague. What do you mean by “Its specifically the weapon thats not bouncing with sway.”? Do you mind illustrating it?

I have a part in workspace thats using the spring:

https://i.gyazo.com/560aa79ae1d09ee03047d9416412a5ab.gif

thats what the weapon should move like.

Its only the weapon that is stiff not the part thats what i meant

It should make no difference, though. You would just need to scale the output spring down by a lot for the viewmodel one.

Thats the thing. It doesn’t work at all. I dont know whats wrong. The weapon should bounce like the part but it doesnt.

As in not moving at all? Or bouncing too little?

If you look at the video in the original post, you can see that it sways a little but it doesnt really bounce. I dont know why it instantly returns to its position.

I can think of two possible reasons:

  1. The speed coefficient is too high and needs to be decreased.

  2. The velocity you’re shoving the spring with is too little. I’d rather try and divide the ouput velocity by 200 instead of the input velocity.
    Assuming this is the shove line for that specific spring: Springs.sway:shove(Vector3.new(mouseDelta.x / 200,mouseDelta.y / 200))

What do you mean by output velocity? youre right about that line btw

When you shove the spring, it requires a Vector3 value, this is the input velocity. When you call the Spring:update() function, you get the output velocity.

No luck. I think im going to delete this thread and make a clearer one. Thanks :slight_smile:

1 Like