Hold right mouse button to zoom in, release to zoom out

I’m trying to set up a sniper scope, but I have three scripts in my game that are required for the custom camera manipulation, all of which that have stopped me in the past from making it through regular methods. However, I recently thought it would be better if the camera just zoomed in when the scope is active (holding down the right mouse button), and returned to normal when the scope isn’t (releasing the right mouse button).

How would I go about doing this?

TL;DR: I want to make a script that zooms in the camera when an input begins, and zooms out when it ends.

Any help is appreciated!

Have you tried field of view? I believe that should work.

Yes, however last time I ran into a problem in which activating the scope in certain ways causes the camera to be forever zoomed in, or the controls to be inverted (holding rmb zooms out, releasing zooms in)

  1. Activating the scope multiple times in quick succession (sometimes)
  2. Activating the scope, unequipping the tool, re-equipping the tool and activating the scope again (always)

The video below will demonstrate what I mean (done in a test place, not in-game)

This could either be a result of the tweening of the FOV, or something to do with the RunService connection. I’m not sure though

UPDATE:

I have managed to create a fixed version, that doesn’t have any issues (that I know of)
However I still want to make a smooth animation between aiming and not aiming

Here’s the code for the gun:

-- SERVICES --

local Players = game:GetService('Players')
local RuS = game:GetService('RunService')
local UIS = game:GetService('UserInputService')
local camera = workspace.CurrentCamera

-- PLAYER VARIABLES -- 

local Player = Players.LocalPlayer
local hum = Player.Character:WaitForChild('Humanoid')
local mouse = Player:GetMouse()

-- VALUES --

local Holdable, Holding = true, false -- if holdable is true, the weapon will be (semi)automatic
local Aimable, Aiming = true, false
local debounce = false

-- ANIMATIONS -- 

local tool = script.Parent
local shoot = script.Parent:WaitForChild('Shoot')
local ShootAnims = tool.ShootAnims
local Hold = tool:WaitForChild('Hold')

local Shoot1 = ShootAnims:WaitForChild('Shoot1')
local Shoot2 = ShootAnims:WaitForChild('Shoot2')
local Shoot3 = ShootAnims:WaitForChild('Shoot3')

local holdanim = hum:LoadAnimation(Hold)
local shootanim1 = hum:LoadAnimation(Shoot1)
local shootanim2 = hum:LoadAnimation(Shoot2)
local shootanim3 = hum:LoadAnimation(Shoot3)

function Send()
	shoot:FireServer({Position = mouse.Hit.Position})
end

tool.Activated:Connect(function()
	Holding = true
	if Holdable then
		local Run
		Run = RuS.Heartbeat:Connect(function()
			if not Holding then
				Run:Disconnect()
			end
			Send()
		end)
	else
		Send()
	end
end)

tool.Deactivated:Connect(function()
	Holding = false
end)

tool.Equipped:Connect(function()
	InputBeganRun = nil
	InputEndedRun = nil
	
	holdanim:Play()
	
	if Aimable then
		InputBeganRun = UIS.InputBegan:Connect(function(input, gameprocess)
			if not gameprocess then
				if input.UserInputType == Enum.UserInputType.MouseButton2 then
					Aiming = true
					if Aimable then
						ScopeRun = nil
						ScopeRun = RuS.Heartbeat:Connect(function()
							if not Aiming then
								ScopeRun:Disconnect()
							end
							camera.FieldOfView = 40
						end)
					end
				end
			end
		end)
	end
	
	if Aimable then
		InputEndedRun = UIS.InputEnded:Connect(function(input, gameprocess)
			if not gameprocess then
				if input.UserInputType == Enum.UserInputType.MouseButton2 then
					Aiming = false
					task.wait(.05)
					camera.FieldOfView = 86
				end
			end
		end)
	end
end)

tool.Unequipped:Connect(function()
	Holding = false
	Aiming = false
	
	camera.FieldOfView = 86
	
	InputBeganRun:Disconnect()
	InputEndedRun:Disconnect()
	ScopeRun:Disconnect()
	
	holdanim:Stop()
	shootanim1:Stop()
	shootanim2:Stop()
	shootanim3:Stop()
end)

And here’s the snippet of code that makes the scoping work:

tool.Equipped:Connect(function()
	InputBeganRun = nil
	InputEndedRun = nil
	
	holdanim:Play()
	
	if Aimable then
		InputBeganRun = UIS.InputBegan:Connect(function(input, gameprocess)
			if not gameprocess then
				if input.UserInputType == Enum.UserInputType.MouseButton2 then
					Aiming = true
					if Aimable then
						ScopeRun = nil
						ScopeRun = RuS.Heartbeat:Connect(function()
							if not Aiming then
								ScopeRun:Disconnect()
							end
							camera.FieldOfView = 40
						end)
					end
				end
			end
		end)
	end
	
	if Aimable then
		InputEndedRun = UIS.InputEnded:Connect(function(input, gameprocess)
			if not gameprocess then
				if input.UserInputType == Enum.UserInputType.MouseButton2 then
					Aiming = false
					task.wait(.05)
					camera.FieldOfView = 86
				end
			end
		end)
	end
end)

tool.Unequipped:Connect(function()
	Holding = false
	Aiming = false
	
	camera.FieldOfView = 86
	
	InputBeganRun:Disconnect()
	InputEndedRun:Disconnect()
	ScopeRun:Disconnect()
	
	holdanim:Stop()
	shootanim1:Stop()
	shootanim2:Stop()
	shootanim3:Stop()
end)

Right now, it instantly zooms in and out by setting the camera FOV to whatever it needs to be, without any transition, but how would I go about making it so that it tweens the camera’s FOV, rather than having it instantly zoom in?

UPDATE 2:
I fixed it by just swapping out the ‘camera.FieldOfView’ with a tween that sets the field of view. Guess I didn’t need to overthink it
Thanks for your help anyway!

Full code if anyone’s interested (in local script):

-- SERVICES --

local Players = game:GetService('Players')
local RuS = game:GetService('RunService')
local UIS = game:GetService('UserInputService')
local TS = game:GetService('TweenService')
local camera = workspace.CurrentCamera

-- PLAYER VARIABLES -- 

local Player = Players.LocalPlayer
local char = Player.Character or Player.CharacterAdded:Wait()
local hum = char:WaitForChild('Humanoid')
local mouse = Player:GetMouse()

-- VALUES/CONFIG --

local Holding = false
local Aiming = false
local debounce = false

local tool = script.Parent

config = {
	Holdable = script:GetAttribute('Holdable'), -- if holdable is true, the weapon will be (semi)automatic
	Aimable = script:GetAttribute('Aimable'), -- if aimable is true, the weapon will have a scope
	zoomFOV = script:GetAttribute('zoomFOV')
}

local TInfo = TweenInfo.new(
	0.3,
	Enum.EasingStyle.Exponential,
	Enum.EasingDirection.Out,
	0,
	false,
	0
)

-- ANIMATIONS -- 

local shoot = script.Parent:WaitForChild('Shoot')
local ShootAnims = tool.ShootAnims
local Hold = tool:WaitForChild('Hold')

local Shoot1 = ShootAnims:WaitForChild('Shoot1')
local Shoot2 = ShootAnims:WaitForChild('Shoot2')
local Shoot3 = ShootAnims:WaitForChild('Shoot3')

local holdanim = hum:LoadAnimation(Hold)
local shootanim1 = hum:LoadAnimation(Shoot1)
local shootanim2 = hum:LoadAnimation(Shoot2)
local shootanim3 = hum:LoadAnimation(Shoot3)

function Send()
	shoot:FireServer({Position = mouse.Hit.Position})
end

tool.Activated:Connect(function()
	Holding = true
	if config.Holdable then
		local Run
		Run = RuS.Heartbeat:Connect(function()
			if not Holding then
				Run:Disconnect()
			end
			Send()
		end)
	else
		Send()
	end
end)

tool.Deactivated:Connect(function()
	Holding = false
end)

tool.Equipped:Connect(function()
	InputBeganRun = nil
	InputEndedRun = nil
	
	holdanim:Play()
	
	if config.Aimable then
		InputBeganRun = UIS.InputBegan:Connect(function(input, gameprocess)
			if not gameprocess then
				if input.UserInputType == Enum.UserInputType.MouseButton2 then
					Aiming = true
					if config.Aimable then
						ScopeRun = nil
						TS:Create(camera, TInfo, {FieldOfView = config.zoomFOV}):Play()
						ScopeRun = RuS.Heartbeat:Connect(function()
							if not Aiming then
								ScopeRun:Disconnect()
							end
							camera.FieldOfView = config.zoomFOV
						end)
					end
				end
			end
		end)
	end
	
	if config.Aimable then
		InputEndedRun = UIS.InputEnded:Connect(function(input, gameprocess)
			if not gameprocess then
				if input.UserInputType == Enum.UserInputType.MouseButton2 then
					Aiming = false
					task.wait(.05)
					TS:Create(camera, TInfo, {FieldOfView = 86}):Play()
				end
			end
		end)
	end
end)

tool.Unequipped:Connect(function()
	Holding = false
	Aiming = false
	
	TS:Create(camera, TInfo, {FieldOfView = 86}):Play()
	
	if InputBeganRun ~= nil then
		InputBeganRun:Disconnect()
	end
	if InputEndedRun ~= nil then
		InputEndedRun:Disconnect()
	end
	if ScopeRun ~= nil then
		ScopeRun:Disconnect()
	end
	
	holdanim:Stop()
	shootanim1:Stop()
	shootanim2:Stop()
	shootanim3:Stop()
end)

UIS.InputBegan:Connect(function(input, gameprocess)
	if not gameprocess then
		if input.UserInputType == Enum.UserInputType.Keyboard then
			if input.KeyCode == Enum.KeyCode.E and debounce == false then
				debounce = true
				tool.Grip = CFrame.Angles(0, math.rad(90), 0)
				task.wait(1)
				tool.Grip = CFrame.new(Vector3.new(0.039, 0, -0.295)) * CFrame.Angles(0, math.rad(126), 0)
				task.wait(1.1)
				debounce = false
			end
		end
	end
end)
1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.