How can I make an effective tower placement system for a tower defense game?

  1. What do you want to achieve?
    I want to make a good tower placement system for a tower defense game i’m making.

  2. What is the issue?
    I’m not able to find a good one that works.

  3. What solutions have you tried so far?
    I’ve looked through developer hub and haven’t found anything that I fully understand as I’m not that much of an experienced scripter. I’ve also tried TheDevKing’s placement system but that had multiple bugs with it.

1 Like

you can use Mouse.Hit and Mouse.TargetFilter to get a placing point and offset it with a cframe so it doesnt stick in the ground, heres a idea of it

local offset = CFrame.new(0,whatever number you want,0)

while Placing == true do
if mouse.Target ~= nil then
tower.HumanoidRootPart.CFrame = mouse.Hit + offset
end

then you cant just do a click detection and then fire a thing to place it in the position and what not

When I actually place it would I just find the CFrame of the preview of where it’s gonna be, clone the actual tower from replicated storage, and set it’s CFrame to that?

Pretty much, but you need to send the necessary information to the server using a RemoteEvent, so the server can do the actual work and have it replicate to all players.

You should put the Tower in ReplicatedStorage so the local script can clone the model for the placement view before placing it.

Basically the client is going to view the model before actually placing it which means you’ll need to use a local script for that,
You can use UserInputService for the click detection.

Use RunService RenderStepped to make the Tower follow the Mouse CFrame. (RenderStepped runs every frame of the client.)

Mouse.TargetFilter = Character
game:GetService("RunService").RenderStepped:Connect(function()
   if Mouse.Target ~= nil then
      Tower.PrimaryPart.CFrame = CFrame.new(Mouse.Hit.Position) * CFrame.new(0, Y, 0) -- With a offset.
   end
end)

When you’re going to place it, send the CFrame/Mouse Position using a remote event.

After the client sends the information to the server using a remote event, Clone the Tower
to a Folder where the Tower(s) are going to be placed (Better off making a folder for a specific player, I also recommend using the PrimaryPart property if the Tower is a Model).

Finally, Use the CFrame from the parameter to position the Tower with a offset.
Tower.PrimaryPart.CFrame = CFrame * CFrame.new(0, up/down, 0)

The server can’t see/access instances that are created by the client/a local script.
Let me know if I forgot something!

Wouldn’t it have to show the tower by using a button then you would place it?

Yes, Which is why I said to put the Tower in ReplicatedStorage so the local script can access it.

Anything to do with placement systems is pretty ambitious let alone for a beginner. Just know that even if you find the solution that you may still not understand how or why your system works. It’s like starting out scripting by making an FPS, it does not end well. I suggest maybe a smaller project so you don’t overwhelm yourself with a project that is at a high difficulty level to produce, however it’s your choice. Best of luck with your project and I hope it turns out well :]

I’m just trying to mess around with what I know and getting help from others hopefully making it into a full game.

I’m not done yet but is there something wrong with this code?

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local PlaceTower = ReplicatedStorage:WaitForChild("PlaceTower")
local Tower = ReplicatedStorage.Towers:WaitForChild("Tower")
local Towers = ReplicatedStorage:WaitForChild("Towers")

local UIS = game:GetService("UserInputService")

local player = game.Players.LocalPlayer
local Character = player.Character or player.Character:Wait()
local HumanoidRootPart = Character:WaitForChild("HumanoidRootPart")

local Mouse = player:GetMouse()
local placingTower = false
local TowerFrame = script.Parent.TowerFrame

Mouse.TargetFilter = Character
game:GetService("RunService").RenderStepped:Connect(function()
	if Mouse.Target ~= nil then
		Tower.HumanoidRootPart.CFrame = CFrame.new(Mouse.Hit.Position) * CFrame.new(0, 8.836, 0) -- With a offset.
	end
end)

for _, towerButton in pairs(TowerFrame:GetChildren()) do
	if towerButton:IsA("TextButton") then
		towerButton.MouseButton1Up:Connect(function()
			
			TowerFrame.Visible = false
			
			local goodToPlace = false
			local placedTower
			
			if placingTower == false then
				placingTower = true
				
				local clientTower = Towers:FindFirstChild(towerButton.Name):Clone()
				clientTower.Hitbox.BrickColor = BrickColor.new("Forest green")
				clientTower.Parent = game.Workspace.Towers
				
				local startingCFrame = CFrame.new
				
				
			end
		end)
	end
end
1 Like