#3312 Roblox Voxel Builder
- Get link
- X
- Other Apps
#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
| Location | Object | Notes |
|---|---|---|
| ReplicatedStorage | Folder - “VoxelAssets” | Holds shared templates |
| └─ VoxelAssets | Part - “Voxel” | Size 4 × 4 × 4, Anchored = false, CanCollide = true, BrickColor as you like |
| ReplicatedStorage | RemoteEvent - “PlaceVoxelEvent” | Used to ask the server to place a block |
| ServerScriptService | Script - “PlaceVoxelHandler” | Paste the server code below |
| StarterPlayer ▸ StarterPlayerScripts | LocalScript - “VoxelBuilderClient” | Paste the client code below |
Grid size is 4 studs everywhere. Change
SIZEin 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
-
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.
-
When the player left-clicks, the client fires PlaceVoxelEvent with the snapped position.
-
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
- Get link
- X
- Other Apps
Comments
Post a Comment