We use cookies on this site to enhance your user experience

Experimental Mode

Experimental Mode

10 min

There are many legacy places and models that were created when “Experimental Mode” was available, but the setting has since been disabled. This article outlines some common design practices that will not work in the current Roblox architecture, along with ways to fix them.

Creating Parts

Sometimes a player action means new parts should be inserted into the game world. In Experimental Mode, a single LocalScript could create a new part, tell the server about it, and the server would update the other clients.

local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

local player = Players.LocalPlayer
local playerGui = player:WaitForChild("PlayerGui")
local screenGui = playerGui:WaitForChild("ScreenGui")
local spawnCarButton = screenGui:WaitForChild("SpawnCarButton")

local carTemplate = ReplicatedStorage:WaitForChild("Car")

local function onClick()
	local car = carTemplate:Clone()
	local character = player.Character
	local humanoidRootPart = character:FindFirstChild("HumanoidRootPart")
	if humanoidRootPart then
		local spawnPosition = humanoidRootPart.CFrame + Vector3.new(0, 10, 0)
		car:SetPrimaryPartCFrame(spawnPosition)
		car.Parent = game.Workspace
	end
end

spawnCarButton.MouseButton1Click:Connect(onClick)

Again, this code worked fine in Experimental Mode, but now it will only spawn the car for the player locally — no other player be able to see or interact with it!

Moving Parts

Many player actions can cause parts to move. In most cases, such as a player’s character pushing or moving a part around, this automatically replicates to the server due to Articles/Network Ownership|network ownership. However, this doesn’t apply to anchored parts which are always owned by the server.

In the following example, buildings are moved around a grid map by clicking and dragging on them. In Experimental Mode, the player’s client could move a building and the server would automatically update to show all players the new placement.

local Players = game:GetService("Players")
local RunService = game:GetService("RunService")

local player = Players.LocalPlayer
local mouse = player:GetMouse()

local map = game.Workspace:WaitForChild("Map")
local buildings = game.Workspace:WaitForChild("Buildings")
local currentBuilding = nil

mouse.TargetFilter = map

local function onRenderStep()
	local cell = mouse.Target
	if cell and cell:IsDescendantOf(map) then
		local newPosition = cell.Position
		local base = currentBuilding.PrimaryPart
		local x, y, z, R00, R01, R02, R10, R11, R12, R20, R21, R22 = base.CFrame:components()
		local newCFrame = CFrame.new(newPosition.X, newPosition.Y, newPosition.Z, R00, R01, R02, R10, R11, R12, R20, R21, R22)
		currentBuilding:SetPrimaryPartCFrame(newCFrame)
	end
end

local function onMouseDown()
	local part = mouse.Target
	if part and part:IsDescendantOf(buildings) then
		currentBuilding = part.Parent
		mouse.TargetFilter = buildings
		RunService:BindToRenderStep("DragBuilding", Enum.RenderPriority.Input.Value, onRenderStep)
	end
end

local function onMouseUp()
	if currentBuilding then
		RunService:UnbindFromRenderStep("DragBuilding")
		mouse.TargetFilter = map
		currentBuilding = nil
	end
end

mouse.Button1Down:Connect(onMouseDown)
mouse.Button1Up:Connect(onMouseUp)

With Experimental Mode disabled, only the player who’s dragging the building will see it move.

Server Manipulating Player’s Interface

Sometimes the server needs to update a player’s interface, like showing a popup menu. In Experimental Mode, the server could access the contents of the player’s PlayerGui and make changes. Consider the following example which displays a message to any player joining the game:

local Players = game:GetService("Players")

local function onPlayerAdded(player)
	local playerGui = player:WaitForChild("PlayerGui")
	local welcomeScreen = playerGui:WaitForChild("WelcomeScreen")
	local welcomeMessage = welcomeScreen:WaitForChild("WelcomeMessage")
	
	welcomeMessage.Visible = true
	wait(5)
	welcomeMessage.Visible = false
end

Players.PlayerAdded:Connect(onPlayerAdded)

Without Experimental Mode, the player’s GUI is not visible to the server. Also, changing what’s shown in a player interface should generally be managed by the client itself.

Tools

Tool events fire on both the client and the server, so it’s important to remember the role of each when adapting an Experimental Mode game. Any LocalScript associated with a tool should be responsible for interface elements or local effects, along with player input. The server should be responsible for making changes to the game world, such as creating parts or changing game values.

The following example allows the tool user to create a sparkle effect on any other character that they click on. In Experimental Mode, this could be accomplished with just a LocalScript:

local Players = game:GetService("Players")

local tool = script.Parent

local player = Players.LocalPlayer
local mouse = player:GetMouse()

local function onActivated()
	local target = mouse.Target
	local character = target.Parent
	local humanoidRootPart = character:FindFirstChild("HumanoidRootPart")
	if humanoidRootPart and not humanoidRootPart:FindFirstChild("Sparkles") then
		local sparkles = Instance.new("Sparkles", humanoidRootPart)
	end
end

tool.Activated:Connect(onActivated)

Without Experimental Mode, this effect will not be replicated to the server (or other clients) because it’s created locally.

Tags:
  • coding