How do I detect parts better

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

  1. What do you want to achieve? Keep it simple and clear!
    I want to make a game like https://Territorial.io and I want to find parts near the parts and change their color.

  2. What is the issue? Include screenshots / videos if possible!
    whenever my script find a part it continues on and on and a ton of ray casts cause a ton of lag. e.g. if I want to expand it will just expand to the part right, left, up, down parts
    like this;
    image
    and when you expand again it’ll look like this and so on

  3. What solutions have you tried so far? Did you look for solutions on the Developer Hub?
    Code 1:

	for i,v in pairs(workspace.Europe:GetChildren()) do
		if v:IsA("BasePart") and v:GetAttribute("Owner") == plr.Name and v:FindFirstChild("Done") == nil then
			local inst = Instance.new("BoolValue")
			inst.Name = "Done"
			inst.Parent = v
			local function ray1()
				-- Set an origin and directional vector
				local rayOrigin = v.Position
				local rayDirection = Vector3.new(0, 0, -0.3)

				-- Build a "RaycastParams" object and cast the ray
				local raycastParams = RaycastParams.new()
				raycastParams.FilterDescendantsInstances = {plr.Character}
				raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
				local raycastResult = workspace:Raycast(rayOrigin, rayDirection, raycastParams)

				if raycastResult then
					local hitPart = raycastResult.Instance
					-- Check if the part resides in a folder, that it's fully visible, and not locked
					if hitPart:GetAttribute("Owner") == plr.PlayerValues.Attacking.Value then
						plr.PlayerValues.Pixels.Value += 1
						hitPart.Color = plr.PlayerValues.ColorValue.Value
						hitPart:SetAttribute("Owner",plr.Name)
					end
				end
			end

			local function ray2()
				-- Set an origin and directional vector
				local rayOrigin = v.Position
				local rayDirection = Vector3.new(0, 0, 0.3)

				-- Build a "RaycastParams" object and cast the ray
				local raycastParams = RaycastParams.new()
				raycastParams.FilterDescendantsInstances = {plr.Character}
				raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
				local raycastResult = workspace:Raycast(rayOrigin, rayDirection, raycastParams)

				if raycastResult then
					local hitPart = raycastResult.Instance
					-- Check if the part resides in a folder, that it's fully visible, and not locked
					if hitPart:GetAttribute("Owner") == plr.PlayerValues.Attacking.Value then
						plr.PlayerValues.Pixels.Value += 1
						hitPart.Color = plr.PlayerValues.ColorValue.Value
						hitPart:SetAttribute("Owner",plr.Name)
					end
				end
			end

			local function ray3()
				-- Set an origin and directional vector
				local rayOrigin = v.Position
				local rayDirection = Vector3.new(-0.3, 0, 0)

				-- Build a "RaycastParams" object and cast the ray
				local raycastParams = RaycastParams.new()
				raycastParams.FilterDescendantsInstances = {plr.Character}
				raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
				local raycastResult = workspace:Raycast(rayOrigin, rayDirection, raycastParams)

				if raycastResult then
					local hitPart = raycastResult.Instance
					-- Check if the part resides in a folder, that it's fully visible, and not locked
					if hitPart:GetAttribute("Owner") == plr.PlayerValues.Attacking.Value then
						plr.PlayerValues.Pixels.Value += 1
						hitPart.Color = plr.PlayerValues.ColorValue.Value
						hitPart:SetAttribute("Owner",plr.Name)
					end
				end
			end

			local function ray4()
				-- Set an origin and directional vector
				local rayOrigin = v.Position
				local rayDirection = Vector3.new(0.3, 0, 0)

				-- Build a "RaycastParams" object and cast the ray
				local raycastParams = RaycastParams.new()
				raycastParams.FilterDescendantsInstances = {plr.Character}
				raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
				local raycastResult = workspace:Raycast(rayOrigin, rayDirection, raycastParams)

				if raycastResult then
					local hitPart = raycastResult.Instance
					-- Check if the part resides in a folder, that it's fully visible, and not locked
					if hitPart:GetAttribute("Owner") == plr.PlayerValues.Attacking.Value then
						plr.PlayerValues.Pixels.Value += 1
						hitPart.Color = plr.PlayerValues.ColorValue.Value
						hitPart:SetAttribute("Owner",plr.Name)
					end
				end
			end
			ray1(); ray3();
			ray2(); ray4();
		end
	end
	for i,v in pairs(workspace.Europe:GetChildren()) do
		if v:IsA("BasePart") and v:FindFirstChild("Done") then
			v:WaitForChild("Done"):Destroy()
		end
	end

Code 2:

local p = nil
	for i,e in pairs(workspace.Europe:GetChildren()) do
		if e:IsA("BasePart") and e:GetAttribute("Owner") == plr.Name then
			p = e
		end
	end
	for i,v in pairs(workspace.Europe:GetChildren()) do
		if v:IsA("BasePart") then
			if v:GetAttribute("Owner") ~= plr.Name then
				for i,e in pairs(workspace.Europe:GetChildren()) do
					if e:IsA("BasePart") and e:GetAttribute("Owner") == plr.Name then
						p = e
					end
				end
				local magn = (p.Position - v.Position).Magnitude
				if magn <= 0.6 then
					plr.PlayerValues.Pixels.Value += 1
					v.Color = plr.PlayerValues.ColorValue.Value
					v:SetAttribute("Owner",plr.Name)
				end
			end
		end
	end 

After that, you should include more details if you have any. Try to make your topic as descriptive as possible, so that it’s easier for people to help you!
en

1 Like

If you want to detect parts around a part, this may help: :GetTouchingParts()

using :GetTouchingParts() is terrible idea, it has a very annoying conditions, and its outdated(maybe?). so I recommend the following

  1. ArePartsTouchingOthers
  2. GetPartsInPart
  3. GetPartBoundsInBox

also I would use raycast over the overlap, but it seems like you’ve already tried that, so it you could tell us if there was any errors in the output, then that would be great.

good luck!

Hello! Thank you for the help! but I was wondering if any of these would cause lag, because I have made a system that kind of works but it causes lag when you own multiple parts.

	local folder = workspace:WaitForChild(plr.Name)
	for i,v in pairs(folder:GetChildren()) do
		if v:IsA("BasePart") then
			for i,e in pairs(workspace:WaitForChild("Europe"):GetChildren()) do
				if e:IsA("BasePart") then
					local magn = (e.Position - v.Position).Magnitude
					if magn <= 0.6 then
						--plr.PlayerValues.Pixels.Value += 1
						e.Color = plr.PlayerValues.ColorValue.Value
						e.Parent = folder
						e:SetAttribute("Owner",plr.Name)
					end
	--				task.wait()
				end
			end
		end
--		task.wait()
	end

so I was wondering if any of these would cause lag, and thanks again, I really appreciate it!

is this going through all the parts in the world? if that’s the case then it will most defenatly cause a lot of lag, also, are you doing this in a while true do loop? or are you using run service? if that’s the case, what are you using? stepped? heatbeat? or renderstepped?

1 Like

it’s going through parts in a folder, it’s using for loops activated by a remote event, sorry for the late reply, i had forgotten to check.

Most of the lag from this comes from the fact that you are causing every part to send a ray in all four directions. You could make the rays only shoot in certain directions, although I’m not sure how to program that properly. The best solution, imo, would be to put the newly created parts in a lua table and only create raycasts from those parts, and then wipe the table and replace it with the newly created parts for the next iteration.

Alternatively, since this is a voxel grid, you could instead cache all of the positions in a 3d array and use indexing to modify the parts (i.e. [x+1][y] for the part to the right)

is it going through every single tiles in the world?

this seems confusing, any way you could give a sample code? sorry btw

it goes every tiles in the folder, yes

Well I can’t really give you full sample code because it’s 12am and I’m on a laptop and not at home, but what exactly are you confused about?

oh, sorry i didn’t know it’s 12 am for you guys, but most of the things you just said were confusing to me, like the cache and 3d array. only games i’ve made were jojo games i’m just trying some new stuff sorry.

so it goes through all the tiles, not just the colored ones?

It goes to all the tiles even the colored ones, yes.

by a 2d array (forgot this was 2d, sorry) I mean something like this:

local xMax = 10
local yMax = 10

local arr = {}
for i=1,xMax do
   arr[i] = {}
   for j=1,yMax do
      arr[i][j] = somethingThatTellsYouWhoItBelongsTo
   end
end


Yeah I wouldn’t have thought of this :skull:, alright I’ll try to use this formula soon.

try just the colored ones, I mean is there a reason why you can’t?

I need to subtract the colored one’s position to an uncolored one to get their distance

so you’re going through every tile for every tile, why? why not use raycast to get the adjacent tiles?

I don’t understand, wdym? i tried raycast before but cost alot of lag and some other bugs that are hard to explain