I am trying to make a part fit the screen of the player perfectly. The part contains a SurfaceGui with a vignette filter. In another script I have the FOV being tweened and adjusted based on conditions. When zooming out, the visor gui is a frame delayed.
I have tried chagning Renderpriority, removing the fov tween, parenting to the camera and Heartbeat.
All do not work, except for increasing the size, to where the delay isn’t visible. It isn’t ideal to have the bigger size because a large part of the gui is cut off.
Any input is great, thanks for reading.
RunService:BindToRenderStep("UpdateVisor", Enum.RenderPriority.Last.Value - 1, function()
local Camera = workspace.CurrentCamera
local cameraFOV = Camera.FieldOfView
local viewportSize = Camera.ViewportSize
local aspectRatio = viewportSize.X / viewportSize.Y
local fovRadians = math.rad(cameraFOV)
local depth = 1
local height = 2 * math.tan(fovRadians / 2) * depth
local width = height * aspectRatio
VisorGui.Size = Vector3.new(width + 0.15, height + 0.15, 0.1)
VisorGui.CFrame = Camera.CFrame * CFrame.new(0, 0, -depth)
end)
I played around with the code and it seems like the issue is the lack of precision in either of the calculations (due to floating point error) and to fix it I simply increased the depth by a big number.
However I do have to note that there seems to be shadows popping in and out despite me toggling “CastShadow” off in the part properties.
Here’s the code I tested it with:
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local Camera = workspace.CurrentCamera
local VisorGui = script.VisorGui
VisorGui.Parent = workspace
RunService:BindToRenderStep("UpdateVisor", Enum.RenderPriority.Last.Value + 1, function()
local Camera = workspace.CurrentCamera
local cameraFOV = Camera.FieldOfView
local viewportSize = Camera.ViewportSize
local aspectRatio = viewportSize.X / viewportSize.Y
local fovRadians = math.rad(cameraFOV)
local depth = 100
local height = 2 * math.tan(fovRadians / 2) * depth
local width = height * aspectRatio
local partDepth = 1
VisorGui.Size = Vector3.new(width, height, partDepth)
VisorGui.CFrame = Camera.CFrame * CFrame.new(0, 0, -depth - (partDepth / 2))
end)
RunService:BindToRenderStep("UpdateFOV", Enum.RenderPriority.First.Value, function()
local m = (math.sin(time()) + 1) / 2
Camera.FieldOfView = 40 + (m * 80)
end)
I think, you should try changing Enum.RenderPriority.Last.Value + 1 to Enum.RenderPriority.Camera.Value + 1, so it’s certain that the change will happen right after the FOV updates.
After furthing testing, I concluded that: Even when keeping the parts size static, in my case I used 100x100x0.1, and only modified the SurfaceGuiSize and PixelsPerStus, It still hasthis delay. I don’t know how I can counteract this, seems kind of impossible.
Maybe It’s an engine bug, but I honestly don’t know. I will try some other things but, this is what I concluded.
I’m so genuinely frustrated at this. I wish roblox had a feature to where you could make SurfaceGUIS appear above ScreenGUIS.
After a bit of research I think it’s because of the way SurfaceGui are updated. I think they’re updated one frame behind the camera, so inherintly the surfacegui will always be a frame behind the fov update.
Code I used:
local Camera = workspace.CurrentCamera
local CamCFrame = Camera:GetRenderCFrame()
local cameraFOV = Camera.FieldOfView
local viewportSize = Camera.ViewportSize
local aspectRatio = viewportSize.X / viewportSize.Y
local depth = 1
local partDepth = 0.1
VisorGui.SurfaceGui.PixelsPerStud = 100
VisorGui.SurfaceGui.Visor.Size = UDim2.new(0,viewportSize.X,0,viewportSize.Y)
VisorGui.Size = Vector3.new(100, 100, partDepth)
local fovRadians = math.rad(cameraFOV)
local hFOV = 2 * math.atan(math.tan(fovRadians/2) * aspectRatio)
local W_s = VisorGui.SurfaceGui.Visor.Size.X.Offset / VisorGui.Size.X
local H_s = VisorGui.SurfaceGui.Visor.Size.Y.Offset / VisorGui.Size.Y
local d_v = (H_s/2) / math.tan(fovRadians/2)
local d_h = (W_s/2) / math.tan(hFOV/2)
local d = math.max(d_v, d_h)
local partDepth = VisorGui.Size.Z
VisorGui.CFrame = CamCFrame * CFrame.new(0, 0, -d -partDepth/2)