Change model's color without looping

I have a placing system where theres already a while task.wait() do loop that checks if the object that you are gonna place will collide with other objects or not. If it does, then it will use a for i, v in pars() loop through the model’s childrens which are baseparts and change their color to red; otherwise, change it to green. It works fine with models that have not too much parts in it, but theres a christmas tree model with over 100 parts in it. If I add an empty wait() or task.wait() function then it will take around a minute to loop through them. If I don’t use any then it takes around a few seconds of lag to simply change the color. Can anyone help me to be able to change the color fast without causing lag? The keys is to not use loops. Thank you so much!

How about having already colored models in ReplicatedStorage and clone the model with the color whenever you need to change the color

oof but i think that would be more laggin tho ;-;

How about try adding yields inside the loop but the yield will depend on the player’s frame

game:GetService(“RunService”).Heartbeat:Wait()

So it will be like

-- Example
for i, v in pairs(model:GetChildren()) do
   game:GetService(“RunService”).Heartbeat:Wait()
   v.Color = Color.fromRGB(255, 0, 0)
end

You should try out both methods that I have posted and test which one is better

I don’t believe that 100 Parts with no wait, will lag a few seconds. I’m saying there are over 1000 Parts & Joints(which also must be checked for BaesePart…) or

there is some other bug in your code which you did not show.

If 1000s, then you can try wait(); every 100 parts or so…? I do that checking 2400 nodes of a Map…

Or you could, just for the Tree, Divide the Model into Four Special “Red”/Green" Glass Parts, and only check those Parts,… or…

This “lag” is probably occurring because you are constantly setting the color of all the parts in the model. What you could do is have a debounce that checks if it already set the color of the model to red/green. You shouldn’t be setting any value constantly in a loop if you only want to change it once.

Note that there may be typos!
This is what I imagine you currently have:

-- Example of what you currently have:
while true do 
	task.wait(); 
	if CanTouch == false then -- CanTouch represents whether the model can touch the area as u mentioned
		for _, Part in ipairs(MyModel:GetChildren()) do -- This is going to loop through all the children of the model even if the color was already set previously!
			Part.BrickColor = BrickColor.new("Bright red");
		end;
		-- Do other stuff here if model CANNOT touch
	else
		-- Sets color to green
		-- Do other stuff here if model CAN touch
	end;
end;

This is an example of what you can do:

-- Example of what you could do:
local SetColor = true; -- True == green, False == red

while true do 
	task.wait(); 
	if CanTouch == false then -- CanTouch represents whether the model can touch the area as u mentioned
		if SetColor then -- Checks if the SetColor is currently true (aka green)
			SetColor = false; -- Now that we set "SetColor" to false, the if statement won't pass.
			for _, Part in ipairs(MyModel:GetChildren()) do -- Now this loop only runs once!
				Part.BrickColor = BrickColor.new("Bright red");
			end;
		end;
		-- Do other stuff here if model CANNOT touch
	else
		if not SetColor then -- Checks if the SetColor is currently false (aka red)
			SetColor = true;
			-- Sets color to green
		end;
		-- Do other stuff here if model CAN touch
	end;
end;

Below is just some suggestions that don’t relate to your main issue but might be of use to you!

Another tip would be to ditch the while loop all together. A good thing to remember that you really only want to use a loop when you want an action to CONSTANTLY happen. In your case you only want the model to update its position whenever the player moves their mouse (assuming that’s how your placement system works). Therefore instead of using a while loop that constantly runs (even if the players mouse position stays the same), you should instead only update the models values when the player moves their mouse.

This helps lighten the load on the server/computer. You can still use the while loop but you should compare the players current mouse position and their last mouse position → If it changed then run all of the code you need to such as: detecting if it collided with a part it shouldn’t, updating the models visual position, updating the color, etc.

Anyway goodluck with your game!

Its 5am here and I’m super tired so hopefully my explanations were clear and I didn’t make a bunch of typos.

hi, i need to use while loop because the system is based on in rfont of the player, not the mouse. so maybe I can union the model?

You could do a system where when ever the part itself moves

Use GetTouchingParts and then through that you can check the 3d region of the said touching parts.

So instead of looping through like 100 it’ll loop through 4

Since you are using a place system based on the models the loop needs to check them all as you said.

What if you use some sort of hitboxes to check them? For a tree for example just use a hitbox for all the leaf and one for the log resulting in two cubes as hitboxes, it will may be a little less precise but unless you want to be able to place objects on too much complex parts that would need a lot of hitboxes then should be fine

um yes i do use a hitbox but the reason i loop is not for checking for collision, it is for changing the color, as the name says

If you put the model inside the collision box and change the collision box color to green the whole model will look like green, doing like this may be useful

Are we talking about collission detectors (turns red if they collide or green if they can be placed)? If so, rather don’t make the whole model change color; instead, use a singular part which covers the whole height/width/depth of the object being placed.
A lot of popular games tend to go that route if their models have too many parts or they follow your idea if they’re working with custom singular meshes.

1 Like