As the title states, I’m trying to figure out how to make the flashlight ring stop jittering.
Script:
local UIS = game:GetService("UserInputService")
local RunService = game:GetService("RunService")
local HttpService = game:GetService("HttpService")
local LocalPlayer = game.Players.LocalPlayer
local Cam = workspace.CurrentCamera
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local TweenService = game:GetService("TweenService")
local Flashlight = ReplicatedStorage:WaitForChild("Flashlight")
local Brightness = 20
local Toggle = false
local canTick = false
local hasFlashlight = false
local tweenInfOn = TweenInfo.new(0.3, Enum.EasingStyle.Sine)
local tweenInfOff = TweenInfo.new(0.15, Enum.EasingStyle.Sine)
local clonedFlashlight
local spotLightAngle = 100
local spotLightRange = 27.6
local function toggle()
if not hasFlashlight then
clonedFlashlight = Flashlight:Clone()
local character = LocalPlayer.Character
if character and character:FindFirstChild("Head") then
local head = character.Head
local frontAttachment = head:FindFirstChild("FrontAttachment")
if not frontAttachment then
frontAttachment = Instance.new("Attachment")
frontAttachment.Name = "FrontAttachment"
frontAttachment.Position = Vector3.new(0, 0, 0)
frontAttachment.Parent = head
end
clonedFlashlight.CFrame = frontAttachment.WorldCFrame
clonedFlashlight.Anchored = false
clonedFlashlight.Parent = head
local weld = Instance.new("WeldConstraint")
weld.Part0 = clonedFlashlight
weld.Part1 = head
weld.Parent = clonedFlashlight
hasFlashlight = true
else
warn("Head not found on character")
clonedFlashlight:Destroy()
clonedFlashlight = nil
hasFlashlight = false
return
end
end
if Toggle == false then
Toggle = true
script.On:Play()
canTick = true
else
Toggle = false
script.Off:Play()
canTick = false
if clonedFlashlight then
clonedFlashlight:Destroy()
clonedFlashlight = nil
hasFlashlight = false
end
end
end
local function toggleOnDeath()
if Toggle == true then
Toggle = false
script.Off:Play()
canTick = false
if clonedFlashlight then
clonedFlashlight:Destroy()
clonedFlashlight = nil
hasFlashlight = false
end
end
end
local function onFlashlight(input, gameProcessed)
if gameProcessed then return end
if shared.keybindActionsLoaded then
local keybindActions = LocalPlayer:FindFirstChild("Keybind_Actions")
if keybindActions then
local flashlightKeybind = keybindActions:FindFirstChild("Flashlight") and HttpService:JSONDecode(keybindActions["Flashlight"].Value) or nil
if flashlightKeybind then
if table.find(flashlightKeybind, input.UserInputType.Name) then
toggle()
elseif input.KeyCode then
if table.find(flashlightKeybind, input.KeyCode.Name) then
toggle()
end
end
end
end
end
end
UIS.InputBegan:Connect(onFlashlight)
if UIS.TouchEnabled then
local mobileButton = LocalPlayer.PlayerGui:WaitForChild("MobileButton")
mobileButton.FlashlightButton.MouseButton1Down:Connect(function()
toggle()
end)
end
RunService.RenderStepped:Connect(function(deltaTime)
if clonedFlashlight and Toggle then
Brightness = math.clamp(Brightness + (0.5 * deltaTime), 0, 1)
local spotLight = clonedFlashlight:FindFirstChild("SpotLight")
if spotLight then
spotLight.Shadows = true
spotLight.Angle = spotLightAngle
spotLight.Range = spotLightRange
TweenService:Create(spotLight, tweenInfOn, {Brightness = Brightness}):Play()
end
elseif clonedFlashlight then
local spotLight = clonedFlashlight:FindFirstChild("SpotLight")
if spotLight then
spotLight.Shadows = false
TweenService:Create(spotLight, tweenInfOff, {Brightness = 0}):Play()
end
end
end)
LocalPlayer.CharacterAdded:Connect(function(character)
local humanoid = character:WaitForChild("Humanoid")
humanoid.Died:Connect(function()
hasFlashlight = false
toggleOnDeath()
end)
end)
It’s probably because you are attaching the flashlight to the player’s head. You should always use the camera for this, which you could do by simply parenting the light to a part and pivoting it to the camera every single frame.
I’m not necessarily talking about parenting it to the camera, but rather pivoting it to the camera every frame, so no attachments or any sort of weld used. You just need a loop that updates the light or its parent part’s CFrame to the camera’s CFrame every frame.
I understand but it just returns the same results , you can give it a go if you’d like or not. I’ve been stuck on this for a minute, I can’t seem to figure it out.
I tested the following code, and it seems to work perfectly fine:
local RunService = game:GetService("RunService")
local function makeLight()
local holder = Instance.new("Part")
holder.Parent = workspace
holder.CanCollide = false
holder.CanTouch = false
holder.CanQuery = false
holder.Anchored = true
holder.Transparency = 1
holder.Size = Vector3.one
local light = Instance.new("SpotLight")
light.Parent = holder
light.Brightness = 20
light.Angle = 15
return holder
end
repeat task.wait() until workspace.Camera
local camera = workspace.CurrentCamera
local holder = makeLight()
RunService.RenderStepped:Connect(function(dt)
holder.CFrame = camera.CFrame
end)
Here is a video of it in action:
One important thing I’ve noticed is that Lighting.Technology matters in terms of light quality, and found that Future works the best in this case.
Now obviously I don’t have the same camera and flashlight configuration as you do, nor any real consistency with your game. However, that should not be a problem in this context as what you’re trying to do is pretty trivial in terms of complexity and should work in any game.
local UIS = game:GetService("UserInputService")
local RunService = game:GetService("RunService")
local HttpService = game:GetService("HttpService")
local LocalPlayer = game.Players.LocalPlayer
local Cam = workspace.CurrentCamera
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local TweenService = game:GetService("TweenService")
local Flashlight = ReplicatedStorage:WaitForChild("Flashlight")
local Brightness = 20
local Toggle = false
local canTick = false
local hasFlashlight = false
local tweenInfOn = TweenInfo.new(0.3, Enum.EasingStyle.Sine)
local tweenInfOff = TweenInfo.new(0.15, Enum.EasingStyle.Sine)
local clonedFlashlight
local spotLightAngle = 100
local spotLightRange = 27.6
local function toggle()
if not hasFlashlight then
clonedFlashlight = Flashlight:Clone()
clonedFlashlight.CFrame = Cam.CFrame
clonedFlashlight.Parent = Cam
hasFlashlight = true
end
if Toggle == false then
Toggle = true
script.On:Play()
canTick = true
else
Toggle = false
script.Off:Play()
canTick = false
if clonedFlashlight then
clonedFlashlight:Destroy()
clonedFlashlight = nil
hasFlashlight = false
end
end
end
local function toggleOnDeath()
if Toggle == true then
Toggle = false
script.Off:Play()
canTick = false
if clonedFlashlight then
clonedFlashlight:Destroy()
clonedFlashlight = nil
hasFlashlight = false
end
end
end
local function onFlashlight(input, gameProcessed)
if gameProcessed then return end
if shared.keybindActionsLoaded then
local keybindActions = LocalPlayer:FindFirstChild("Keybind_Actions")
if keybindActions then
local flashlightKeybind = keybindActions:FindFirstChild("Flashlight") and HttpService:JSONDecode(keybindActions["Flashlight"].Value) or nil
if flashlightKeybind then
if table.find(flashlightKeybind, input.UserInputType.Name) then
toggle()
elseif input.KeyCode then
if table.find(flashlightKeybind, input.KeyCode.Name) then
toggle()
end
end
end
end
end
end
UIS.InputBegan:Connect(onFlashlight)
if UIS.TouchEnabled then
local mobileButton = LocalPlayer.PlayerGui:WaitForChild("MobileButton")
mobileButton.FlashlightButton.MouseButton1Down:Connect(function()
toggle()
end)
end
RunService.RenderStepped:Connect(function(deltaTime)
if clonedFlashlight and Toggle then
clonedFlashlight.CFrame = Cam.CFrame
Brightness = math.clamp(Brightness + (0.5 * deltaTime), 0, 1)
local spotLight = clonedFlashlight:FindFirstChild("SpotLight")
if spotLight then
spotLight.Shadows = true
spotLight.Angle = spotLightAngle
spotLight.Range = spotLightRange
TweenService:Create(spotLight, tweenInfOn, {Brightness = Brightness}):Play()
end
elseif clonedFlashlight then
local spotLight = clonedFlashlight:FindFirstChild("SpotLight")
if spotLight then
spotLight.Shadows = false
TweenService:Create(spotLight, tweenInfOff, {Brightness = 0}):Play()
end
end
end)
LocalPlayer.CharacterAdded:Connect(function(character)
local humanoid = character:WaitForChild("Humanoid")
humanoid.Died:Connect(function()
hasFlashlight = false
toggleOnDeath()
end)
end)
You’re right, it does look to be functionally similar. I assume Ring is the “image” that is projected onto the surface of the light, however, I don’t see where/how that is handled in your code. Could that be the issue?
The ring is parented to the flashlight part and the flashlight is in replicated storage. It gets cloned and parented into workspace. The “Ring” is a union.
Is the flashlight anchored? It looks like the flashlight is trying to fall down but is repositioned before it can go too far, creating a jitter effect.
It does not seem to be that the parts are unanchored, but rather some weird issue with lighting updates. Here is a video:
Edit: I’m not really sure if you can avoid this because it really does seem like an engine limitation/issue. I would just recommend getting rid of the ring or trying a different method.