How do I get the middle of multiple parts?

I want to get the middle of these eight blocks, which is the red circle. Just know when I click run, the blocks act like a soft-body cube, and I’m trying to get the middle of all eight blocks.
Screenshot (789)

2 Likes

Well, this only utilizes 2 of the parts, but this should work.

local parts = {} -- all of the parts

local part1
local part2

for i,p1 in pairs(parts) do
    for i,p2 in pairs(parts) do
        if p1.Position.X ~= p2.Position.X and p1.Position.Y ~= p2.Position.Y and p1.PositionZ ~= p2.Position.Z then
            part1 = p1
            part2 = p2
        end
        
        if part1 and part2 then break end
    end
    
    if part1 and part2 then break end
end

local pos = (part1.Position + part2.Position)/2

Do you know how I can make this work with eight parts?

Well, you don’t need to utilize all of the parts, but sure.

local parts = {} -- all of the parts

local pos

for i,part in pairs(parts) do
    if pos then
        pos += part.Position
    else
        pos = part.Position
    end
end

pos /= #parts

Couldn’t you do this like finding the average? Add all the part’s X position, then divide by the number of parts. Then do that for the Y and Z. Right?

You could find the average position of all 8 parts shown in the picture which would be the same as finding where that red dot is.

local Parts = {} --// Your Parts

--// Variables
local FinalPosition = Vector3.new(0, 0, 0)

--// Loops through the parts' positions and adds them up for later use
for i = 1, #Parts, 1 do
    FinalPosition += Parts[i].Position
end
FinalPosition /= #Parts --[[ Divides the total by # of parts to
 find the average/middle position between all parts' positions]]

print(FinalPosition) --// The result
1 Like

This is very odd, @deafaultyboii1324 @Kaid3n22 both scripts get the same result, and the red ball is very offset-ed from the center.

A few questions:

Where are the white dots you mentioned in your original post?

What parts are you using on the Parts variable?

1 Like

The white dots move around, like its an unanchored cube. The parts I’m using is all eight white dots.
sorry for the late reply

something like this? (I have not tested this)

local Parts = {} -- array of parts
local X = {}
local Y = {}
local Z = {}

for i, Part in ipairs(Parts) do
    table.insert(X, Part.Position.X)
    table.insert(Y, Part.Position.Y)
    table.insert(Z, Part.Position.Z)
end

local MaxX = math.max(table.unpack(X))
local MinX = math.min(table.unpack(X))

local MaxY = math.max(table.unpack(Y))
local MinY = math.min(table.unpack(Y))

local MaxZ = math.max(table.unpack(Z))
local MinZ = math.min(table.unpack(Z))

local Middle = Vector3.new((MinX + MaxX) / 2, (MinY + MaxY) / 2, (MinZ + MaxZ) / 2)
1 Like

The lazy way of doing this is to put the parts in a model and get the model’s Pivot

local function GetMiddlePosition(Parts : {Part}) : Vector3
	local Model = Instance.new("Model")
	Model.Parent = workspace
	
	local Stuff = {}
	
	for i, Part in pairs(Parts) do
		table.insert(Stuff, {
			["Instance"] = Part,
			["Parent"] = Part.Parent
		})
		
		Part.Parent = Model
	end
	
	local PivotPosition = Model:GetPivot().Position
	
	for i, Thing in pairs(Stuff) do
		Thing.Instance.Parent = Thing.Parent
	end
	
	Model:Destroy()
	
	return PivotPosition
end
GetMiddlePosition(workspace.Part1, workspace.part2 ... more thingies)

No problem!


Have you welded the 8 parts together? Could you provide a screenshot of the parts and their descendants in the explorer?

MacOS: CTRL + CMD + SHIFT + 4, click and drag
Windows: Open the Snip & Sketch app, capture the screenshot, and press the copy button (top right corner)

1 Like

Well it’s a lot more complicated than just welded parts, they are all held by 28 springs in total. Each point is connected to each other point.
Screenshot 2022-10-05 220732

Do these parts hold a similar shape similar to a cube/the shape formed by the parts shown in your original post?

The script finds the average position among all 8 parts, which means if one part is far away from the others, then the position/red dot is going to be far away from the other 7 parts.

1 Like

Yes, when it is still it is basically a perfect cube

The absolute position/middle position might change from when the script gets the position of all 8 parts and when the loading screen disappears.

You could try setting the red dot’s position later or constantly update its position with game:GetService('RunService'):Heartbeat()(may not be the most performant based on what you need).

1 Like

I already have put it in the heartbeat loop I have.

I don’t see anything wrong here. Just for testing, what happens if you anchor those 8 parts and run the game?

1 Like


Sorry the quality is dog water, I lowered my bitrate to hell because obs was giving me gigantic file sizes, but I fixed it now.

image

function GetCenter(partList)
	local min = nil
	local max = nil
	for _,i in pairs(partList) do
		if not min then
			min = i.Position
		else
			if i.Position.X < min.X then min = Vector3.new(i.Position.X,min.Y,min.Z) end  
			if i.Position.Y < min.Y then min = Vector3.new(min.X, i.Position.Y,min.Z) end  
			if i.Position.Z < min.Z then min = Vector3.new(min.X,min.Y,i.Position.Z) end  
		end
		if not max then
			max = i.Position
		else
			if i.Position.X > max.X then max = Vector3.new(i.Position.X,max.Y,max.Z) end
			if i.Position.Y > max.Y then max = Vector3.new(max.X, i.Position.Y,max.Z) end
			if i.Position.Z > max.Z then max = Vector3.new(max.X,max.Y,i.Position.Z) end
		end	
	end
	
	local center = ((max-min)/2)+min
	return center
end

local tab = workspace.Folder:GetChildren()
local center = GetCenter(tab)

local marker = Instance.new("Part")
marker.Size = Vector3.new(1,1,1)
marker.BrickColor = BrickColor.Red()
marker.Parent = workspace
marker.Position = center
2 Likes