Scripting HelpersARCHIVE
A little piece of Roblox history. Preserved for everyone, one question at a time.Read about the archive →
✓ ANSWER ACCEPTED

How can i make a preview of what i am placing?

Hello people of the internet! I recently started to make a sandbox tycoon game, i want to know how to make a preview. (Also, if you could keep it usable with my currentbuilding setup.)

I've done a bit of research, and couldn't find a way to do it. Thanks in advance!

How my building system look right now

Replicated Storage(For those ones who want to mimic my current setup)

What my "Preview" looks like

SERVER SCRIPT

local place = game:GetService("ReplicatedStorage").Placement.Remotes.Place


game.ReplicatedStorage.Placement.Remotes.Place.OnServerEvent:Connect(function(plr, building, position)
	-- Are you kidding me, you guy not indenting properly is trigger my OCD
	local position2 = position
    	local building2 = building:Clone()
	building2.Parent = workspace
    	building2:MoveTo(position2)
    
     

end)

LOCAL SCRIPT

local player = game:GetService("Players").LocalPlayer -- Define the player
local mouse = player:GetMouse() -- Define the mouse
local UIS = game:GetService("UserInputService") -- UIS for activate of placement
local active = true -- Is placement active?
local activekeycode = Enum.KeyCode.E -- When the player presses E, they start placement.
local event = game:GetService("ReplicatedStorage").Placement.Remotes.Place
local changeevent = game:GetService("ReplicatedStorage").Placement.Remotes.ChangeBuilding
local currentbuilding = game:GetService("ReplicatedStorage").Placement.Buildings.Model

UIS.InputBegan:Connect(function(input, gp) --Change if it is active or not
	if input == activekeycode and gp and active == true then
		active = true
	else
		active = false
	end
end)
	
	
mouse.Button1Down:Connect(function()--Start the placement
	if active == true then -- Ensure it is active
		print("Activated")
		
		local building = currentbuilding
		local position = mouse.Hit.p -- Don't know if i should use "mouse.Hit.p" or "mouse.Hit"
		event:FireServer(building, position)
	end
end)

changeevent.OnClientEvent:Connect(function(building)-- Change building
	if not active == false and building ~= currentbuilding then -- Ensure it is not active
		currentbuilding = building
	end
end)

mouse.Move:Connect(function() -- Basically my preview 
	if active == true then
		local position = mouse.Hit.p
		local building = currentbuilding:Clone()
		building.Parent = workspace
		building:MoveTo(position)
		local parts = building:GetChildren()
		parts.Transparency = 0.4
	end
end)

1 answer

✓ Accepted answer

Before you copy and paste the code: create two RemoteEvents on Placement.Remotes, one named "MovePreview" and the other "CreatePreview". At least try to understand what I wrote. Its quite a big Code:

Server Script Code:

local place = game:GetService("ReplicatedStorage").Placement.Remotes.Place
local movepreview = game:GetService("ReplicatedStorage").Placement.Remotes.MovePreview
local createpreview = game:GetService("ReplicatedStorage").Placement.Remotes.CreatePreview

function newPlayer(player)--Create a Value inside the player that shows what is the currentpreview
	local currentpreview = Instance.new("ObjectValue")
	currentpreview.Parent = player
	currentpreview.Name = "CurrentPreview"
end
game.Players.PlayerAdded:Connect(newPlayer)

function onPreviewDeleted(obj,target)--Sometimes ObjectValues hold values of instances that got destroyed
	if obj == target.Value then
		target.Value = nil
	end
end
function findPartOnRayCheck(camerap,mousep,currentpreview)
	local ori = camerap
	local dir = mousep
	local ray = Ray.new(ori,(dir-ori).unit*999)
	local ignoreList = {currentpreview}--Ignores the CurrentPreview so I cant move over itself
	local part, rayposition = workspace:FindPartOnRayWithIgnoreList(ray,ignoreList)
	return part,rayposition
end
function movepreview(player,camerap,mousep)--Moves the Preview
	if camerap and mousep and player:findFirstChild("CurrentPreview") then
		local currentpreview = player.CurrentPreview.Value
		if currentpreview then
			local part,rayposition = findPartOnRayCheck(camerap,mousep,currentpreview)
			if part then
				if currentpreview.PrimaryPart then
					currentpreview:SetPrimaryPartCFrame(CFrame.new(rayposition))
				else
					currentpreview:MoveTo(rayposition)
				end
			end
		end
	end
end
game.ReplicatedStorage.Placement.Remotes.MovePreview.OnServerEvent:Connect(movepreview)

function createPreview(player,building,mousep)--Creates the preview
	if building and mousep and player:findFirstChild("CurrentPreview") and player.CurrentPreview.Value == nil then
		local currentpreview = player.CurrentPreview
		currentpreview.Value = building:Clone()
		workspace.DescendantRemoving:Connect(function(obj) onPreviewDeleted(obj,currentpreview) end)
		local parts = currentpreview.Value:GetDescendants()
		for i=1,#parts do
			if parts[i]:IsA("BasePart") then
				parts[i].CanCollide = false
				parts[i].BrickColor = BrickColor.new("Bright red")
				parts[i].Transparency = .5
			end
		end
		currentpreview.Value.Parent = workspace
		if currentpreview.Value.PrimaryPart then
			currentpreview.Value:SetPrimaryPartCFrame(CFrame.new(mousep))
		else
			currentpreview.Value:MoveTo(mousep)
		end
	end
end
game.ReplicatedStorage.Placement.Remotes.CreatePreview.OnServerEvent:Connect(createPreview)

game.ReplicatedStorage.Placement.Remotes.Place.OnServerEvent:Connect(function(plr,building,camerap,mousep)
	local previewpos = nil
	if plr:findFirstChild("CurrentPreview") and plr.CurrentPreview.Value ~= nil then--Destroy Preview, as it wont be used anymore
		local part,rayposition = findPartOnRayCheck(camerap,mousep,plr.CurrentPreview.Value)
		if part then previewpos = rayposition end
		plr.CurrentPreview.Value:Destroy()
	end
	if not previewpos then previewpos = mousep end
	if previewpos then
		--Why would you create a local position2 = position?
		local building2 = building:Clone()
		building2.Parent = workspace
		if building2.PrimaryPart and previewpos then
			building2:SetPrimaryPartCFrame(CFrame.new(previewpos))
		else
			building2:MoveTo(previewpos)
		end
		--return building2
	end
end)

Local Script Code:

local player = game:GetService("Players").LocalPlayer -- Define the player
local mouse = player:GetMouse() -- Define the mouse
local UIS = game:GetService("UserInputService") -- UIS for activate of placement
local active = true -- Is placement active?
local activekeycode = Enum.KeyCode.E -- When the player presses E, they start placement.
local event = game:GetService("ReplicatedStorage").Placement.Remotes.Place
local changeevent = game:GetService("ReplicatedStorage").Placement.Remotes.ChangeBuilding
local currentbuilding = game:GetService("ReplicatedStorage").Placement.Buildings.Model
local camera =  workspace.CurrentCamera

UIS.InputBegan:Connect(function(input, gp) -- I don't think this works right now, maybe i'll fix it soon.
    if input == activekeycode and gp and active == false then
        active = true
    elseif input == activekeycode and gp and active == true then
        active = false
    end
end)


mouse.Move:connect(function()game.ReplicatedStorage.Placement.Remotes.MovePreview:FireServer(camera.CFrame.Position,mouse.Hit.p) end)
mouse.Button1Down:connect(function()game.ReplicatedStorage.Placement.Remotes.CreatePreview:FireServer(currentbuilding,mouse.Hit.p) end)

mouse.Button1Up:Connect(function()--Start the placement
    if active == true then -- Ensure it is active
		print("Activated")
		local building = currentbuilding
		--local position = mouse.Hit.p -- Don't know if i should use "mouse.Hit.p" or "mouse.Hit"
		game.ReplicatedStorage.Placement.Remotes.Place:FireServer(building,camera.CFrame.Position,mouse.Hit.p)
		--local building = game.ReplicatedStorage.Placement.Remotes.Place:InvokeServer(building,mouse.Hit.p)
		end
	end)

changeevent.OnClientEvent:Connect(function(building)-- Change Building
    if not active == false and building ~= currentbuilding then -- Ensure it is not active
        currentbuilding = building
    end
end)

1 comment

0

It works, thanks! Few problems here and there, but overall really good.

This discussion is preserved as it was. New answers, comments, and votes are closed.