I’m working on an FPS game with viewmodels like most FPS games, Although i’ve run into a problem that’s quite unusual.
Whenever i shoot upwards, the cameras rotation sort of glitches out, this is probably due to the recoil, im using the spring module by the way.
Here’s a video of what’s happening
Here’s the module script im using to move the camera using recoil (not the spring module):
function module.update(viewmodel, dt, RecoilSpring, BobbleSpring, SwaySpring)
for i,v in pairs(viewmodel:GetChildren()) do
if v:IsA("MeshPart") or v:IsA("Part") then
v.CanCollide = false
end
end
local Bobble = Vector3.new(GetBobbing(10) * dt, GetBobbing(5) * dt, GetBobbing(5) * dt)
local MouseDelta = game:GetService("UserInputService"):GetMouseDelta()
local Character = game.Players.LocalPlayer.Character or game.Players.LocalPlayer.CharacterAdded:Wait()
viewmodel:SetPrimaryPartCFrame(workspace.CurrentCamera.CFrame)
BobbleSpring:shove(Bobble / 10 * (Character.HumanoidRootPart.Velocity.Magnitude) / 10)
SwaySpring:shove(Vector3.new(-MouseDelta.X / 1.5 * dt, MouseDelta.Y / 1.5 * dt, 0))
local UpdatedRecoilSpring = RecoilSpring:update(dt)
local UpdatedBobbleSpring = BobbleSpring:update(dt)
local UpdatedSwaySpring = SwaySpring:update(dt)
viewmodel:SetPrimaryPartCFrame(viewmodel:GetPrimaryPartCFrame():ToWorldSpace(CFrame.new(UpdatedBobbleSpring.Y, UpdatedBobbleSpring.X, 0)))
viewmodel:SetPrimaryPartCFrame(viewmodel:GetPrimaryPartCFrame() * CFrame.new(UpdatedSwaySpring.X, UpdatedSwaySpring.Y, 0))
viewmodel:SetPrimaryPartCFrame(viewmodel:GetPrimaryPartCFrame() * CFrame.Angles(math.rad(UpdatedRecoilSpring.X), math.rad(UpdatedRecoilSpring.Y), 0))
workspace.Camera.CFrame *= CFrame.Angles(math.rad(UpdatedRecoilSpring.X), math.rad(UpdatedRecoilSpring.Y), math.rad(UpdatedRecoilSpring.Z))
end
Here’s where I run the .update (Gun Local Script):
RunService.RenderStepped:Connect(function(dt)
if Viewmodel then
MainModule.update(Viewmodel, dt, RecoilSpring, BobbleSpring, SwaySpring)
end
end)
And this is where i use :shove when i shoot for the recoil (Same Module Script):
function module.Shoot(Mouse, FirePos, FireCF, Attachment, RecoilSpring, Up, Sideways, Shake, Gun, dt)
local plr = game.Players.LocalPlayer
local Cam = workspace.CurrentCamera
local Viewmodel = Cam:WaitForChild(Gun.Name)
local Ammo = Gun:GetAttribute("Ammo")
local OrgAmmo = Gun:GetAttribute("OriginalAmmo")
local RS = game:GetService("ReplicatedStorage")
local SS = game:GetService("SoundService")
local KillSound = SS:WaitForChild("KillSound")
local EXPsound = SS:WaitForChild("EXP")
local Background = plr.PlayerGui.Kill.Background
local KillPopup = plr.PlayerGui.Kill.KillPopup
local HeadPopup = plr.PlayerGui.Kill.HeadPopup
FirePos = Attachment.Position
FireCF = Attachment.CFrame
if Mouse.Target ~= nil then
local ShootEvent = RS.Events.Shoot:InvokeServer(Mouse.Hit.Position, false, FirePos, FireCF, Gun)
print(ShootEvent)
RecoilSpring:shove(Vector3.new(Up * dt, math.random(-Sideways, Sideways) * dt, Shake * dt)) --!!! Here
coroutine.wrap(function()
task.wait(.1)
RecoilSpring:shove(Vector3.new(-(Up - .2) * dt, math.random(-(Sideways / 2), (Sideways / 2)) * dt, -Shake * dt)) --!!! Here
end)()
if ShootEvent == "Killed" then
KillSound:Play()
Kill_UI(Background, KillPopup)
EXPsound:Play()
end
if ShootEvent == "Headshot" then
KillSound:Play()
Kill_UI(Background, HeadPopup)
EXPsound:Play()
end
else
RS.Events.Shoot:InvokeServer(Mouse.Hit.Position, true, FirePos, FireCF, Gun)
RecoilSpring:shove(Vector3.new(Up * dt, math.random(-Sideways, Sideways) * dt, Shake * dt)) --!!! Here
coroutine.wrap(function()
task.wait(.1)
RecoilSpring:shove(Vector3.new(-(Up - .2 * dt), math.random(-(Sideways / 2), (Sideways / 2)) * dt, -Shake * dt)) --!!! Here
end)()
end
end
I run the .Shoot in that same Gun Local Script but i don’t believe it’s necessary to provide it, unless i’m wrong.
I’ve never run into this before, so help would be very useful!