Distance Between Player and Lights (Continued)

I’m trying to figure out how to make SurfaceLights turn off when they are not within a region around the player. So far I’ve been able to achieve having them turn on when they are in the region around the player, but when the player exits the region I’m not sure how to turn them off.

This is what I’ve got so far,

local player = game.Players.LocalPlayer
local Name = player.Name
local character = game.Workspace:WaitForChild(Name)
local Humanoid = character.HumanoidRootPart
local DoorTouched = false
local LightFolder = game.Workspace.Ceiling.DefaultLights

local region = Region3.new(Vector3.new(1,1,1), Vector3.new(100, 50, 100))


local rgpart = Instance.new("Part", game.Workspace)
rgpart.Name = "LightRegion"


rgpart.Anchored = true
rgpart.Size = region.Size
rgpart.CFrame = region.CFrame
rgpart.Transparency = 1
rgpart.CanCollide = false

game:GetService("RunService").Heartbeat:connect(function()

	wait()	

	rgpart.Position = Humanoid.Position
	local PlayerSearchRegionTest = Region3.new(rgpart.Position-(rgpart.Size/2),rgpart.Position+(rgpart.Size/2))	
	
	wait(0.1)
	local Lights = game.Workspace:FindPartsInRegion3(PlayerSearchRegionTest, rgpart, math.huge)
	for i, v in pairs(Lights) do
		if v.Name == "CoreLight" then
			print("ok")
			v:WaitForChild("SurfaceLight").Enabled = true
			v:WaitForChild("PointLight").Enabled = true
		end
	end	
end)

This runs locally on the client.

Any Ideas or examples?

1 Like

Create a variable and set it to false in the RunService that states if they are in the region. Then, right here:

Set the variable to true. Then check after the loop if that variable is true, if it isn’t, turn the lights off.

Where in the RunService?

And what exactly would I use do to state if they’re in the region or not, set a Boolean value?

Reading over this script, it’s a bit hard to follow what’s going on. What I suggest you do is check the magnitude of the player and the part like so:

(Part.Position - player.Character.HumanoidRootPart.Position).Magnitude

Then determine what size distance you want (ie 5 studs away or less) then turn on the lights. If they are greater than 5, turn them off.

I’ve tried this but it was performance destroying, not sure if it’s because I just didn’t do it right or what. But I had looped through the whole workspace for the parts that are within a magnitude from the player.

You must be doing something wrong then. Since this is the client, you only need to check the part’s position to the player’s humanoid root part.

Perhaps an example? I’m lacking lol

Try this out, it should be fine. Just be sure you aren’t creating repeat connections too!

local RunService = game:GetService("RunService")
local Players = game:GetService("Players")
local player = Players.LocalPlayer

local MinimumDistance = 5

RunService.RenderStepped:Connect(function()
	for i, v in pairs(Lights) do
		if v.Name == "CoreLight" then
			local magnitude = math.round((player.Character.HumanoidRootPart.Position - v.Position).Magnitude)

			if magnitude <= MinimumDistance then
				-- turn on light in object
				
				v:WaitForChild("SurfaceLight").Enabled = true
				v:WaitForChild("PointLight").Enabled = true
			else
				v:WaitForChild("SurfaceLight").Enabled = false
				v:WaitForChild("PointLight").Enabled = false
			end
		end
	end	
end)

Do I want to completely disregard and remove my regions with this script?

You don’t need to worry about regions in this code block.

This spammed Output,

hm…

Wait this may be because some parts dont got the PointLight?

It means that the PointLight isn’t there yet. You will need to add it in before the RunService runs.

Fixed it, but now I got this,

You need to also run this after the player is fully loaded in. Do the following:

local RunService = game:GetService("RunService")
local Players = game:GetService("Players")
local player = Players.LocalPlayer

local MinimumDistance = 5

RunService.RenderStepped:Connect(function()
	for i, v in pairs(Lights) do
		if v.Name == "CoreLight" then
			if player.Character:FindFirstChild("HumanoidRootPart") then
				local magnitude = math.round((player.Character.HumanoidRootPart.Position - v.Position).Magnitude)

				if magnitude <= MinimumDistance then
					-- turn on light in object

					v:WaitForChild("SurfaceLight").Enabled = true
					v:WaitForChild("PointLight").Enabled = true
				else
					v:WaitForChild("SurfaceLight").Enabled = false
					v:WaitForChild("PointLight").Enabled = false
				end				
			end
		end
	end	
end)

Well,

Oh, this is because you are in a player scripts. For the player variable, do script.Parent.Parent

So, this?

if script.Parent.Parent then

Also MinimumDistance is measured in Studs, correct?

No, ok you should be able to local player. It’s just you need to wait for the character to load. The script I provided you is fine, just have it wait a little then run the runservice.

And yes, it is measured in studs.

Why doesn’t this work? It’s waiting for the Humanoid Root part.

if Character:WaitForChild("HumanoidRootPart") then

Or, here, if this helps more.

local RunService = game:GetService("RunService")
local Players = game:GetService("Players")
local player = Players.LocalPlayer
local Character = player.Character

local MinimumDistance = 1000

RunService.RenderStepped:Connect(function()
	for i, v in pairs(game.Workspace.Ceiling.DefaultLights:GetDescendants()) do
		if v.Name == "CoreLight" then
			if Character:WaitForChild("HumanoidRootPart") then
				local magnitude = math.round((player.Character.HumanoidRootPart.Position - v.Position).Magnitude)

				if magnitude <= MinimumDistance then
					-- turn on light in object

					v:WaitForChild("SurfaceLight").Enabled = true
					v:WaitForChild("PointLight").Enabled = true
				else
					v:WaitForChild("SurfaceLight").Enabled = false
					v:WaitForChild("PointLight").Enabled = false
				end				
			end
		end
	end	
end)