How to make smooth FOV tween script?

I’ve now corrected my script completely, sending it now.

oh no my batteryㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤ

touch event still run on the client
you dont need to run touch event from the server since camera is a client’s object

local TweenService = game:GetService("TweenService")

local Player = game.Players.LocalPlayer
local Character = Player.Character or Player.CharacterAdded:Wait()

local Camera = game.Workspace.CurrentCamera

local function ChangeFovTweened(FieldOfView, Time)
	return TweenService:Create(Camera, TweenInfo.new(Time), {FieldOfView = FieldOfView})
end

local function OnTouched(Object)
	if Object.Parent == Character then
		ChangeFovTweened(
			20, -- fov change
			0.25 -- time (lower value is faster)
		):Play()
	end
end

--[[
Connect the OnTouched function into a touched event Example:

game.Workspace.Part.Touched:Connect(OnTouched)

]]

Where do i put this? StarterCharacter?

What script is that?? Where is the remove event??

I know that you can use TweenService and this way may be slower, but the LocalScript just makes the tween more customizable than a tween object. TweenObjects works fine as well but they may not always go in the speed you want the to go at and how much you want to change.

I also heard that you wanted stuff to happen when the Player touched the part.

For this, you will have to create a RemoteEvent. I suggest placing it in ReplicatedStorage and for testing purposes, name it “FOVChanger”.

Scripts

LocalScript (Place in StarterPlayerScripts):

local RemoteEvent = game:GetService([[ReplicatedStorage]]):WaitForChild([[FOVChanger]])

local robloxFovLimit = {
    min = 1;
    max = 120;
    default = 70;
}

local RunService = game:GetService([[RunService]])

local function pause(n)
    local t = os.time()
    repeat RunService.RenderStepped:Wait() until os.time() - t >= n
end

local camera = game.Workspace.Camera

local fovIsChanging = false

local function smoothFov(startFov, goal, fovPerInterval, interval)
    if startFov < robloxFovLimit.min or startFov > robloxFovLimit.max or goal < robloxFovLimit.min or goal > robloxFovLimit.max or startFov - goal == 0 or fovIsChanging == true then return end
    if startFov == nil then startFov = camera.FieldOfView end
    fovIsChanging = true
    for i = startFov, goal, fovPerInterval do
        camera.FieldOfView = i
        pause(interval)
    end
    fovIsChanging = false
end

RemoteEvent.OnClientEvent:Connect(smoothFov)

-- Usage example: smoothFov(camera.FieldOfView, 20, 0.3, 0.01)

ServerScript:

local RemoteEvent = game:GetService([[ReplicatedStorage]]):WaitForChild([[FOVChanger]])

local Part = game.Workspace.Part -- change this to wanted part

Part.Touched:Connect(function(hit)
    local Humanoid = hit.Parent:FindFirstChildOfClass([[Humanoid]])
    local Player = Humanoid and game.Players:GetPlayerFromCharacter(Humanoid.Parent)
        
    local startingFOV = nil -- change to nil which sets to current fov or new starting fov (from 1 to 120)
    local goalFOV = 20 -- change the rest of the variables to wanted value
    local fovPerTick = 1 -- fov changes by this number every time a cetain amount of time passes
    local fovChangeCooldown = 0.05 -- cooldown until fov ticks/changes
    
    if Player then
        RemoteEvent:FireClient(Player, startingFOV, goalFOV, fovPerTick, fovChangeCooldown)
    end
end)

If you prefer to use a LocalScript only, use this script and place it in StarterPlayerScripts.

local Part = game.Workspace.Part -- change to wanted part
local LocalPlayer = game.Players.LocalPlayer

local robloxFovLimit = {
    min = 1;
    max = 120;
    default = 70;
}

local RunService = game:GetService([[RunService]])

local function pause(n)
    local t = os.time()
    repeat RunService.RenderStepped:Wait() until os.time() - t >= n
end

local camera = game.Workspace.Camera

local fovIsChanging = false

local function smoothFov(startFov, goal, fovPerInterval, interval)
    if startFov < robloxFovLimit.min or startFov > robloxFovLimit.max or goal < robloxFovLimit.min or goal > robloxFovLimit.max or startFov - goal == 0 or fovIsChanging == true then return end
    if startFov == nil then startFov = camera.FieldOfView end
    fovIsChanging = true
    for i = startFov, goal, fovPerInterval do
        camera.FieldOfView = i
        pause(interval)
    end
    fovIsChanging = false
end

Part.Touched:Connect(function(hit)
    local Humanoid = hit.Parent:FindFirstChildOfClass([[Humanoid]])
    local Player = Humanoid and game.Players:GetPlayerFromCharacter(Humanoid.Parent)
    if Player then
        if Player == LocalPlayer then
            local startingFOV = nil -- change to nil which sets to current fov or new starting fov (from 1 to 120)
            local goalFOV = 20 -- change the rest of the variables to wanted value
            local fovPerTick = 1 -- fov changes by this number every time a cetain amount of time passes
            local fovChangeCooldown = 0.05 -- cooldown until fov ticks/changes
            
            smoothFov(startingFOV, goalFOV, fovPerTick, fovChangeCooldown)
        end
    end
end)

-- Usage example: smoothFov(camera.FieldOfView, 20, 0.3, 0.01)

(The last time, I made a mistake in the beginning and forgot to pass the player argument in the FireServer function. Anyways, I fixed that and added another option, everything should work completely fine now)

I apologize now that I have got this wrong 2 times but now I promise it is fixed…

Edit 3: My editor is buggy so the server script got deleted but I fixed that, now you should be able to copy the script and it will 100% work

Also make sure to change the Part variable to the wanted Part… Otherwise it will not work!!

Alright let me now delete the previous scripts for the third time now and try this.


IT WOrKS noW 100%

copy the explorer tab that i forgot to close

Paste this script in any part you want to affect.

local targetFov = 100 -- Target fov
local changeTime = 1 -- How long the fov changes 
local changesBack = false -- Does it go back to normal

local rep = game.ReplicatedStorage
local part = script.Parent
local remote = rep:FindFirstChild'ChangeFOV'
if not remote then
	remote = Instance.new'RemoteEvent'
	remote.Name = "ChangeFOV"
	remote.Parent = rep
end

local plrs = game.Players
part.Touched:Connect(function(hit)
	local plr = plrs:GetPlayerFromCharacter(hit.Parent)
	if plr then
		remote:FireServer(plr, targetFov, changeTime)
	end
end)

There are three values at the top you can change.

And a local script in StarterCharacterScripts.

local run = game:GetService'RunService'
local remote = game.ReplicatedStorage:WaitForChild'ChangeFOV'

local cam = workspace.Camera
local min, max = math.min, math.max

local defaultFov = cam.FieldOfView

local currentFOV = defaultFov
local targetFOV = defaultFov
local goesBack = false

local diff = 0
remote.OnClientEvent:Connect(function(target, speed, changesBack)
	diff = (target - currentFOV) * speed
	targetFOV = target
	goesBack = changesBack
end)

run.RenderStepped:Connect(function(dt)
	if currentFOV > targetFOV then
		currentFOV = max(currentFOV + diff*dt, targetFOV)
	elseif currentFOV < targetFOV then
		currentFOV = min(currentFOV + diff*dt, targetFOV)
	elseif goesBack then
		targetFOV = defaultFov
	end
end)

robloxapp-20220509-1355389.wmv (114.7 KB)

Just did everything, nothing works. I do have a screen recording of everything being in the correct place if you want to see.

Can you try my method. I used RunService instead of TweenService since creating a new tween uses a lot of memory.

I’m really sorry… I accidentally put game.Workspace.CurrentCamera instead of game.Workspace.Camera. I edited it, try again.

I know that it works.

i sent the wrong video lol now it says

You’ve performed this action too many times. Please wait 20 hours before trying again.
so i cant delete it

copy the explorer tab e

( PLZ USE IT WORKS 100 % !!! !! !!! )

Does not work, just tried, why is this so hard :confused:

You should try my script because I fixed it and now I know for a fact that it is completely fixed…

Remember to define the Part variable to the wanted part.