Say theres a script that follows this same process over and over
- taking a random model with parts of various heights, widths and lengths
- cloning it
- and neatly placing it next to the previous model, no gaps or floating parts (Like how a bookshelf is arranged)
(example)

How can I achieve the third step? I already have something setup for the first two steps, but my attempt at the third one failed miserably, seen below.

All the books are at a different height, theres z-fighting everywhere, it’s all a jumbled mess.
I’m sure theres some complicated thing involving math to achieve this. I can reveal some of what I tried to do, but I would still like to keep my code to myself.
3 Likes
Bump 
If it helps to know, what I’m doing right now is multiplying the previous book’s CFrame with it’s thickness and then using that to set the new book’s CFrame with :SetPrimaryPartCFrame().
For example, heres just a snippet of my code
local catalog = {
-- OBJECT, THICKNESS
[1] = {Folder.BookType1, 0.3},
[2] = {Folder.BookType2, 0.2}
{
local function createBook(b, newpos)
local clone = b:Clone()
clone.PrimaryPart = clone:FindFirstChild("Main")
clone:SetPrimaryPartCFrame(newpos)
clone.Parent = bfolder
return clone.PrimaryPart.CFrame
end
local randomBookstats = catalog[math.random(1, #catalog)]
local randomBook = randomBookstats[1]
local bookThickness = randomBookstats[2]
newpos = createBook(randomBook, newpos) * CFrame.new(bookThickness, 0, 0)
-- And then this is looped of course
You will need an accumulator for the total thickness of the books so far.
The first book will start at an x of 0.
Place the book at an x of accumulator + (thickness / 2)
and then add thickness
to accumulator
. The /2
is needed because parts are positioned by their centers.
Repeat until you can’t fit another book (until accumulator + thickness < width_of_shelf
).
The y of each book can just be half its height (again, because parts are positioned by their centers).
FWIW, your original code would’ve worked fine if it accounted for the thickness of both the current book and the previous book.
For example, there are some books of identical thickness in your second image which have no problems because it just worked out right.
edit: The start position (or rather, start CFrame) should be on one of the bottom back inner corners of the shelf, facing forward out of the bookshelf.
Then you just createBook(randomBook, startcf * CFrame.new(x, y, z))
1 Like
Sorry, I’m a little lost (and desperate) so I’m gonna go ahead and give you the place file.
Then could you explain what I need again? If that isn’t too much to ask?
All in all, I did already try something similar to the accumulator thing and then tried it your way which didn’t seem to solve anything.
Unfortunately, I can’t use the place file because I can’t run Roblox or Studio on this computer, so the best I can do is edit the script in the original post.
As implied, I have not tested this code. It should work after you fill in Folder
, bfolder
and the arguments to populateShelf()
at the bottom.
local Folder
local bfolder
local catalog = Folder:GetChildren()
local function populateShelf(shelfCFrame, shelfWidth)
local x = 0
while true do
-- create and setup book
local book = catalog[math.random(1, #catalog)]:Clone()
book.PrimaryPart = clone.Main -- no need for FindFirstChild here methinks. If there is no Main, then that's good, you *should* get an error
local size = book.PrimaryPart.Size
-- if the book won't fit, then stop
if x + size.X > shelfWidth then return end
book:SetPrimaryPartCFrame(shelfCFrame * CFrame.new(
x + size.X / 2,
size.Y / 2,
size.Z / 2
))
x = x + size.X
book.Parent = bfolder
end
end
populateShelf(CFrame.new(), 10)
As you can see, there is an x
variable that starts at 0 and the thickness of each book is added to it.
2 Likes
Thanks, this function helped a lot in fixing it. Everything fits and is level. One last thing though, what’s causing this to happen?
local function populateShelf(shelfCFrame, shelfWidth)
local x = 0
while true do
local book = catalog[math.random(1, #catalog)]:Clone()
book.PrimaryPart = book.Main
local size = book.PrimaryPart.Size
if x + size.X > shelfWidth then return end
book:SetPrimaryPartCFrame(shelfCFrame * CFrame.new(
x + size.X / 2,
size.Y / 2,
size.Z / 2
))
x = (round(x + size.X, 2))
print(x)
book.Parent = bfolder
end
end
-------------------------------------------------
local x = -(start.Size.X/2) + 0.9
for i = 1, columns do
local y = (start.Size.Y/2)
for i = 1, rows do
local shelfcf = start.CFrame * CFrame.new(x, y, -.5)
populateShelf(shelfcf, sps)
y = y + 2.2
end
x = x + 15
end
The last time I checked, 2.2 studs was just enough to ascend one shelf. I’m probably stupid and forgetting to do something you already mentioned.
Not at all.
I think you just have to increase that 2.2
to the distance between two shelves.
So if one shelf’s Y is at 2 and another’s is at 4.5, then that would be 2.5, for example. I don’t have the measurements you do, though.
I would also suggest running this function for each of these spaces between shelves, as right now the books are clipping into these pillar things.
1 Like
Yeah, 2.2 is the distance between two shelves. Even if I go 0.1 up it’ll leave gaps
2.2 seems to be precise for the first two shelves before it starts falling short
Then I can’t imagine what could be causing this. Maybe the shelves aren’t all 2.2 studs apart?
1 Like
My bad. All the shelves werent the same distance apart so I fixed that.
Thanks again