You can write your topic however you want, but you need to answer these questions:
-
I would like to make a building system. Almost like plane crazy or build a boat for treasure.
-
I would like to be able to build on the blocks, not inside the blocks robloxapp-20210914-1853114.wmv - Google Drive
(Sorry about low-quality video)
-
I was unable to find a solution.
Here is my code (Client sided)
local LocalPlayer = game.Players.LocalPlayer
local selectionBox = game.ReplicatedStorage.Selection:Clone()
selectionBox.Parent = game.Workspace
local Mouse = LocalPlayer:GetMouse()
Mouse.TargetFilter = selectionBox
local function getBlockPosition(vector3)
local posX = math.ceil(vector3.X/2 - .5)*2
local posY = math.ceil(vector3.Y/2 - .5)*2 + 1
local posZ = math.ceil(vector3.Z/2 - .5)*2
return Vector3.new(posX, posY, posZ)
end
Mouse.Move:Connect(function()
local MousePosition = Mouse.Hit.p
local BlockPosition = getBlockPosition(MousePosition)
selectionBox.Position = BlockPosition
end)
Mouse.Button1Down:Connect(function()
local MousePosition = Mouse.Hit.p
game.ReplicatedStorage.Events.Place:FireServer("Blocks", "Block1x1", MousePosition)
local placeSound = game.ReplicatedStorage.Place:Clone()
placeSound.Parent = game.Workspace.CurrentCamera
placeSound.Playing = true
wait(placeSound.TimeLength)
placeSound:Destroy()
end)
And Placement Code (Server Sided)
local function getBlockPosition(vector3)
local posX = math.ceil(vector3.X/2 - .5)*2
local posY = math.ceil(vector3.Y/2 - .5)*2 + 1
local posZ = math.ceil(vector3.Z/2 - .5)*2
return Vector3.new(posX, posY, posZ)
end
game.ReplicatedStorage.Events.Place.OnServerEvent:Connect(function(plr, partCategory, partName, pos)
local plrFolder = game.Workspace.PlayerCreations:WaitForChild(plr.Name .. "Build")
local part = game.ReplicatedStorage.Building:WaitForChild(partCategory):WaitForChild(partName):Clone()
part.Parent = plrFolder
part.Position = getBlockPosition(pos)
end)
Don’t mind the security issue about this. I can handle that later.
All help is appreciated
2 Likes
I tried editing how it rounds to the nearest 2 studs, but nothing I tried worked.
1 Like
For the solution I am thinking of, it would require you to switch to a raycast system instead of mouse.hit. This is because mouse.hit doesn’t provide the surfaces normal. With the normal and the raycast position, you would add the position and the normal * half the block size and then do your rounding method. This would offset the block from the hit position.
1 Like
Okay, how can I do all of this? Can you provide me an example with some docs? I never tried using raycast.
Thanks for replying btw
Firstly, here is the docs for raycasting. To cast a ray from the camera position, we need the mouse’s position on the screen. Then the Camera(workspace.CurrentCamera) method ScreenPointToRay can be used.
--this is for the mouse.Move
local mousePosition = UserInputService:GetMouseLocation()
local unitRay = camera:ViewportPointToRay(mousePosition.X, mousePosition.Y)
This will return a unitRay with the position and direction to cast the raycast in.
-- only define raycastParams once at the top for speed
local raycastParams = RaycastParams.new()
raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
raycastParams.FilterDescendantsInstances = {player.Character, selectionBox} -- this might error with with no character, if so add to character added event.
--cast, back in the mouse.Move
-- 500 is just the distance, its really big you can decrease it if you need.
local raycastResult = workspace:Raycast(unitRay.Origin, unitRay.Direction * 500, raycastParams )
then if there is a raycastResult we can position the selection box
if raycastResult then
local BlockPosition = getBlockPosition(raycastResult.Position + raycastResult.Normal * 1) -- change the 1 to whatever half your block size is.
--position the selection block
end
I think because of this method you can get rid of the posY + 1, because the normal should account for it.
The mouse button down code would be done the same way, so I won’t do it. I hope this works and helps.
2 Likes
I received an error:
I will read the docs about this
oops its meant to be FilterDescendantsInstances, my bad.
1 Like
Thank you so much!!! It works! I will also use this for the place event later, may ask for help if needed. But I will mark as solution!!
Also mind editing your mistake so others can use it without errors?
1 Like
Uh oh. Ran into another error…
Code (Server sided)
local function getBlockPosition(vector3)
local posX = math.ceil(vector3.X/2 - .5)*2
local posY = math.ceil(vector3.Y/2 - .5)*2 + 1
local posZ = math.ceil(vector3.Z/2 - .5)*2
return Vector3.new(posX, posY, posZ)
end
local UserInputService = game:GetService("UserInputService")
game.ReplicatedStorage.Events.Place.OnServerEvent:Connect(function(plr, partCategory, partName, pos, camera)
local plrFolder = game.Workspace.PlayerCreations:WaitForChild(plr.Name .. "Build")
local mousePosition = UserInputService:GetMouseLocation()
local unitRay = camera:ViewportPointToRay(mousePosition.X, mousePosition.Y)
local part = game.ReplicatedStorage.Building:WaitForChild(partCategory):WaitForChild(partName):Clone()
part.Parent = plrFolder
-- only define raycastParams once at the top for speed
local raycastParams = RaycastParams.new()
raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
raycastParams.FilterDescendantsInstances = {plr.Character, part} -- this might error with with no character, if so add to character added event.
--cast, back in the mouse.Move
-- 500 is just the distance, its really big you can decrease it if you need.
local raycastResult = workspace:Raycast(unitRay.Origin, unitRay.Direction * 500, raycastParams )
if raycastResult then
local BlockPosition = getBlockPosition(raycastResult.Position + raycastResult.Normal * 1) -- change the 1 to whatever half your block size is.
part.Position = BlockPosition
end
end)
Client Side:
local LocalPlayer = game.Players.LocalPlayer
local selectionBox = game.ReplicatedStorage.Selection:Clone()
selectionBox.Parent = game.Workspace
LocalPlayer.CharacterAdded:Wait()
local UserInputService = game:GetService("UserInputService")
local camera = game.Workspace.CurrentCamera
local Mouse = LocalPlayer:GetMouse()
Mouse.TargetFilter = selectionBox
local function getBlockPosition(vector3)
local posX = math.ceil(vector3.X/2 - .5)*2
local posY = math.ceil(vector3.Y/2 - .5)*2
local posZ = math.ceil(vector3.Z/2 - .5)*2
return Vector3.new(posX, posY, posZ)
end
Mouse.Move:Connect(function()
--this is for the mouse.Move
local mousePosition = UserInputService:GetMouseLocation()
local unitRay = camera:ViewportPointToRay(mousePosition.X, mousePosition.Y)
-- only define raycastParams once at the top for speed
local raycastParams = RaycastParams.new()
raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
raycastParams.FilterDescendantsInstances = {LocalPlayer.Character, selectionBox} -- this might error with with no character, if so add to character added event.
--cast, back in the mouse.Move
-- 500 is just the distance, its really big you can decrease it if you need.
local raycastResult = workspace:Raycast(unitRay.Origin, unitRay.Direction * 500, raycastParams )
if raycastResult then
local BlockPosition = getBlockPosition(raycastResult.Position + raycastResult.Normal * 1) -- change the 1 to whatever half your block size is.
--position the selection block
selectionBox.Position = BlockPosition
end
end)
Mouse.Button1Down:Connect(function()
local MousePosition = Mouse.Hit.p
game.ReplicatedStorage.Events.Place:FireServer("Blocks", "Block1x1", MousePosition, camera)
local placeSound = game.ReplicatedStorage.Place:Clone()
placeSound.Parent = game.Workspace.CurrentCamera
placeSound.Playing = true
wait(placeSound.TimeLength)
placeSound:Destroy()
end)
The move event works fine though!
Its just the click event… I dont think there should be a problem considering I am passing all the info needed?
OHH wait I forgot about the UserInputService, I will try to fix it in a second
With the click event, send the position the client wants to put the block to the server and then sanity check it and stuff. The unitRay method won’t work on the server as you cant get the players camera or their mouse position on the server.
Already done! works well!!! Thank you so much for your help
1 Like
Hello, new problem! This is about if the blocks are different sizes. Here it is: How do I make a building grid place a block that is a different size?