Lag being caused when parts is touched

local function partTouched(hit, teleportFrom, teleportTo)
	local Character = hit.Parent
	if not Character then return end
		
	local Player = Players:GetPlayerFromCharacter(Character)
	if not Player then return end
	
	if teleportTo == Houses then
		if teleportTo[teleportFrom.Name].House.Locked.Value or Player.Name ~= teleportFrom.Name then return end
	end
end

-- Constantly checking as new plots can be added, etc.
RunService.RenderStepped:Connect(function()
	for _, v in pairs(Plots:GetDescendants()) do
		if v:IsA('Model') then
			if v.Name == 'Door' then
				v.PrimaryPart.Touched:Connect(function(hit)
					partTouched(hit, v.Parent.Parent, Houses)
				end)
			end
		end
	end
end)

Problem is whenever I touch the part to teleport, I get constant lag. Inside my touch function, I have a check to see if the house you are trying to teleport to is locked. Basically if the house is locked, you can’t enter, and thus why it has a return (so I don’t run code further down that causes you to teleport)

Only allowable case for a player to still enter the house if its locked is is if that house is their own (so they dont lock themselves out)

Hi to anyone at RDC from Australia :3

4 Likes

I think the reason it creates lag is because it is constantly creating new event listeners for the part. I might be wrong though. Try putting a single print statement in the event and see if it prints it out more than one time after being touched.

Ye it prints a million times over, and if I continue to stay on the part it just crashes.

Managed to fix it now :+1: forgot I had a debounce further down :sweat_smile:

1 Like

Would there be a need to use RenderStepped in this instance? I feel like even having a while loop that checks every minute or something might do better off than having it run every frame.

Glad I could help. If it still creates lag, then I can suggest another way. You could create a table and store all parts that have event listeners and then create an event listener for each part. Every RenderStep, you could have the script check if the part is in the list, and if not, then it could add it to the list and create an event listener for that part. Here is the RenderStepped part of your code modified in the way that I would do it:

local DoorListeners = {}

RunService.RenderStepped:Connect(function()
	for _, v in pairs(Plots:GetDescendants()) do
		if v:IsA('Model') then
			if v.Name == 'Door' then
				if DoorListeners[v] == nil then -- Checks if the door has already a listener
					DoorListeners[v] = true -- Something that will change the nil value so when it checks, it is not nil.
					v.PrimaryPart.Touched:Connect(function(hit)
						partTouched(hit, v.Parent.Parent, Houses)
					end)
				end
			end
		end
	end
end)
2 Likes

If a plot will be added, say under a folder you could listen for ChildAdded event checking the child is a plot. This would be better than loop or render stepped.

3 Likes

You could try connecting to a .DescendantAdded event, and connect the touched event if it was the door:

for _, desc in pairs(Plots:GetDescendants()) do
	if desc:IsA("Model") and desc.Name == "Door" then
		desc.PrimaryPart.Touched:Connect(function(hit)
			partTouched(hit, desc.Parent.Parent, Houses)
		end)
	end
end

Plots.DescendantAdded:Connect(function(desc)
	if desc:IsA("Model") and desc.Name == "Door" then
		desc.PrimaryPart.Touched:Connect(function(hit)
			partTouched(hit, desc.Parent.Parent, Houses)
		end)
	end
end)

You can also use CollectionService to store tagged doors, and then connect a touched event through GetInstanceAddedSignal:

for _, door in pairs(CollectionService:GetTagged("Door")) do
	door.PrimaryPart.Touched:Connect(function(hit)
		partTouched(hit, door.Parent.Parent, Houses)
	end)
end

CollectionService:GetInstanceAddedSignal("Door"):Connect(function(door)
	door.PrimaryPart.Touched:Connect(function(hit)
		partTouched(hit, door.Parent.Parent, Houses)
	end)
end)
5 Likes

.touched event fires every time something comes in contact or moves while in contact. Also it’s not good to be doing loops in renderstepped cause that alone eats up processing power.

Depends what you’re using RenderStepped for. If you’re running an expensive function in it or something that reasonably shouldn’t be ran before a frame renders, then yes, you’re going to experience issues but it’d be in delays of frames getting rendered rather than hits in processing power.

I can’t use DescendantAdded as the Plots folder already has all the plots in it. When a player joins I just change that plot from ‘Empty’ to the players name. So now plots are actually being ‘added’ per say into that folder, they are all already there before the game starts

Even if .DescendantAdded doesn’t fire for plots that already exist, it should fire for descendants/children of those plots when they are added/when the player’s data loads their doors in. Think of it as binding to an implicit recursive .ChildAdded for every child under Plots.

In this case you can loop through the plots connecting a function to a name change event listener

local function fn()
    -- ...
end

for _, plot in ipairs(plots:GetChildren()) do
    plot:GetPropertyChangedSignal("Name"):Connect(fn)
end