I'm trying to make a part change its color based on the other part that it is touching. How could I do it?

You can write your topic however you want, but you need to answer these questions:

  1. What do you want to achieve? I want to make it change the parts color based on what the parts neighbors color is. I’m working on a HOI4 type of game but you can watch what the AI does, and I want it to invade.

  2. What is the issue? I got the border working, but then it will not continue down the path.

  3. What solutions have you tried so far? I’ve tried looping the script, but nothing will change.

My code below:

local ChanceToInvade = math.random(10,10)

script.Parent.Touched:Connect(function(part)
	while true do
		
		wait(1.5)
		
		if part.Name == "Part" then
			if ChanceToInvade == 10 then
				part.BrickColor = script.Parent.BrickColor
			end
		end
	end
end)

If you can help, then thank you!

I did 10,10 for testing by the way.

You shouldn’t have a loop in an event function. Here is code that should work, but something else may be causing a problem. I’m not exactly sure.

local self = script.Parent

self.Touched:Connect(function(hit)
	local invadeChance = math.random(10)
	
	if hit:IsA("BasePart") and invadeChance == 1 then
		hit.Color = self.Color
	end
end)

If nothing is happening, then try adding print(hit.Name) at the top of the script. There are some caveats to using .Touched that you can read here: BasePart | Roblox Creator Documentation
Basically, .Touched will not fire if the part was moved into another part using CFrame and at least one of the touching parts must have Anchored set to false.

You’ve got a couple things wrong here. Let’s go over them in order.

To get a part’s neighboring parts, you want to use Part:GetTouchingParts(). Part.Touched is an event, and events only fire when something changes. Touched fires when a part begins touching another part, which isn’t what you want. If we switch to GetTouchingParts, we get

local ChanceToInvade = math.random(10,10)

while true do
	wait(1.5)
	local parts = script.Parent:GetTouchingParts()
	for _, part in pairs(parts) do
		if part.Name == "Part" then
			if ChanceToInvade == 10 then
				part.BrickColor = script.Parent.BrickColor
			end
		end
	end
end)

At this point you’re using the correct method, but there’s a bug in the way you’re selecting your random number. Since you call math.random at the beginning of the script it’s only be evaluated once. Your ChanceToInvade will be a constant number. To evaluate it for each part individually you need to put it in the body of the for loop we just added. This will cause it to be declared as a different number each time the for loop executes.

while true do
	wait(1.5)
	local parts = script.Parent:GetTouchingParts()
	for _, part in pairs(parts) do
		if part.Name == "Part" then
			local ChanceToInvade = math.random(10,10)
			if ChanceToInvade == 10 then
				part.BrickColor = script.Parent.BrickColor
			end
		end
	end
end)

Now you’ve got a script that does the following: Every 1.5 seconds, iterate over each part that’s touching the script’s parent. If the chance to invade is 10, change the part’s color to the parent’s color.

1 Like

Just FYI, but there is a new version of :GetTouchingParts() called OverlapParams. That should be used for new work instead.

OverlapParams is used for finding queryable parts within a volume. OP is specifically looking for touchable parts touching a physics object. GetTouchingParts is still fully supported and has its own unique uses.