Why does disabled collision have a delay?

this is the code:

local rs = game:GetService("RunService")
local player = game.Players.LocalPlayer
rs.RenderStepped:Connect(function(plr)
	for _, descendant in pairs(workspace:GetDescendants()) do
		if descendant:IsA("BasePart") and descendant.Name == "Boulder" then
			if descendant.Player.Value ~= player.Name then
				descendant.CanTouch = false
				descendant.CanCollide = false
			end
		end
	end
end)

it works but it always have a dalay, which is enough for player to move boulders that isn’t theirs

You should change workspace:GetDescendants(). Because your loop checks all of the workspace objects and their children. You should store your parts in a folder. It will be faster when you make this.

Another option is to use CollectionService to tag your boulders and iterate through but you can still put them anywhere in your hierarchy.

Yea, @taner60 explained a good solution. You should also be using events like .DescendantAdded instead of RunService.RenderStepped for this.

Fixed code:

--//Serivces
local Players = game:GetService("Players")

--//Variables
local LocalPlayer = Players.LocalPlayer

--//Functions
local function OnDescendantAdded(descendant)
	if descendant.Name ~= "Boulder" or descendant.Player.Value == LocalPlayer.Name then
		return
	end
	
	descendant.CanTouch = false
	descendant.CanCollide = false
end

--//Changing it to .ChildAdded would greatly help performance but only do so if the script still works after
workspace.DescendantAdded:Connect(OnDescendantAdded)

for i, descendant in ipairs(workspace:GetDescendants()) do
	task.spawn(OnDescendantAdded, descendant)
end
--//Serivces
local Players = game:GetService("Players")
wait()
--//Variables
local LocalPlayer = Players.LocalPlayer

--//Functions
local function OnDescendantAdded(descendant)
	if descendant.Name ~= "Boulder" and descendant.Player.Value ~= LocalPlayer.Name then
		return
	end

	descendant.CanTouch = false
	descendant.CanCollide = false
end

--//Changing it to .ChildAdded would greatly help performance but only do so if the script still works after
workspace.DescendantAdded:Connect(OnDescendantAdded)

for i, descendant in ipairs(workspace.Balls:GetDescendants()) do
	task.spawn(OnDescendantAdded, descendant)
end


it says theres no player in boulder when there clearly is

Do you have any other children inside that boulder that are also named player?

Also, use this script instead: (only if all boulders spawn in balls)

--//Serivces
local Players = game:GetService("Players")

--//Variables
local LocalPlayer = Players.LocalPlayer
local Balls = workspace:WaitForChild("Balls")

--//Functions
local function OnBoulderAdded(boulder)
	print(boulder:GetChildren())
	if boulder.Player.Value ~= LocalPlayer.Name then
		return
	end

	boulder.CanTouch = false
	boulder.CanCollide = false
end

Balls.ChildAdded:Connect(OnBoulderAdded)

for i, boulder in ipairs(Balls:GetChildren()) do
	task.spawn(OnBoulderAdded, boulder)
end


maybe i should rename the stringvalue to something else
i have to go i will try something else later