Notice
This module uses deprecated code and is no longer being updated. For a system that is being actively updated, please use this tutorial instead: https://devforum.roblox.com/t/how-to-use-placement-service
Zblox’s placement module (V2) tutorial
Hello! In this tutorial, I will show you how to use my placement module that I have been working on. This includes:
- How to set up your game to work easily with the module,
- How to build models with primary parts
- How to trigger placement,
- How to finish placement using a remote event,
- Editing settings to further customize the module.
- Limitations
The first thing you will need, is to get the module from the catalog. Once you have that, we can move on (keep in mind, this module is used for sandbox tycoon games)!
Setting up your game!
Now, this is not required to work, but I recommend first time users to use this setup.
Insert a model or folder into the workspace, and call it Plots
. Then add a model call it Plot
, and put a folder and a part in inside it. Call the part Plot
and the folder PlacedObjects
(or something like that). After your done, it should look something like this:
Let’s scale the Plot
part to 180 (x), 1 (y), 180 (z)
and place it on top of the baseplate. Make sure you anchor it!
Next, we will wan’t to get the module in our game. Add in a folder called modules
and put in ReplicatedStorage
. Next, put the module in there. We will also want a folder for models and remote events.
It should look something like this:
Now we will add a remote event in the Events
folder. I called mine PlaceObj
since that is what we will be using it for. In StarterGui, add a ScreenGui, and make any sort of UI interface you want. I just have a simple text button with a few changes in the properties menu. I named it Trigger
. Now you wan’t to add a LocalScript in the ScreenGui. Name it ClientPlacement
since that is what it is.
Here is my setup for the UI:
The final thing for setup is to add a server side script in ServerScriptService
and call it ServerPlacement
.
Great!
Building models
This is one of the most important parts of this tutorial. To start off, you are going wan’t to build on the grid texture you choose.
This is to ensure the model will snap to the grid when you are moving the model around. This is mainly for the primary part.
Primary Parts
The primary part is the object that the model snaps to the grid with. To make this, first group your item into a model and name it whatever you like. Click on the model and in properties you will see PrimaryPart as a setting. Before we set this, we need to create the PrimaryPart. You can build this however you want just make sure it covers the box the model creates on the x and z coordinates.
Next, put this part in the model and set it as the primary part by clicking primary part on the model and then clicking on the part you wan’t to be the primary part. Once your done, place the model on top of your plot and then put it in that models folder we created.
Triggering placement
In that ClientPlacement
script, we will be doing some work here. Make variables for ReplicatedStorage
, Players
and the module.
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
local placementModule = require(ReplicatedStorage.Modules.PlacementModuleV2)
local trigger = script.Parent.Trigger
Next, detect when the button is clicked, and invoke the function new().
trigger.MouseButton1Click:Connect(function()
placementModule:new()
end)
In the new() function there are a few things we need to feed it.
- string Model name,
- obj Models location (where they are located),
- obj The plot location (the part you want the texture to be shown on),
- obj Location where the objects are going to end up once placed,
-
bool Toggle
stackable
objects, - bool Rotation type (I will let you play with this instead of me explaining this).
I will make variables for some of these things so the line does not get too long.
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
local placementModule = require(ReplicatedStorage.Modules.PlacementModuleV2)
local trigger = script.Parent.Trigger
local plot = game.Workspace.Plots.Plot.Plot -- added
local placedObjects = game.Workspace.Plots.Plot.PlacedObjects -- added
local models = ReplicatedStorage.Models -- added
trigger.MouseButton1Click:Connect(function()
placementModule:new()
end)
Let’s give the function it’s fuel!
trigger.MouseButton1Click:Connect(function()
placementModule:new("Chair", models, plot, placedObjects, false, false) -- edited
end)
This will let you move the object around while using all the controls. Now we need placement!
Placing down objects
Staying in the same script, we need to make a few more variables for the player, mouse and the remote event.
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
local placementModule = require(ReplicatedStorage.Modules.PlacementModuleV2)
local trigger = script.Parent.Trigger
local plot = game.Workspace.Plots.Plot.Plot
local placedObjects = game.Workspace.Plots.Plot.PlacedObjects
local models = ReplicatedStorage.Models
local remote = ReplicatedStorage.Events.PlaceObj -- added
local player = Players.LocalPlayer -- added
local mouse = player:GetMouse() -- added
trigger.MouseButton1Click:Connect(function()
placementModule:new("Chair", models, plot, placedObjects, false, false)
end)
Now we need to detect when the mouse button is clicked. We will also invoke a function called Finish(). This will place the object down onto the desired location.
mouse.Button1Down:Connect(function()
placementModule:Finish()
end)
In the Finish() function, all you need to give it is the remote event.
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
local placementModule = require(ReplicatedStorage.Modules.PlacementModuleV2)
local trigger = script.Parent.Trigger
local plot = game.Workspace.Plots.Plot.Plot
local placedObjects = game.Workspace.Plots.Plot.PlacedObjects
local models = ReplicatedStorage.Models
local remote = ReplicatedStorage.Events.PlaceObj
local player = Players.LocalPlayer
local mouse = player:GetMouse()
trigger.MouseButton1Click:Connect(function()
placementModule:new("Chair", models, plot, placedObjects, false, false)
end)
mouse.Button1Down:Connect(function()
placementModule:Finish(remote) -- edited
end)
This completes the client side of the system.
Server side
In the server script we created, we need to listen for the remote event to be fired.
local function Place(plr) -- plr is passed automatically
end
game.ReplicatedStorage.Events.PlaceObj.OnServerEvent:Connect(Place)
The remote event gives us all the information needed to find and place the object.
-
Player
-
The data for the model name and rotation,
-
The location of where the model is to be placed,
-
The position.
local function Place(plr, data, location, pos) -- edited end game.ReplicatedStorage.Events.PlaceObj.OnServerEvent:Connect(Place)
Using this data we can get the model and set the appropriate properties.
local function Place(plr, data, location, pos)
local model = game.ReplicatedStorage.Models:FindFirstChild(data.Name):Clone() -- added
model.PrimaryPart.Transparency = 1 -- added
model.PrimaryPart.CanCollide = false -- added
end
game.ReplicatedStorage.Events.PlaceObj.OnServerEvent:Connect(Place)
The last thing is to set the position of the model using CFrames
and set the parent.
local function Place(plr, data, location, pos)
local model = game.ReplicatedStorage.Models:FindFirstChild(data.Name):Clone() -- added
model.PrimaryPart.Transparency = 1
model.PrimaryPart.CanCollide = false
model:SetPrimaryPartCFrame(CFrame.new(pos.X, pos.Y, pos.Z) * CFrame.Angles(0, math.rad(data.CFrame.Rotation), 0)) -- added
model.Parent = location -- added
end
game.ReplicatedStorage.Events.PlaceObj.OnServerEvent:Connect(Place)
That’s it! Now we can move, rotate and place down objects!
Customizing placement
To further customize your placement system, you can edit the settings in the module. I will go over them all right now.
- bool MoveByGrid. This controls if you want the model to move by a grid,
- int GridSize. The grid that the model moves by,
- bool DisplayGrid. If you wan’t to show a grid while placing,
- bool SmartDisplay. This will make the grid rescale depending on the grid size,
- string GridTexture. The texture you wan’t to show when placing the model,
- bool Interpolate. This smooths the movement and rotation,
- number InterpolateSpeed. The speed of the interpolation (a value from 0, 1) 0 = instant,
- int RotationStep. How many degrees the model will rotate when you press the rotate key,
- int FloorStep. How many studs the model will move up/down when you toggle the floor keys,
- int MaxHeight. The maximum height the model can reach,
- number CollisionCheckCooldown. The cool down before placing down the object to ensure the models collision state,
- bool DetectCollisions. This toggles collision detection,
- bool IgnoreItems. If you wan’t the mouse to ignore everything else placed on the plot,
- bool BuildModeEnabled. This will not stop placement until the cancel key is placed,
- bool EnableFloors. This toggles the floor system,
- bool TransparentModels. This edits the models transparency when placing,
- Color3 CollisionColor. Color of the models primary part when colliding with another model/object,
- Color3 PlacingColor. Color of the models primary part when not colliding,
- KeyCode KeyCodeCancel. Key needed to be pressed to cancel placement,
- KeyCode KeyCodeRotate. Key needed to be pressed to rotate the model,
- KeyCode KeyCodeRaiseFloor. Key needed to be pressed to raise the floor,
- KeyCode KeyCodeLowerFloor. Key needed to be pressed to lower the floor.
Other settings
- number transparentDelta. The change in transparency if TransparentModels is enabled,
- number hitboxTransparency. The transparency of the models primary part when placing,
- number step. If stacking is enabled, the step is used to correct the models y pos.
These settings total to 25 including the “other ones”. These can make a quite unique placement system.
Limitations
Now, there are some big limits on this modules current state. One main one being it cannot be used for mobile or consoles (yet). It’s also not meant to be used for anything other than sandbox tycoons. One last one being you have to follow a couple steps to make grid snapping work perfectly.
- The plot has to be a multiple of your grid size,
- The grid size should (in most cases) be an even number (no decimals)
More info
I am still working on this module to add more functionality so suggestions would help. I don’t require any credit to use in a game, but you can if you want.
Anyway, here’s a video showing the module in action!
A test place was linked here before. It has been removed due to the module being outdated. Please see the link at the top to go to the current module tutorial. There is a link to test that module at the end.
Good luck!