Hello everyone.
High-beam glare on trains was created using BillboardGui.
However, because BillboardGui is displayed from all angles, the glare is visible even from angles where the light source is not visible.(See the video.)
I know the best way to solve this is to use SurfaceGui, but SurfaceGui does not have autoscaling. (I need to make the glare appear greater the further away from the light source.)
Any tips on how to solve this?
local RunService = game:GetService("RunService")
local currentCamera = workspace.CurrentCamera -- Current camera
local billboardPart = workspace:WaitForChild("Part") -- The part which contains the BillboardGui
local billboardGui = billboardPart:WaitForChild("BillboardGui") -- The BillboardGui itself.
local visibleThreshold = 0.25 -- Higher this number, higher the visibility angle.
RunService.RenderStepped:Connect(function()
local partLookVector = billboardPart.CFrame.LookVector -- Get the direction the part containing the BillboardGui is facing
local camLookVector = currentCamera.CFrame.LookVector -- Get the direction the player's camera is facing
local dotProduct = partLookVector:Dot(camLookVector) -- Get the dot product of the two look vectors. Visit this for more info: https://devforum.roblox.com/t/the-ultimate-guide-to-vector3cross-and-vector3dot/953984
if dotProduct <= visibleThreshold then -- Check if the dot product is less than threshold
billboardGui.Enabled = true -- Set enabled to true
else
billboardGui.Enabled = false -- Else set enabled to false
end
end)
I think I misunderstood your question. You should use TheBrainy06’s script, if it works. Raycasting is fairly simple, I’ll give a quick example:
local MyParams = RaycastParams.new()
MyParams.FilterType = Enum.RaycastingFilterType.Blacklist -- just an example, but raycast params have a lot of stuff you can play around with
local MyRay = workspace:Raycast(startPosition, (EndPosition - StartPosition), RaycastParams)
inside of the parenthesis of workspace:Raycast(), you have 3 things to fill in: the position where the ray starts, the direction the ray travels, and raycast parameters (basically like settings for your raycast). Please note the direction that the ray travels can also be a lookVector.
You can access the part which the ray hits by using MyRay.Instance, or the position where the ray hits a part by using MyRay.Position
Hopefully this provides a basic understanding of what TheBrainy06 sent
Sorry. There was an error in the text, which has been corrected.
AlwaysOnTop is “false”.
I read in another post that you can use raycast to know if a part is on camera or not, so I will try that.
local RunService = game:GetService("RunService")
local currentCamera = workspace.CurrentCamera -- Current camera
local visibleThreshold = 0.25 -- Higher this number, higher the visibility angle.
RunService.RenderStepped:Connect(function()
for _, v in ipairs(workspace:GetDescendants(""))do
local camLookVector = currentCamera.CFrame.LookVector -- Get the direction the player's camera is facing
if v:IsA("BillboardGui") then continue end
if v.Name == "Gui" then
print("a")
local partLookVector = v.Parent.CFrame.LookVector -- Get the direction the part containing the BillboardGui is facing
local dotProduct = partLookVector:Dot(camLookVector) -- Get the dot product of the two look vectors.
if dotProduct <= visibleThreshold then -- Check if the dot product is less than threshold
v.Enabled = true -- Set enabled to true
print("b")
else
v.Enabled = false -- Else set enabled to false
print("c")
end
end
end
end)
I modified the script to control all BillboardGui named “Gui” in the Workspace, but it seems that the for loop does not work.
Anyway, thanks for all your tips!
I tried various approaches, but they did not work with my technical skills.
Finally, I dealt with this by changing the size of the SurfaceGui depending on the distance from the camera.
--StarterPlayerScript
while task.wait(0.1) do
for _, v in ipairs(workspace:GetDescendants("")) do
if not v:IsA("ImageLabel") then continue end
if v.Name == "GlareTex" then
local a = v.Parent.Parent.Position
local cameraPos = game:GetService("Workspace").CurrentCamera.CFrame.Position
local mag = (a - cameraPos).Magnitude
local size = mag / 50
if size < 5 then
v.Size = UDim2.new(size,0,size,0)
else
v.Size = UDim2.new(5,0,5,0)
end
if size < 0.3 then
v.ImageTransparency = 1
else
v.ImageTransparency = 0
end
end
end
end
This is probably a poor performance approach, so I will continue to research raycasting and other methods.