What's wrong with my script?

  1. What do you want to achieve?

I apologize for the vague topic title; however, I’m not sure how to describe what I’m struggling with.

What I’m specifically trying to do is when the player clicks the TextButton, it searches for whichever plot the player has claimed, then searches for the “Fences” model (or whichever part) within the “House” folder, and then changes the color of the model/part to the desired color.

  1. What is the issue?
    My script is not working when I click on the button to change the color.

  2. What solutions have you tried so far?
    I’ve tried searching Youtube videos and the DevForum but I couldn’t find videos/posts specific to the issue I’m having. The Youtube videos weren’t very detailed and went over how to color a part but nothing else.

Color Button LocalScript:

local plr = game.Players.LocalPlayer
local PlotClaimed = plr.PlotClaimed
local painting = false

script.Parent.MouseButton1Click:Connect(function()
	
	for i ,v in pairs(game.Workspace.PlotFolder:GetDescendants()) do
		if v.Name == "PlayerName" and v:IsA("StringValue") then
			if v.Value == tostring(plr.Name) then
				painting = true
				
				for i ,v in pairs(game.Workspace.PlotFolder:GetDescendants()) do
					if v.Name == "Fences" then
						local Fences = (v.Parent:FindFirstChild("Fences") 
							Fences.Color = Color3.fromRGB(218, 253, 255) 
							
					end
				end
			end
		end
	end
	end)

Screen Shot 2022-07-26 at 12.43.27 PM

PlotFolder Layout & House:


ClaimPart Script:
Screen Shot 2022-07-26 at 12.52.07 PM

	if hit.Parent:FindFirstChild("Humanoid") then
		local plr = game.Players:GetPlayerFromCharacter(hit.Parent)
		if plr and script.Parent.Parent.PlotClaim.Value == false then
			local PlotClaimed = plr.PlotClaimed
			PlotClaimed.Value = true
			script.Parent.Parent.PlayerName.Value = tostring(plr.Name)
			script.Parent.Parent.PlayerNamePart.SurfaceGui.PlayerNameLabel.Text = tostring(plr.Name) .. "'s House"
		end
	end
end)

All plots are named “Plot” within the “PlotFolder”—I need help with having ONLY the player’s plot being targeted.


Here you can see that the PlayerName Value changes to the player who claimed the plot’s username.

& finally, here’s a video of the issue:

Thank you so much for your help, I’ve been struggling to do this for hours and it has caused me a lot of frustration. :slight_smile:

Isn’t fences a group? You can’t color groups. You can color parts.

1 Like

What if I were to create a folder with all the fence parts, would I be able able to color it then? Or if I create a Union?

Union. You can color unions. Be careful though because unions can lose their hitboxes.

2 Likes

Also make sure that the UsePartColor property is ticked.

2 Likes

Can you show me Whats inside “fence”?

1 Like

Inside of the Fence was each Part that made up the fence. Currently making the fences into a union.

Okay! I’ve created two Unions named “Fence” but my script still doesn’t change the color of one of the unions named “Fence”?

local plr = game.Players.LocalPlayer
local PlotClaimed = plr.PlotClaimed
local painting = false

script.Parent.MouseButton1Click:Connect(function()

	for i ,v in pairs(game.Workspace.PlotFolder:GetDescendants()) do
		if v.Name == "PlayerName" and v:IsA("StringValue") then
			if v.Value == tostring(plr.Name) then
				painting = true

				for i ,v in pairs(game.Workspace.PlotFolder:GetDescendants()) do
					if v.Name == "Fence" then
						local Fences = (v.Parent:FindFirstChild("Fence"))
							Fences.Color = Color3.fromRGB(218, 253, 255) 

					end
				end
			end
		end
	end
end)

Want to add in here that you’re reassigning variables.

Working on the assumption that you’ve fixed the issue @Intechill raised, your issue is here:

-- i and v are both independent variables when iterating through all the children of "PlotFolder"
for i ,v in pairs(game.Workspace.PlotFolder:GetDescendants()) do
		if v.Name == "PlayerName" and v:IsA("StringValue") then
			if v.Value == tostring(plr.Name) then
				painting = true
				
                                -- You overwrite i and v here, changing their values.
                                -- Running this, you'll only change the colour of one object (whichever matches tostring(plr.Name) first!)
				for i ,v in pairs(game.Workspace.PlotFolder:GetDescendants()) do
					if v.Name == "Fences" then
						local Fences = (v.Parent:FindFirstChild("Fences") 
							Fences.Color = Color3.fromRGB(218, 253, 255) 
							
					end
				end
			end
		end
	end

Hope this helps.

1 Like

Thank you for helping me! Would this script then target the fences on the player’s plot only? Instead of all the “Fences” in the PlotFolder?

A cleaner way of writing what you’re trying to do would be:

-- Instead of iterating through the descendants of an object to find one object,
-- simply use Luau's in-built method
local playerName = game.Workspace.PlotFolder:FindFirstChild("PlayerName")

-- Checks the value of playerName against the player's name
if playerName.Value == plr.Name then
    -- Iterates through the descendants of the PlotFolder
    for k, v in pairs(game.Workspace.PlotFolder:GetDescendants()) do
        -- Checks whether the currently iterated object has the name "Fences"
        if v.Name == "Fences" then
            -- Finds the sibling object "Fences"
            -- Could forego using this, and just change fences directly?
            -- Equally, this will return nil if none are found, potential security issue
            local fences = v.Parent:FindFirstChild("Fences")
            -- Edits properties
            Fences.Color = Color3.fromRGB(218, 253, 255)
        end
    end
end

The above will affect any object within the PlotFolder that has the name “Fences”.

Hope this helps!

1 Like

Oh! I see what you mean. I’ve changed my script to this so that it won’t rewrite the variable:

local plr = game.Players.LocalPlayer
local PlotClaimed = plr.PlotClaimed
local painting = false

script.Parent.MouseButton1Click:Connect(function()

	-- i and v are both independent variables when iterating through all the children of "PlotFolder"
	for i ,v in pairs(game.Workspace.PlotFolder:GetDescendants()) do
		if v.Name == "PlayerName" and v:IsA("StringValue") then
			if v.Value == tostring(plr.Name) then
				painting = true

			
						local Fences = (v.Parent:FindFirstChild("Fence")) 
							Fences.Color = Color3.fromRGB(218, 253, 255) 

					end
				end
			end
		
end)

I’m trying to have the “Fence” within the player’s plot to change color, not all the fences within the PlotFolder. So I guess I’d like to check to see if the PlayerName within the Plot model is = to the plr.Name and then within that same model have the player’s fence within their plot change color.

Right, I understand you better now.

Looking at your game’s organisation, you’re looking for something like this:

-- Iterates through the primary children of "PlotFolder"
for k, v in pairs(plotFolder:GetChildren()) do
    -- Checks whether the value of the first child found called "PlayerName" is equal
    -- to the player's name

    -- Could be an issue if things initialise slowly with the player,
    -- as :FindFirstChild() will equate to nil if an object isn't found
    if v:FindFirstChild("PlayerName").Value == tostring(plr.Name) then
        -- Iterates through the descendants of the currently iterated plot
        for h, j in pairs(v:GetDescendants()) do
            -- Evaluates the name of the currently iterated object
            if j.Name == "Fence" then
                -- Edits properties
                j.Color = Color.fromRGB(218, 253, 255)
            end
        end
    end
end

Hope this answers your question.

1 Like

Thank you so much for your help! I’ve inserted your script into my game— here’s what it looks like:

local plr = game.Players.LocalPlayer
local PlotClaimed = plr.PlotClaimed
local painting = false

script.Parent.MouseButton1Click:Connect(function()

	-- i and v are both independent variables when iterating through all the children of "PlotFolder"
	for k, v in pairs(game.Workspace.PlotFolder:GetDescendants()) do
		if v:FindFirstChild("PlayerName").Value == tostring(plr.Name) then
			-- Iterates through the descendants of the currently iterated plot
			for h, j in pairs(v:GetDescendants()) do
				-- Evaluates the name of the currently iterated object
				if j.Name == "Fence" then
					-- Edits properties
					j.Color = Color3.fromRGB(255, 152, 220)

					end
				end
			end
		end
end)

However, I’m getting this error:
Players.Auevi.PlayerGui.Paint.Frame.Fence.Color.ColorSelect.Blue.LocalScript:9: attempt to index nil with ‘Value’

I did mention that around here, though for a different reason.

The initial for loop (k, v) iterates through all the primary children of “PlotFolder”. The subsequent line checks for an object that’s a child to the currently iterated object. If it doesn’t find a child object matching “PlayerName”, then the :FindFirstChild() function will return nil.

The issue here, I imagine, is that the currently iterated object of the first for loop hasn’t got a child of this description, and hence isn’t a plot.

Easy to fix by amending our equality check:

if v.FindFirstChild("PlayerName") and v:FindFirstChild("PlayerName").Value == tostring(plr.Name) then

Hope this helps.


Edit: Should add that the last line now requires both the “PlayerName” object to be present, and for its value to equal the player’s name.

:FindFirstChild() will return true if the object is found, and the second half of the and gate will evaluate to true if the value of the object is equal to the player’s name.

3 Likes