#3312 Roblox Voxel Builder

#3312 Roblox Voxel Builder

#3312 Provide a Roblox script to enable a player to build voxel-based structures

Below is a clean, ASCII-only implementation of a grid-snapped voxel builder that lets players click to place blocks in real time.

It uses one RemoteEvent, one server Script, and one client LocalScript.


1. One-time setup in Studio

LocationObjectNotes
ReplicatedStorageFolder - “VoxelAssets”Holds shared templates
 └─ VoxelAssetsPart - “Voxel”Size 4 × 4 × 4, Anchored = false, CanCollide = true, BrickColor as you like
ReplicatedStorageRemoteEvent - “PlaceVoxelEvent”Used to ask the server to place a block
ServerScriptServiceScript - “PlaceVoxelHandler”Paste the server code below
StarterPlayer ▸ StarterPlayerScriptsLocalScript - “VoxelBuilderClient”Paste the client code below

Grid size is 4 studs everywhere. Change SIZE in both scripts if you want a different voxel size.


2. Server-side script

ServerScriptService/PlaceVoxelHandler

-- PlaceVoxelHandler (server)
local ReplicatedStorage = game:GetService("ReplicatedStorage") local event = ReplicatedStorage:WaitForChild("PlaceVoxelEvent") local voxelTemplate = ReplicatedStorage:WaitForChild("VoxelAssets"):WaitForChild("Voxel") local SIZE = 4 -- grid size in studs local MAX_HEIGHT = 200 -- build height limit -- Snap a Vector3 to the grid local function snapToGrid(v) return Vector3.new( math.floor(v.X / SIZE + 0.5) * SIZE, math.floor(v.Y / SIZE + 0.5) * SIZE, math.floor(v.Z / SIZE + 0.5) * SIZE ) end -- Called when a client wants to place a voxel event.OnServerEvent:Connect(function(player, rawPos) if not rawPos or rawPos.Magnitude > 1e5 then return end if rawPos.Y > MAX_HEIGHT or rawPos.Y < -SIZE then return end local pos = snapToGrid(rawPos) -- Simple collision check: is there already a part at this CFrame? local region = Region3.new( pos - Vector3.new(SIZE/2, SIZE/2, SIZE/2), pos + Vector3.new(SIZE/2, SIZE/2, SIZE/2) ) local parts = workspace:FindPartsInRegion3(region, nil, 1) if #parts > 0 then return end -- space is occupied -- Place the voxel local voxel = voxelTemplate:Clone() voxel.CFrame = CFrame.new(pos) voxel.Parent = workspace end)

3. Client-side script

StarterPlayerScripts/VoxelBuilderClient

-- VoxelBuilderClient (local)
local Players = game:GetService("Players") local ReplicatedStorage = game:GetService("ReplicatedStorage") local UserInputService = game:GetService("UserInputService") local RunService = game:GetService("RunService") local player = Players.LocalPlayer local mouse = player:GetMouse() local event = ReplicatedStorage:WaitForChild("PlaceVoxelEvent") local voxelTemplate = ReplicatedStorage:WaitForChild("VoxelAssets"):WaitForChild("Voxel") local SIZE = 4 -- must match server -- Ghost preview block local preview = voxelTemplate:Clone() preview.Transparency = 0.5 preview.CanCollide = false preview.Anchored = true preview.Material = Enum.Material.ForceField preview.Parent = workspace -- Snap helper local function snap(v) return Vector3.new( math.floor(v.X / SIZE + 0.5) * SIZE, math.floor(v.Y / SIZE + 0.5) * SIZE, math.floor(v.Z / SIZE + 0.5) * SIZE ) end -- Update the ghost every frame RunService.RenderStepped:Connect(function() local ray = Ray.new(mouse.UnitRay.Origin, mouse.UnitRay.Direction * 512) local hit, pos = workspace:FindPartOnRay(ray, player.Character) if pos then preview.Position = snap(pos) end end) -- Left-click to place mouse.Button1Down:Connect(function() event:FireServer(preview.Position) end)

How it works

  1. Client ray-casts from the player’s camera; the hit point is snapped to the nearest 4-stud grid, and a semi-transparent preview cube is moved there every frame.

  2. When the player left-clicks, the client fires PlaceVoxelEvent with the snapped position.

  3. Server validates the position, checks that no part already occupies that grid cell, and then clones the voxel template into workspace.


Extensions you can add

  • Right-click to delete – send a different RemoteEvent that destroys the targeted voxel on the server.

  • Per-player block limits or permissions.

  • Different materials/colors – pass a color or ID in the RemoteEvent arguments.

  • Saving/loading – serialize all voxels’ positions to DataStore when a player leaves.

This skeleton keeps the client authoritative for aiming but the server authoritative for actual placement, preventing exploits while giving responsive building.


From <https://chatgpt.com/>  ChatGPT o3

Comments

Popular posts from this blog

#2892 Example of ChatGPT o1 Prompt

#3105 Federal and State Spending Idiocy