How to make sure parts can't go past a certain boundary?

  1. I want to make it so that when you move your mouse across the plot it tracks that the object is on the plot which I did the following
if Mouse.Target.Name = plot then
--Rest is in the bottom of the post

I want to make it so the object stays completely on the plot.
2. The issue is that when you track the Mouse.Target it still makes it so a Object can go over and off the plot like this:

  1. I tried to make parts as barriers but it still goes through and I tried a Barrier.Touched but it didn’t work.

The Script:

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 Grid = 2

local PosX
local PosY
local PosZ
local Plot
local plotName
local Object

local GivenPlot = game.ReplicatedStorage.BuildEvents.GivenPlot
local PlaceObject = game.ReplicatedStorage.BuildEvents.PlaceObject
GivenPlot.OnClientEvent:Connect(function(plt)
	Plot = plt
	plotName = plt.Name
end)

local Rot = Plot.Orientation.Y

Plot.Touched:Connect(function(hit)
	local plr = game:GetService("Players"):GetPlayerFromCharacter(hit.Parent)
	if plr then
		OnPlot = true
	end
end)
Plot.TouchEnded:Connect(function(hit)
	local plr = game:GetService("Players"):GetPlayerFromCharacter(hit.Parent)
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
StartBarn = BuildSelection.StartBarnSelect.ImageButton
Tent = BuildSelection.TentSelect.ImageButton
HayBale = BuildSelection.HayBaleSelect.ImageButton
Log = BuildSelection.LogSelect.ImageButton
GreenScreen = BuildSelection.GreenScreenSelect.ImageButton
Flag = BuildSelection.FlagSelect.ImageButton
SmallDeck = BuildSelection.SmallDeck.ImageButton
DeckStairs = BuildSelection.DeckStairs.ImageButton
LargeDeck = BuildSelection.LargeDeck.ImageButton
Chair = BuildSelection.Chair.ImageButton
Bed = BuildSelection.Bed.ImageButton
TallBillboard = BuildSelection.TallBillboard.ImageButton
ShortBillboard = BuildSelection.ShortBillboard.ImageButton
Table = BuildSelection.Table.ImageButton
CampFire = BuildSelection.CampFire.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 Round(n, to)
	local to = to or 1
	if to == 0 then return n end
	return math.floor(n/to + 0.5) * to
end

local function SnapToGrid(vector3)
	return Vector3.new(
		Round(vector3.X, Grid),
		Round(vector3.Y, 0),
		Round(vector3.Z, Grid)
	)
end

local function CloneService(Obj)
	if CanStart == true and not CanPlace and not Placing then
		Object = game.ReplicatedStorage.BuildObjects:FindFirstChild(Obj):Clone()
		Object.Parent = game.Workspace
		Mouse.TargetFilter = Object
		
		Object.PrimaryPart.Orientation = Vector3.new(0, Object.PrimaryPart.Orientation.Y, 0)
		
		CanStart = false
		CanPlace = true
		Placing = true
	end
end

Soil.MouseButton1Click:Connect(function()
	CloneService("Soil")
	MoveObject = true
end)
StartBarn.MouseButton1Click:Connect(function()
	CloneService("StarterBarn")
	MoveObject = true
end)
Tent.MouseButton1Click:Connect(function()
	CloneService("Tent")
	MoveObject = true
end)
HayBale.MouseButton1Click:Connect(function()
	CloneService("Haybale")
	MoveObject = true
end)
Log.MouseButton1Click:Connect(function()
	CloneService("Log")
	MoveObject = true
end)
GreenScreen.MouseButton1Click:Connect(function()
	CloneService("GreenScreen")
	MoveObject = true
end)
Flag.MouseButton1Click:Connect(function()
	CloneService("Flag")
	MoveObject = true
end)
SmallDeck.MouseButton1Click:Connect(function()
	CloneService("SmallDeck")
	MoveObject = true
end)
DeckStairs.MouseButton1Click:Connect(function()
	CloneService("DeckStairs")
	MoveObject = true
end)
LargeDeck.MouseButton1Click:Connect(function()
	CloneService("LargeDeck")
	MoveObject = true
end)
Chair.MouseButton1Click:Connect(function()
	CloneService("Chair")
	MoveObject = true
end)
Bed.MouseButton1Click:Connect(function()
	CloneService("Bed")
	MoveObject = true
end)
TallBillboard.MouseButton1Click:Connect(function()
	CloneService("TallBillboard")
	MoveObject = true
end)
ShortBillboard.MouseButton1Click:Connect(function()
	CloneService("ShortBillboard")
	MoveObject = true
end)
Table.MouseButton1Click:Connect(function()
	CloneService("Table")
	MoveObject = true
end)
CampFire.MouseButton1Click:Connect(function()
	CloneService("Campfire")
	MoveObject = true
end)

local function Place()
	if Placing and CanPlace then
		PosX = Object.PrimaryPart.Position.X
		PosY = Object.PrimaryPart.Position.Y
		PosZ = Object.PrimaryPart.Position.Z
		PlaceObject:FireServer(Object.Name, PosX, PosY, PosZ, Rot, Plot)
		Placing = false
		CanPlace = false
		CanStart = true
		
		Object:Destroy()
	end
end

local function GetMousePlacementCFrame(Plot, Object)
	local objectOffset = Vector3.new(0, Object.PrimaryPart.Size.Y/2, 0)
	
	local mouseHit = Mouse.Hit
	
	local mouseHitRelative = Plot.CFrame:ToObjectSpace(mouseHit) + objectOffset
	
	local mouseHitRelativeSnapped = CFrame.new( SnapToGrid(mouseHitRelative.p))
	
	local mouseHitWorldSnapped = Plot.CFrame * mouseHitRelativeSnapped
	
	return mouseHitWorldSnapped
end

local function updateModelPlacement()
	if Plot and (not Plot:IsDescendantOf(Object)) and Mouse.Target.Name == plotName then
		Object:SetPrimaryPartCFrame(GetMousePlacementCFrame(Plot, Object)*CFrame.Angles(0,math.rad(Rot),0))
		Object.PrimaryPart.Orientation = Vector3.new(0, Rot, 0)
	end
end
--TAKE THIS PART OUT FOR RELEASE
BuildMode = true



game:GetService("UserInputService").InputBegan:Connect(function(input, GPE)
	if input.KeyCode == Enum.KeyCode.R and Placing == true and CanPlace == true then
		Rot = Rot + 45
		Object:SetPrimaryPartCFrame(Object.PrimaryPart.CFrame * CFrame.Angles(0, math.rad(Rot), 0))
	end
end)

RunService.RenderStepped:Connect(function()
	Mouse.TargetFilter = Object
	if Placing == true and CanPlace == true and not CanStart then
		Plot.Texture.Transparency = 0
		updateModelPlacement()
	end
end)

Mouse.Button1Down:Connect(Place)

Hello there!

The math function you’re looking for is math.clamp.
This takes in 3 arguments: X, Min, Max.

If X is less than Min then the returned value is Min, and if X is bigger than Max, then the returned value is Max. If X is in-between both Min and Max, the returned value is X.

In your SnapToGrid function, make sure to use the math.clamp function for both X and Z, doing this:

local function SnapToGrid( vector3 )
        return Vector3.new(
	        math.clamp( Round( vector3.X, Grid ), Grid.Position.X - ( Grid.Size.X / 2 ), Grid.Position.X + ( Grid.Size.X / 2 ) ),
	        Round(vector3.Y, 0),
	        math.clamp( Round( vector3.Z, Grid ), Grid.Position.Z - ( Grid.Size.Z / 2 ), Grid.Position.Z + ( Grid.Size.Z / 2 ) )
        )
end

If you found this answer useful, please accept it!

Have a nice day.

2 Likes

Is the Grid referring to 2 or is it the Plot position

1 Like

Grid in that case would’ve been the Grid Instance, sorry for being confusing.

1 Like

Wdym… So is grid like the grid for the movement or is it for the barrier because I thought and want to track the plot

1 Like