What will you build next?
You finished a game. Pick one experiment that makes you want to open Studio again. These are optional and earn no required XP. Save your launch file, then open a new Baseplate for each experiment. Save it with a different name. Keep the default floor and spawn so you can test safely.
For every recipe below: insert a Part in Workspace, rename it, set Anchored on, and enter Size and Position in X, Y, Z order. Insert a normal Script inside the named part, delete its placeholder, and use the complete example. Stop Play before editing.
A spinner you can dodge
Build a Part named Spinner, Size 20, 1, 1, Position 0, 3, 15. Turn CanCollide off. Give it a bright color. Insert SpinnerController inside it.
local spinner = script.Parent
local RunService = game:GetService("RunService")
local degreesPerSecond = 60
local pivot = spinner.CFrame
local angle = 0
RunService.Heartbeat:Connect(function(deltaTime)
angle = angle + math.rad(degreesPerSecond) * deltaTime
spinner.CFrame = pivot * CFrame.Angles(0, angle, 0)
for _, part in workspace:GetPartsInPart(spinner) do
local humanoid = part.Parent:FindFirstChildOfClass("Humanoid")
if humanoid then humanoid.Health = 0 end
end
end)
Press Play and approach the arm. It turns around its own center. Touch its sweep and you should respawn. Test both walking into it and standing still in its path. The script checks overlaps as well as rotating; moving a part with CFrame alone does not guarantee a touch event.
Stop and change degreesPerSecond from 60 to 30. Predict the result and test again. Keep a clear waiting area beyond the arm’s ten-stud reach.
Something different? Confirm the Script is inside Spinner and CanCollide is off. If it circles around another object, compare the pivot and spinner.CFrame lines. How Roblox detects collisions.
A cannon that makes its own fireballs
Build Muzzle, Size 2, 2, 2, Position -15, 6, 15; then Target, Size 2, 2, 2, Position 15, 6, 15. Turn CanCollide off on both. Insert CannonController inside Muzzle.
local muzzle = script.Parent
local target = workspace:WaitForChild("Target")
local Debris = game:GetService("Debris")
local launchDelay = 2
local flightTime = 0.8
local function launchFireball()
local ball = Instance.new("Part")
ball.Name = "Fireball"
ball.Shape = Enum.PartType.Ball
ball.Size = Vector3.new(3, 3, 3)
ball.Material = Enum.Material.Neon
ball.Color = Color3.fromRGB(255, 100, 0)
ball.CanCollide = false
ball.Position = muzzle.Position
ball.Parent = workspace
ball:SetNetworkOwner(nil)
local velocity = (target.Position - muzzle.Position) / flightTime
ball.AssemblyLinearVelocity = velocity + Vector3.new(0, workspace.Gravity * flightTime / 2, 0)
ball.Touched:Connect(function(part)
if part == muzzle then return end
local humanoid = part.Parent:FindFirstChildOfClass("Humanoid")
if humanoid then humanoid.Health = 0 end
ball:Destroy()
end)
Debris:AddItem(ball, 3)
end
while true do
launchFireball()
task.wait(launchDelay)
end
Press Play and watch several shots. Each ball follows an arc toward Target and disappears after hitting something or after three seconds. The function creates one ball; the loop calls the function repeatedly. Gravity bends the path, so the launch velocity includes an upward correction.
Walk across the firing lane and test a hit. Stop and increase launchDelay from 2 to 3; the extra pause should make crossing easier. Watch Workspace during Play: old balls should disappear rather than accumulate.
Something different? Target must be directly inside Workspace and spelled exactly. Keep its position different from Muzzle. A fireball is unanchored, even though Muzzle and Target are anchored.
A secret-code door
Create these anchored Parts in Workspace. Give the buttons their named colors, then insert one ClickDetector inside each button. Set each ClickDetector’s MaxActivationDistance to 20.
| Part | Size | Position |
|---|---|---|
| Door | 12, 10, 1 | 0, 5, 20 |
| Green | 3, 1, 3 | -5, 1, 10 |
| Red | 3, 1, 3 | 0, 1, 10 |
| Blue | 3, 1, 3 | 5, 1, 10 |
Insert CodeLockController inside Door.
local door = script.Parent
local correctOrder = {"Green", "Red", "Blue"}
local nextPress = 1
local function press(color)
if nextPress > #correctOrder then return end
if color == correctOrder[nextPress] then
nextPress = nextPress + 1
door.Color = Color3.fromRGB(255, 220, 80)
if nextPress > #correctOrder then
door.CanCollide = false
door.Transparency = 0.75
door.Color = Color3.fromRGB(80, 255, 120)
end
else
nextPress = 1
door.Color = Color3.fromRGB(255, 70, 70)
end
end
for _, color in {"Green", "Red", "Blue"} do
local button = workspace:WaitForChild(color)
button:WaitForChild("ClickDetector").MouseClick:Connect(function()
press(color)
end)
end
Press Play. Walk close to the buttons and click Blue first: the door turns red and stays solid. Now click Green, Red, Blue: it turns green and opens. Stop and restart Play to reset the puzzle.
The table correctOrder stores the secret; nextPress remembers which answer comes next. Change the order, then test a wrong sequence and the correct one. Add a visible clue using the sign method from Mission 8—for example, “Green → Red → Blue.” A puzzle should reward noticing the clue.
Something different? The three buttons must be direct children of Workspace, with a ClickDetector nested inside each. Click them in Play mode from nearby. This sandbox tests the mechanism; it has no room walls. Build an enclosure if you turn it into a game obstacle.
Understand your supplied checkpoints
In your course project, each green pad is a SpawnLocation. Its TeamColor matches one Team under Teams. AllowTeamChangeOnTouch switches you to that team when you touch the pad; Roblox then respawns you there. Only the first Team has AutoAssignable on, so new runs begin at the lobby.
The pads look green, but their functional TeamColors differ. BrickColor/Color controls appearance; TeamColor connects respawn behavior. Inspect the matching values in a copy of your project, then test touching a later pad and falling. Keep the working launch copy safe.