I’m currently working on my building system and players can place down buildings anywhere (different positions or orientations) on the map and it allows them to place a bunch of different things inside of the buildings. What was built inside the buildings can be saved and loaded in any other building of that type which might be at a different location or orientation. How would I structure my save data for this purpose and load what they built back into the correct orientation and position based off of where the building is?
From what I’ve seen, it’s best grouping everything they did together and then pasting it in the map that way. It might be in the same position except it’d be on top of everything else. Just move it down and then ungroup it.
If it spawns randomly, just move the grouped work to the correct position.
Moving it to the “correct position” is part of what I’m trying to understand. How should I go about getting this position based off of the location and orientation of the building? Also, what would be a good way of structuring this within the player’s data (while staying short)?
Actually, group together what the other player has made and paste the group in your own studio and then, copy the id of the position in properties of the group in the other place. Place the position id into the group you pasted in. It shouldn’t be an issue if both places had the exact same map.
I hope it helps.
I think that I haven’t really explained the mechanic of the buildings that well. They can be placed down anywhere in the map and it 99% of the time will not be in the same position or orientation. I would need to get the position of the parts relative to the building meaning not in world-space and thus an approach like this wouldn’t work.
Ah, my apologies. Scripting isn’t my thing, building is.
I hope you fix this problem soon! <3
Am I right in saying that you want players to save a base, and have their furniture transfer to a base of the same size, but in a different position and rotated? Like this?
Yes, exactly. The only changing aspects would be the built building’s position and orientation.
I think this link is exactly what you need: Relative Offset
When you want to store the offset for saving, you’ll have to do:
local offset = buildingBase1:toObjectSpace(furniturePart.CFrame)
Then when you want to load the data onto a new base:
furniturePart.CFrame = buildingBase2.CFrame * offset
Would this require having an attachment somewhere in the base to offset all of the furniture from?
If all what of the player has built is grouped in a model, you can create an invisible block that covers the entire model and is oriented how the entire model is. Then you can get all of the blocks’ CFrames relative to the invisible block’s CFrame:
local BoxCFrame, BoxSize = model:GetBoundingBox()
local saveTable = {Size = {BoxSize.X, BoxSize.Y, BoxSize.Z}}
-- CFrames can't be saved in the datastore, hence why we need to serialise it
function serialize(cf)
return {cf:GetComponents()}
end
for _, part in ipairs(model:GetDescendants()) do
if part:IsA("Part") then
saveTable[#saveTable + 1] = {["SavedCFrame"] = serialise(part.CFrame:inverse() * BoxCFrame)}
end
end
When it comes to loading, you’d create the base part with the size and apply offsets to it. The base can be at any chosen position:
local base = Instance.new("Part")
base.Size = Vector3.new( unpack saveTable.Size )
function deserialise(tbl)
return CFrame.new( unpack tbl )
end
for _, part in ipairs(saveTable) do
local newpart = -- new part
newpart.CFrame = base.CFrame * deserialise(part.CFrame)
end
base:Destroy() -- because we don't need it anymore
EDIT: I meant to do BoxCFrame:inverse() * part.CFrame
for the serialisation part as mentioned below
What’s the difference between using (I’m aware the wiki says they’re the same, so I’ll assume it doesn’t matter)part.CFrame:inverse() * BoxCFrame
and CFrame:toObjectSpace()
here?
Wouldn’t this setup work without the use of a bounding box? Ideally, you could just have a randomly placed attachment that all of the items get placed relative to.
BoxCFrame:ToObjectSpace(part.CFrame)
is the same as BoxCFrame:inverse() * part.CFrame
(I meant to do BoxCFrame:inverse() * part.CFrame)
It can work without a bounding box, but you can keep it if you want to not make the building go out-of-bounds at sometimes. A randomly placed attachment could work
Why would the usage of a bounding box affect the placement’s ability to go out of the bounds? If you had an attachment and one of your 3 items was outside, it would still load in the same position relative to the attachment, right?
Yes, it will, but if the attachment is randomly positioned within the boundaries, for argument’s sake, it’s 20 studs above the bottom boundary and the whole building takes up 60 studs in that direction, some of the building may be out of bounds. I don’t really know your system works but it’s something to consider
I’ll keep that in mind when working on the system. Thanks for the help!