I have created a simple script which is meant for a brief effect in one of my games, which makes the FOV of the camera zoom in and out quickly, making it look like it’s shaking. The problem is, assuming the FOV is set to 70, if another script tries to change the FOV, it’ll be stuck as 70 due to this script.
I’m quite confused, I don’t really know how to solve this without messing the script up. Any help is appreciated!
local Camera = workspace.CurrentCamera
local TS = game:GetService("TweenService")
local Info = TweenInfo.new(0.035)
local FOVValue = Camera.FieldOfView
local FOVValueNum = game.ReplicatedStorage:WaitForChild("FOVShakeValue")
while true do
wait (0.035)
TS:Create(Camera, Info, {FieldOfView = FOVValue + FOVValueNum.Value}):Play()
wait (0.035)
TS:Create(Camera, Info, {FieldOfView = FOVValue - FOVValueNum.Value}):Play()
end
FOVValueNum is a NumberValue in ReplicatedStorage which is handled by a second script:
local IsShaking = game.ReplicatedStorage:WaitForChild("IsFOVShaking")
IsShaking:GetPropertyChangedSignal("Value"):Connect(function()
if IsShaking.Value == true and game.ReplicatedStorage:WaitForChild("Ended").Value == false then
game:GetService("TweenService"):Create(game.ReplicatedStorage:WaitForChild("FOVShakeValue"), TweenInfo.new(1), {Value = 0.45}):Play()
elseif IsShaking.Value == false then
game:GetService("TweenService"):Create(game.ReplicatedStorage:WaitForChild("FOVShakeValue"), TweenInfo.new(2), {Value = 0}):Play()
end
end)
local Camera = workspace.CurrentCamera
local TS = game:GetService("TweenService")
local Info = TweenInfo.new(0.035, Enum.EasingStyle.Linear, Enum.EasingDirection.InOut, -1, true)
local FOVValue = Camera.FieldOfView
local FOVValueNum = game.ReplicatedStorage:WaitForChild("FOVShakeValue")
TS:Create(Camera, Info, {FieldOfView = FOVValue + FOVValueNum.Value}):Play()
I recommend describing how Camera.FieldOfView should change by setting the rate at which it should change instead of the new position it should change to.
You would not need to have a FOVValue variable outside of the loop, since FieldOfView is updated using a value based on it’s current value. (In some sense, this is how an Animation works by using Motor6D.Transform)
Even better, create a ModuleScript to create a centralized place any LocalScript wanting to modify Camera.FieldOFView has to go through, as then you can have explicit control over which script has priority or how they should blend.
A very nice way to extend this approach is to have the ModuleScript internally use a spring and offer a method that allows scripts to apply an instantaneous impulse, letting the module handle the rest of the animation of the camera movement.
An approach I would take is to use a spring and model the displacement using some resting FOV which you can set if a script wants to overwrite it.
local Workspace = game:GetService("Workspace")
local RunService = game:GetService("RunService")
local CameraShake = {}
function CameraShake.new(camera, resting, frequency, damping)
local self = setmetatable({}, { __index = CameraShake })
self.camera = camera
self.resting = resting
self.frequency = frequency
self.damping = damping
self.loop = RunService.PreRende r:Connect(function(dt)
self:Update(dt)
end)
return self
end
function CameraShake:Apply(impulse)
self.velocity += impulse
end
function CameraShake:__update(dt)
local acceleration = -(2 * math.pi * self.frequency)^2
* self.displacement - (2 * self.damping * self.velocity)
self.velocity += acceleration * dt
self.displacement += self.velocity * dt
self.camera.FieldOfView = self.resting + self.displacement
end
local SPRING_FREQUENCY = 1
local SPRING_DAMPING = 1
local RESTING_FOV = 70
return CameraShake.new(
Workspace.CurrentCamera,
RESTING_FOV
SPRING_FREQUENCY,
SPRING_DAMPENING,
)
I’m more of just trying to make the “FOVValue” variable constantly update, and I think I could approach this using attributes, but again, I’m a bit confused and nothing seems to work.
Also, make sure to use task.wait() instead of wait().
wait() has been deprecated for task.wait()
It’s basically the same, but task.wait() is more supported, while wait() is no longer supported, and has delays.
You can see for youself → https://www.youtube.com/watch?v=ffttKVy2cWc