Creating A Furniture Placement System

just use a invisible part as the canvas area

3 Likes

How do you convert Vector2 to Vector3? Also, how do you make objects stack?

4 Likes

Vector2 to Vector3
– I don’t know why you want to achieve this, but here is easy solution
Vector3.new(vec2.x, 0, vec2.y) or Vector3.new(vec2.x, vec2.y, 0)
Object stack
– I assume ‘stack’ that you mean is something like lamp place on the table.
In this example, just make placement canvas as desk surface or hidden canvas on desk surface.
– I assume that later question relate to first one, where extra axis of vector is current ‘height’ of object stack, I don’t recommend to store data that way, I prefer something like this:

"canvas": {
    "item": Furniture:getId("desk"),
    "position": Vector2.new(12, 24),
    "rotation": 90,
    --"__comment": "You can use something like this if you prefer, 'transform: Vector3.new(x, y, rotate)' ",
    "canvas": {
        --[[ 1:]]{
            "item": Furniture:getId("lamp"),
            "position": Vector2.new(0, 0),
            "rotate": 0,
            --"__comment": "canvas: {} --if you want item to place-able to your lamp! Side note, position should relate to it parent not main canvas or world"
        }
    }
}

Do you see that is better to store data object this way than array of vector of x,y,height and if player move table, lamp move too. If player remove table, lamp gone as well. No floating lamp anymore.

I wrote it in JSON format because it is compatibility with Database Datastore, and it also look like Lua table too.

– If you mean building floors, almost same to desk example :

"plot": {
    --[[1: ]]{
        "canvas": {DeskWithLampObj, chairObj}
    },
    --[[2: ]]{
        "canvas": {}
    }
}

If I am wrong with your question, feel free to notice me to correct it.

6 Likes

How can I make objects have them stack like a minecraft placement system?

5 Likes

I don’t understand it at all @EgoMoose. Why

local something = Placement.__index -- ???
2 Likes

It’s a metamethod, it’s used in Placement.new(). It lets you call the functions of the new placement.

Basically, all you need to know is every time you write a class, you use __index.

3 Likes

Ok which means:

local Placement = Placement.new(parameter1)
local something = Placement.__index --the parameter1 == __index???
3 Likes

No, like this:

Placement.__index = Placement -- placement is the default value
setmetatable({}, Placement) -- when it is used
2 Likes

Ok, but the __index canot be use then the metatable is not created?

2 Likes

@mobyboyy, i get the error: ServerScriptService.Script (0,15):Exepted identifier, got “.“

1 Like

You don’t create a Placement instance, you use that when writing the class. The class doesn’t exist yet.

2 Likes

How would I go about to stop placement once saved?
I tried referencing RenderStepped to disconnect it, however, this happens after I go back to place furniture.


During the first try, it works perfectly fine. After I disconnect and attempt to place furniture, RenderStepped doesn’t work as it should.

10 Likes

You can achieve that with something like this: is important to unbind from the client if you want to finish placement, if u want you could set on saved function (on client too) change the variable or even unbinding directly. I hope this can help. Please excuse my english.

plr:WaitForChild("Editing").Changed:Connect(function()
if plr.Editing.Value == true then
	if model then
		if model.Parent == nil then
			model.Parent = placement.CanvasObjects
		end
	end

	game:GetService("ContextActionService"):BindAction("switch", onSwitch, false, Enum.KeyCode.E)
	game:GetService("ContextActionService"):BindAction("rotate", onRotate, false, Enum.KeyCode.R)
	game:GetService("ContextActionService"):BindAction("place", onPlace, false, Enum.UserInputType.MouseButton1)
	game:GetService("ContextActionService"):BindAction("clear", onClear, false, Enum.KeyCode.C)
	game:GetService("ContextActionService"):BindAction("save", onSave, false, Enum.KeyCode.F)
else
	if model then
		model.Parent = nil
	end
	game:GetService("ContextActionService"):UnbindAction("switch", onSwitch, false, Enum.KeyCode.E)
	game:GetService("ContextActionService"):UnbindAction("rotate", onRotate, false, Enum.KeyCode.R)
	game:GetService("ContextActionService"):UnbindAction("place", onPlace, false, Enum.UserInputType.MouseButton1)
	game:GetService("ContextActionService"):UnbindAction("clear", onClear, false, Enum.KeyCode.C)
	game:GetService("ContextActionService"):UnbindAction("save", onSave, false, Enum.KeyCode.F)
end

end)

5 Likes

I’d recommend using :GetPropertyChangedSignal("Value") rather than .Changed

6 Likes

I’ve been reordering my code to implement this. It’s slightly better(when you place again its smooth). However, none of the binds work in the second time and I’ve been messing with it to get the binds to work. So far, here’s the current code

onSwitch(nil, Enum.UserInputState.Begin, nil)

	game:GetService("ContextActionService"):BindAction("switch", onSwitch, false, Enum.KeyCode.E)
game:GetService("ContextActionService"):BindAction("rotate", onRotate, false, Enum.KeyCode.R)
game:GetService("ContextActionService"):BindAction("place", onPlace, false, Enum.UserInputType.MouseButton1)
game:GetService("ContextActionService"):BindAction("clear", onClear, false, Enum.KeyCode.C)
game:GetService("ContextActionService"):BindAction("save", onSave, false, Enum.KeyCode.F)



player.playerData.Editing:GetPropertyChangedSignal("Value"):Connect(function()
if player.playerData.Editing.Value == true then
	if model then
		if model.Parent == nil then
			model.Parent = placement.CanvasObjects
		end
	end
elseif player.playerData.Editing.Value == false then
		game:GetService("ContextActionService"):UnbindAction("switch", onSwitch, false, Enum.KeyCode.E)
	game:GetService("ContextActionService"):UnbindAction("rotate", onRotate, false, Enum.KeyCode.R)
	game:GetService("ContextActionService"):UnbindAction("place", onPlace, false, Enum.UserInputType.MouseButton1)
	game:GetService("ContextActionService"):UnbindAction("clear", onClear, false, Enum.KeyCode.C)
	game:GetService("ContextActionService"):UnbindAction("save", onSave, false, Enum.KeyCode.F)
end
end)

 game:GetService("RunService").RenderStepped:Connect(function(dt)
	local cf = placement:CalcPlacementCFrame(model, mouse.Hit.p, rotation)
	model:SetPrimaryPartCFrame(cf)
end)
2 Likes

Wow, thanks so much! I definitely will use this in the future.

What about mobile support, I have a lot of players who are mostly on phone and placing on phone is really terrible, can you show us also how it make mobile support? That would be great, but overall tutorial is pretty well made and explained.

2 Likes

Oh that is because you are unbinding your keys but not binding them again, u can move your bindActions inside the PropertyChanged function (when Editing is true), so it will work only when activated and not from the beginning. Also it will work in the second time because it will be bind again. I hope u find this helpful. :smiley:

3 Likes

I am unsure how I would get started at making a window-feature. Exactly how bloxburg does it. To make a model intersect a wall. I can’t wrap my head around it.

3 Likes

I’m guessing in its simplest form a model is positioned on a given plane, your wall for example, and then parts are then redrawn around the window model based on the given position and sizes of the model. I think roller coast tycoon also does something similar to this with its terrain to generate minimal amounts of parts but i’m not 100%. You also might be able to accomplish this with the real-time CSG but I haven’t really used this so i don’t want to comment too much on it. You could probably try both these options though.

Real-time CSG: New Roblox In-Game CSG API is now available

1 Like