My Placement Script isn't making the place able parts align up in a grid according to the orientation of the plot!

  1. I want my script to make the player be able to place down objects on their plot in a Grid. The objects will be moveable in a 2 by 2 grid.

  2. When I tested out my script which is local (Still need to add the server event) it moved the part to the Mouse.Hit.Position but when I moved my mouse it would be oriented correctly (because the plots are all different orientation because of how I laid them out) but the parts / objects would not seem to move in a grid according to the plots orientation. It seemed like the moving of the part with the grid made the grid be aligned at (0, 0, 0) orientation instead of the plots orientation causing the part to move by 2 studs just not 2 studs either forward, sideways, or downwards. Because the grid makes the part move 2 in a wrong orientation the part moves smooth diagonal(or the way pointing at (0, 0,0) and moves irregular or not how it should when you move your mouse forward as seen here:

  3. I looked at other forums and posted this question and no one had a clue to help direct me to fix this. Please help! I really want to release my game and without this, I can’t.

local Player = game.Players.LocalPlayer
local Mouse = Player:GetMouse()
local Camera = game.Workspace.CurrentCamera

local BuildPro = false
local OnPlot = false

local BuildUi = script.Parent.FHOS.Frame.BuildFrame

local MarketPlaceService = game:GetService("MarketplaceService")
local RunService = game:GetService("RunService")
game.Players.PlayerAdded:Connect(function()
	local hasPass = false
	
	local success, message = pcall(function()
		hasPass = MarketPlaceService:UserOwnsGamePassAsync(Player.UserId, 11321181)
	end)
	if not success then
		warn("Error while checking if player has pass: " .. tostring(message))
		return
	end
	if hasPass == true then
		BuildPro = true
	end
end)

local UIS = game:GetService("UserInputService")
local Grid = 2
local Rot = 0

local PosX
local PosY
local PosZ
local Plot
local PlotO
local PlotX
local PlotY
local PlotZ
local Object

local GivenPlot = game.ReplicatedStorage.BuildEvents.GivenPlot
local PlaceObject = game.ReplicatedStorage.BuildEvents.PlaceObject
GivenPlot.OnClientEvent:Connect(function(plt)
	Plot = plt
	PlotO = plt.Orientation
	PlotX = PlotO.X
	PlotY = PlotO.Y
	PlotZ = PlotO.Z
end)

Plot.Touched:Connect(function(hit)
	local plr = game:GetService("Players"):GetPlayerFromCharacter(hit.Parent)
	if plr then
		OnPlot = true
	end
end)

local CanStart = true
local Placing = nil
local CanPlace = nil
local MoveObject = false
local CanPlace
local BuildMode = Instance.new("BoolValue")
BuildMode.Parent = Player
BuildMode = false
BuildSelection = BuildUi.ScrollingFrame
Soil = BuildSelection.SoilSelect.ImageButton

script.Parent.FHOS.Frame.Frame.BuildModeApp.TextButton.MouseButton1Click:Connect(function()
	script.Parent.FHOS.Frame.Frame.Visible = false
	script.Parent.FHOS.Frame.FhBrand.Visible = false
	script.Parent.FHOS.Frame.Power.Visible = false
	script.Parent.FHOS.Frame.Time.Visible = false
	script.Parent.FHOS.Frame.Network.Visible = false
	script.Parent.FHOS.Frame.Battery.Visible = false
	script.Parent.FHOS:TweenPosition(UDim2.new(0.105, 0,0.485, 0), "Out", "Linear", 1, false, nil)
	while script.Parent.FHOS.Rotation > -90 do
		script.Parent.FHOS.Rotation = script.Parent.FHOS.Rotation - 1
		wait()
	end
	BuildMode = true
	if BuildMode == true and OnPlot == true or BuildPro == true then
		Camera.CameraSubject = Plot
	end
end)

local function SnapToGrid()
	PosX, PosY, PosZ = math.floor(Mouse.Hit.X / Grid + .5) * Grid, math.floor(Mouse.Hit.Y / Grid + 1) * Grid, math.floor(Mouse.Hit.Z / Grid + .5) * Grid
end

local function MouseMoved()
	Object.PrimaryPart.Position = Vector3.new(PosX, PosY, PosZ)
	SnapToGrid()
end

local function CloneService(Obj)
	Object = game.ReplicatedStorage.BuildObjects:FindFirstChild(Obj):Clone()
	Object.Parent = Plot
	
	Object.PrimaryPart.Orientation = Vector3.new(PlotX, PlotY, PlotZ)
	Mouse.Move:Connect(MouseMoved)
end

Soil.MouseButton1Click:Connect(function()
	CloneService("Soil")
end)
3 Likes

Well I was hoping you had an answer or suggestion but its TestUser4646 because I use him for testing things in my game. I also use this account to ask questions on other forums such as Scripting Helpers. Hope this answers your question.

This seems to be the code responsible for placing the model:

local function SnapToGrid()
	PosX, PosY, PosZ = math.floor(Mouse.Hit.X / Grid + .5) * Grid, math.floor(Mouse.Hit.Y / Grid + 1) * Grid, math.floor(Mouse.Hit.Z / Grid + .5) * Grid
end

Object.PrimaryPart.Position = Vector3.new(PosX, PosY, PosZ)

Since you’re just setting the position to some world-space coordinates based on where the mouse is pointing, and since you’re just snapping it by rounding these world-space coordinates, it makes sense that it wouldn’t take into account the orientation or position of the grid.

The easiest solution by far is to just make sure every “grid part” is aligned so that it works, but that obviously limits you a little bit.

Actually making it work

What you’re doing makes sense when a “grid part” is aligned correctly, but that’s not always the case. It can be rotated, or even just moved over a little bit, say half a grid spacing. So to make it work we need to align the models to a grid that’s relative to the grid part that the model is being placed on.

We can do this by transforming the mouse Hit to the Plot’s object-space, then rounding the transformed position and finally transforming it back into world-space. That way the position won’t rounded to the nearest 5, but to the nearest 5 from the plot’s center. It will also be rounded in a way that takes into account the rotation of the plot, so you can plots on vertical cliff-sides if you want to.

Doing this, we get something that looks like so:

sEypUQWg2W

Here’s a model file that you can drag-and-drop into an open Place. The code isn’t exactly like yours, but try and adapt it to work with your existing code. If you need help with that let me know :slight_smile:

GridPlacement.rbxm (3.7 KB)

7 Likes

One word… AMAZING!!! I’ve been searching for a solution this whole summer!!! Now I can finish my build system and hopefully my game. Thank you so much!

2 Likes

Sorry I know you already had a solution but I’m having a problem that when i place objects / models with cylinders because i rotated the cylinders to make them for example like a flag pole because the orientation changes the cylinder when placing is turned back to o, o, o, making the object look not how it was supposed to.

1 Like

Can you post a screenshot of what you mean?


Some parts like cylinders are oriented to (0,0,0) making them flip. How could I make it so it does not change the models way they are rotated but still be aligned with the plot

Oh. You’ll want to set the PrimaryPart of each model to an invisible Part that’s oriented so that the front, top and right faces of the part line up with the respective sides of the model. I.e. the top “face” of the model faces upwards, and so does the Part’s.

How can I make it place on server side???

All the stuff that’s only visual effects should be handled on the client. Once a player has decided on where and how to place which model, that information should be sent to the server so that it can independently verify that it’s valid. If you’ve created a local clone of a model to show the player what they’re doing, you’ll most likely want to get rid of that cloned, “visual only” model on the client, so that once the server creates the real model, there’s only one version that exists.

You’ll most likely want to send this to the server:

  • Which model is being placed? A name or ID number, not a reference to the local clone of the model.
  • Where is it being placed? This could be a Vector3 Position and a CFrame rotation, or (X, Y) coordinates for position and a number representing how many “rotation steps” to rotate the model (e.g. 2*90 deg = 180 deg).

You send it with a RemoteEvent, and deal with verifying and reacting to the information with a Script (not a LocalScript). It could be called “PlacementManager” or “BuildingManager” or something like that. Even if the client did some checks to make sure things are being placed correctly, you can’t trust that. The server will have to do all the same checks to make sure no buildings get placed in an invalid manner.

Thanks for the help and sorry about asking for more information… But… I’m curious if you know how I can make it so it saves so when the player comes back the objects are still there. Hope you can help or give a suggestion

Simply changing the size of the object that is supposed to snap to the grid can instantly lead to the object not alliging again, so either this script is outdated or never worked well from the start.