Zum Hauptinhalt springen

Code Your World! Erschaffe deine eigene Experience mit Luau und Roblox Studio.

Inhaltsverzeichnis

Roblox Studio

Intro
#

Roblox Studio ist die Entwicklungsumgebung, mit der alle Spiele auf der Roblox-Plattform gebaut werden. Hier lernst du, wie du eigene Spiele erstellst - von der 3D-Welt bis zur Spielmechanik.

Die Programmiersprache ist Luau, eine Weiterentwicklung von Lua, die speziell für Roblox optimiert wurde. Im Vergleich zu anderen Sprachen ist Lua schlank und gut lesbar - ein guter Einstieg ins Programmieren.


Studio
#

Steuerung
#

Taste(n-Kombination) Funktion
W A S D vor, links, zurück, rechts
E Q
rechte Maustaste
Mausrad Zoom
CTRL+D duplizieren
F2 umbenennen
F5 ausführen
Shift+F5 beenden
CTRL+S speichern
F9 Developer Console

Explorer
#

Workspace
#

Beinhaltet den Großteil der Objekte (Part, Baseplate, SpawnLocation, …) einer Welt (Experience). Wird in Roblox Studio mit großem “W” geschrieben, in Scripts nutzt man aber workspace. Auch als game.Workspace verfügbar.

Properties
#

Erlaubt das Anzeigen und Anpassen der Eigenschaften (Attribute / Parameter) eines Objekts (aus Explorer).

Part
#

Part hinzufügen und manipulieren: Select, Move, Scale, Rotate, …

Script-Typen
#

Typ Wo Wofür
Script ServerScriptService Spiellogik welche alle Spieler betrifft
LocalScript StarterPlayerScripts
StarterGui
Spiellogik nur für den eigenen Spieler
ModuleScript Überall wiederverwendbarer Code

Wichtige Speicherorte
#

Ordner Script-Typ Läuft auf Sichtbar für
ServerScriptService Script Server alle Spieler
StarterPlayerScripts LocalScript Client nur dieser Spieler
StarterGui LocalScript Client nur dieser Spieler
StarterCharacterScripts LocalScript Client nur dieser Spieler
ReplicatedStorage ModuleScript Beide Server & Client
ServerStorage ModuleScript Server nur Server

Server vs. Client
#

Server (ServerScriptService)
-- ✅ kann Spielerdaten speichern (DataStore)
-- ✅ verwaltet Spiellogik (Punkte, Leben)
-- ✅ sicher – Spieler können es nicht manipulieren
-- ❌ kein Zugriff auf GUI des Spielers

Client (StarterPlayerScripts / StarterGui)
-- ✅ kann GUI steuern
-- ✅ reagiert auf Tasteneingaben (UserInputService)
-- ✅ flüssigere Animationen & Effekte
-- ❌ unsicher – kann von Spielern manipuliert werden

Typisches Beispiel

LocalScript in ServerScriptService
-- ❌ FALSCH: Läuft gar nicht!

Script in StarterGui
-- ❌ FALSCH: Läuft, aber kann nicht auf GUI zugreifen

Punkte auf Server verwalten
-- ✅ RICHTIG: ServerScriptService/Script:
local Players = game:GetService("Players")
Players.PlayerAdded:Connect(function(player)
    local leaderstats = Instance.new("Folder")
    leaderstats.Name = "leaderstats"
    leaderstats.Parent = player
end)

Tastendruck auf Client erkennen
-- ✅ RICHTIG: StarterPlayerScripts/LocalScript:
local UIS = game:GetService("UserInputService")
UIS.InputBegan:Connect(function(input)
    if input.KeyCode == Enum.KeyCode.E then
        print("E gedrückt!")
    end
end)

Kommunikation zwischen Server & Client
#

Da Server und Client getrennt sind, braucht man RemoteEvents:

-- In ReplicatedStorage: ein RemoteEvent namens "AddPoints"

-- CLIENT schickt Anfrage:
local event = game.ReplicatedStorage.AddPoints
event:FireServer(10)

-- SERVER empfängt:
event.OnServerEvent:Connect(function(player, points)
    print(player.Name .. " bekommt " .. points .. " Punkte")
end)

💡 Faustregel: Spiellogik & Datenspeicherung → Server. GUI & Input → Client. Geteilter Code → ReplicatedStorage.

Mehrere Scripts im gleichen Ordner
#

Scripts laufen parallel und unabhängig. Alle Scripts in einem Ordner starten gleichzeitig beim Spielstart – es gibt keine festgelegte Reihenfolge.

-- Script A
print("Ich bin Script A")  -- kann vor oder nach B erscheinen!
-- Script B
print("Ich bin Script B")  -- Reihenfolge nicht garantiert!

Teilen sie sich Variablen? ❌ nein – jedes Script hat seinen eigenen Speicher

-- Script A:
local punkte = 100  -- nur in Script A sichtbar
-- Script B:
print(punkte)  -- Fehler! punkte existiert hier nicht

Wie kommunizieren Scripts miteinander?
#

Weg 1: Über ein Objekt in der Welt MeinOrdner (Folder) und Wert (IntValue) zuvor unterhalb Workspace anlegen. Wert ist nicht persistent, fällt auf Ursprungswert zurück. Je nach Timing wird Ursprungswert verwenden. ScriptA und ScriptB unter ServerScriptService.

-- Script A schreibt:
workspace.MeinOrdner.Wert.Value = 42
-- Script B liest:
print(workspace.MeinOrdner.Wert.Value)  -- 42

Weg 2: ModuleScript (empfohlen) ModuleScript Daten in ReplicatedStorage. ScriptA und ScriptB unter ServerScriptService. Auch hier ist der Wert nicht persistent und das Timing entscheidend.

-- ModuleScript "Daten" in ReplicatedStorage:
local Daten = {}
Daten.punkte = 0
return Daten
-- ScriptA:
local Daten = require(game.ReplicatedStorage.Daten)
Daten.punkte = 100
-- ScriptB:
local Daten = require(game.ReplicatedStorage.Daten)
print(Daten.punkte)  -- 100

Weg 3: BindableEvents (für Server-zu-Server) ScriptA und ScriptB als Script unter ServerScriptService. MeinEvent als BindableEvent unter ServerScriptService.

-- ScriptA feuert ein Event:
local event = game.ServerScriptService.MeinEvent
event:Fire("Hallo Script B!")
-- ScriptB hört zu:
local event = game.ServerScriptService.MeinEvent
event.Event:Connect(function(message)
    print(message)  -- "Hallo Script B!"
end)

Luau
#

Roblox’s eigene Lua-Variante.

  1. Script erstellen
  • im Explorer-Panel + neben dem Objekt (z.B. ServerScriptService) betätigen
  • Object auswählen oder suchen → Script (serverseitig) oder LocalScript (clientseitig)
  1. Script öffnen
  • Doppelklick auf das Script → der Code-Editor öffnet sich

Grundlegender Syntax
#

Kommentar
#

-- Zeile

print("Hello") -- Inline

--[[
Block
]]

Variablen
#

local name = "Spieler"
local punkte = 0

Bedingungen
#

if punkte > 10 then
    print("Gut gemacht!")
end

Schleifen
#

for i = 1, 5 do
    print(i)
end

Funktionen
#

local function sagHallo(name)
    print("Hallo, " .. name)
end
sagHallo("Welt")

Wichtige Roblox-Objekte
#

-- Spieler finden
local players = game:GetService("Players")

-- Ein Part erstellen
local part = Instance.new("Part")
part.Parent = workspace
part.Position = Vector3.new(0, 10, 0)

-- Events nutzen
players.PlayerAdded:Connect(function(player)
    print(player.Name .. " ist beigetreten!")
end)

Namenskonventionen
#

Variablen & Funktionen
#

camelCase

local playerName = "Max"
local totalScore = 0

local function getUserData(playerId)
    -- ...
end

Konstanten
#

SCREAMING_SNAKE_CASE

local MAX_PLAYERS = 10
local SPAWN_POSITION = Vector3.new(0, 5, 0)
local GAME_VERSION = "1.0.0"

Klassen / Module / Services
#

PascalCase

local PlayerService = {}
local InventoryManager = {}

-- Roblox Services (bereits so benannt)
local RunService = game:GetService("RunService")
local TweenService = game:GetService("TweenService")

Roblox-Objekte (Instanzen)
#

PascalCase

local MyPart = Instance.new("Part")
local SpawnFolder = workspace:FindFirstChild("Spawns")

Private Felder in Modulen
#

_underscore Präfix

local MyModule = {}

local _privateData = {}  -- nur intern genutzt

function MyModule.publicFunction()
    -- ...
end

return MyModule

Übersicht
#

Typ Konvention Beispiel
Lokale Variable camelCase playerHealth
Funktion camelCase calculateDamage()
Konstante UPPER_SNAKE_CASE MAX_SPEED
Klasse / Modul PascalCase WeaponSystem
Roblox-Instanz PascalCase BasePart
Privates Feld _camelCase _internalState

For
#

Numerisch
#

-- for i = start, ende, schritt do
for i = 1, 10 do
    print(i)          -- 1, 2, 3 ... 10
end

for i = 1, 10, 2 do
    print(i)          -- 1, 3, 5, 7, 9
end

for i = 10, 1, -1 do
    print(i)          -- 10, 9, 8 ... 1
end

Generisch (über Tabellen)
#

-- ipairs: Array, mit Index, stoppt bei nil
for index, value in ipairs(meinArray) do
    print(index, value)
end

-- pairs: alle Einträge, auch gemischte Keys
for key, value in pairs(meineDictionary) do
    print(key, value)
end

-- Modern (Luau): ohne ipairs/pairs
for value in meinArray do
    print(value)
end

Vergleich ipairs vs pairs
#

local t = {
    "Apfel",          -- [1]
    "Banane",         -- [2]
    name = "Obst",    -- String-Key
    "Kirsche",        -- [3]
}

for i, v in ipairs(t) do
    print(i, v)   -- 1 Apfel, 2 Banane, 3 Kirsche
end               -- ⚠️ name="Obst" wird ignoriert!

for k, v in pairs(t) do
    print(k, v)   -- alles, auch name="Obst"
end               -- ⚠️ Reihenfolge nicht garantiert!

Schleife abbrechen
#

for i = 1, 100 do
    if i == 5 then
        break   -- Schleife sofort beenden
    end
    print(i)    -- 1, 2, 3, 4
end

💡 continue gibt es in Luau seit 2022: continue springt zum nächsten Durchlauf ohne break.

Lebensdauer von Variabeln
#

Nur innerhalb des Blocks — danach sind sie weg:

for i = 1, 5 do
    local x = i * 2  -- x existiert nur hier
    print(x)         -- funktioniert
end

print(x)  -- nil! x existiert nicht mehr
print(i)  -- nil! auch i ist weg

Das gilt für alle Blöcke in Lua — for, while, if, do...end. Sobald der Block endet, werden die lokalen Variablen freigegeben.

Soll der Wert erhalten bleiben, muss die Variable vorher deklarieren:

local result
for i = 1, 5 do
    result = i * 2  -- schreibt in die äußere Variable
end
print(result)  -- 10

GetChildren vs GetDescendant
#

-- nur Part aus gleicher Ebene
for _, child in script.Parent:GetChildren() do
	if child:IsA("Part") then
		print(child.Name)
	end
end

-- Part und Sub/PartSub aus tieferen Ebenen
for _, child in script.Parent:GetDescendants() do
	if child:IsA("Part") then
		print(child.Name)
	end
end

If
#

Grundstruktur
#

if bedingung then
    -- code
elseif andereBedingung then
    -- code
else
    -- code
end

Vergleichsoperatoren
#

der Syntax für ungleich ~= ist sehr ungewöhnlich.

if x == 10 then   -- gleich
if x ~= 10 then   -- ungleich (nicht != wie in anderen Sprachen!)
if x > 10 then    -- größer
if x < 10 then    -- kleiner
if x >= 10 then   -- größer gleich
if x <= 10 then   -- kleiner gleich

logische Operatoren
#

if x > 0 and x < 10 then    -- und
if x < 0 or x > 10 then     -- oder
if not x then                -- nicht

Truthy / Falsy
#

In Luau gilt nur false und nil als falsy – alles andere ist truthy, ebenfalls ungewöhnlich:

if 0 then print("wahr") end       -- ✅ 0 ist truthy! Sehr ungewöhnlich!
if "" then print("wahr") end      -- ✅ leerer String ist truthy! Sehr ungewöhnlich!
if nil then print("wahr") end     -- ❌ nil ist falsy
if false then print("wahr") end   -- ❌ false ist falsy

Kurzform für nil-Check
#

local part = workspace:FindFirstChild("MyPart")

-- Beide sind equivalent:
if part ~= nil then print("gefunden") end
if part then print("gefunden") end          -- kürzer

Ternärer Operator
#

local x = if y == 10 then "ja" else "nein"

Kommentar
#

-- Zeile

print("Hello") -- Inline

--[[
Block
]]

Klassen
#

Game
#

tbd

game.Workspace
#

siehe Workspace

Instance
#

Objekte (Instanzen) erstellen und manipulieren.

Part
#

local newPart = Instance.new("Part")
newPart.Name = "NewPart"
newPart.Parent = workspace

Math
#

random
#

while true do
	local r, g, b = math.random(0, 255), math.random(0, 255), math.random(0, 255)
	print(r, g, b)
	workspace.Part.Color = Color3.fromRGB(r, g, b)
	task.wait(0.1)	
end

Workspace
#

auch workspace, game.Workspace, game:GetService("Workspace") https://create.roblox.com/docs/de-de/reference/engine/classes/Workspace Je nach [[#Die wichtigsten Speicherorte|Kontext]] (Speicherorte / Ordner) können bestimmte Children erreicht werden.

for i, child in workspace:GetChildren() do
	print(i, child.Name, child.ClassName)
end

Datentypen
#

Vector3
#

Vector3.new(X, Y, Z)

Koordinatensystem in Roblox
#

        Y (oben/unten)
        └──────→ X (links/rechts)
     ↙ Z (vor/zurück)
Wert Richtung Positiv Negativ
X Links/Rechts Rechts Links
Y Oben/Unten Oben Unten
Z Vor/Zurück Rückwärts Vorwärts
Vector3.new(10, 0, 0)   -- 10 Studs nach rechts
Vector3.new(0, 10, 0)   -- 10 Studs nach oben
Vector3.new(0, 0, 10)   -- 10 Studs rückwärts
Vector3.new(0, 0, -10)  -- 10 Studs vorwärts

Praktische Beispiele
#

-- Part auf dem Boden, mittig:
part.Position = Vector3.new(0, 0, 0)

-- Part 10 Studs in der Luft:
part.Position = Vector3.new(0, 10, 0)

-- Part Größe (Breite, Höhe, Tiefe):
part.Size = Vector3.new(4, 1, 4)  -- flache Plattform

-- Spieler nach oben schleudern:
humanoidRootPart.Velocity = Vector3.new(0, 50, 0)

Enums
#

FromValue
#

workspace.Part.Shape = Enum.PartType:FromValue( math.random(0, 4) )  

Patterns
#

Code wiederholt ausführen
#

RunService.Heartbeat wird in jedem Frame ausgelöst, nachdem die Physik-Simulation abgeschlossen ist.

local RunService = game:GetService("RunService")
local lastExecutionTime = tick()

RunService.Heartbeat:Connect(function(deltaTime)
	if tick() - lastExecutionTime > 0.5 then -- eine halbe Sekunde Pause
		local r, g, b = math.random(0, 255), math.random(0, 255), math.random(0, 255)
		workspace.Part1.Color = Color3.fromRGB(r, g, b)
		lastExecutionTime = tick()
	end
end)

Explosion
#

Explosion auslösen sobald Part1 berührt wird:

local explosion = Instance.new("Explosion")

local function boom(otherPart)
	if otherPart.Name ~= "HumanoidRootPart" then return end	-- nur wenn ein Spieler berührt
	explosion.Position = otherPart.Position
	-- explosion.BlastRadius = 10
	-- explosion.BlastPressure = 100000
	explosion.ExplosionType = Enum.ExplosionType.Craters -- nur auf Terrain (Gras, Erde, etc.)
	explosion.Parent = workspace
end

workspace.Part1.Touched:Connect(boom)		

Explode als ModuleScript in ReplicatedStorage:

local Explode = {}

function Explode.boom(otherPart) 
	local explosion = Instance.new("Explosion")
	explosion.Position = otherPart.Position
	-- explosion.BlastRadius = 10
	-- explosion.BlastPressure = 100000
	explosion.Parent = workspace
end

function Explode.boomCrater(otherPart) 
	local explosion = Instance.new("Explosion")
	explosion.Position = otherPart.Position
	-- explosion.BlastRadius = 10
	-- explosion.BlastPressure = 100000
	explosion.ExplosionType = Enum.ExplosionType.Craters -- nur auf Terrain (Gras, Erde, etc.)
	explosion.Parent = workspace
end

return Explode

Folgendes Script an ein Part oder Ähnliches hängen, ggf. auch mit :GetChildren() oder :GetDescendants() in Verbindung mit Folder oder Tag arbeiten.

local Explode = require(game.ReplicatedStorage.Explode)

local part = script.Parent
part.touched:Connect(Explode.boom) --boomCrater

Parts mittels Datei (Table)
#

ModuleScript unterhalb von ServerStorage

-- ModuleScript ServerStorage/PartsTable
return {
	-- Position, Size, Shape, Type
	{Position = Vector3.new(0,5,0), Type = "Simple"},
	{Position = Vector3.new(10,5,0), Type = "Ice"},
	{Position = Vector3.new(10,5,10), Type = "Bomb"},
}

Script unterhalb von Workspace:

-- Script Workspace/CreatePartsFromTable
print("Start " .. script.Name)

local partsTable = require(game.ServerStorage.PartsTable)
local partsSimple = {}

local function createPartSimple(position, size, color, shape)
	local position = position or Vector3.new(-1, 1.5, 0)	-- Default position
	local size = size or Vector3.new(4, 1, 2)				-- Default size
	local color = color or Color3.fromRGB(163, 162, 165)	-- Default color
	local shape = shape or Enum.PartType.Block				-- Default shape
	
	local part = Instance.new("Part")
	part.Name = "PartSimple" .. #partsSimple + 1
	part.Position = position
	part.Size = size
	part.Color = color
	part.Shape = shape
	part.Anchored = true
	part.Parent = workspace
	table.insert(partsSimple, part)
end

for _, item in ipairs(partsTable) do
	if item.Type == "Simple" then
		createPartSimple(item.Position, item.Size, item.Color, item.Shape)
	elseif item.Type == "Ice" then
		print(item.Type)
	elseif item.Type == "Bomb" then
		print(item.Type)
	else
		print("Unknown Type " .. item.Type)
	end
end

print("Ende " .. script.Name)

Erweiterung Part als Bomb:

local partsBomb = {}

local function createPartBomb(position, size, color, shape)
	local position = position or Vector3.new(-1, 1.5, 0)	-- Default position
	local size = size or Vector3.new(4, 1, 2)				-- Default size
	local color = color or Color3.fromRGB(0, 0, 0)			-- Default color
	local shape = shape or Enum.PartType.Block				-- Default shape
	
	local part = Instance.new("Part")
	part.Name = "PartBomb" .. #partsBomb + 1
	part.Position = position
	part.Size = size
	part.Color = color
	part.Shape = shape
	part.Anchored = true
	part.Parent = workspace
	
	part.Touched:Connect(function(otherPart)
		local explosion = Instance.new("Explosion")
		if otherPart.Name ~= "HumanoidRootPart" then return end	-- nur wenn ein Spieler berührt
		explosion.Position = otherPart.Position
		-- explosion.BlastRadius = 10
		-- explosion.BlastPressure = 100000
		explosion.ExplosionType = Enum.ExplosionType.Craters -- nur auf Terrain (Gras, Erde, etc.)
		explosion.Parent = workspace
	end)
	
	table.insert(partsBomb, part)
end

-- createPartBomb(item.Position, item.Size, item.Color, item.Shape)

Erweiterung Part als Ice:

local partsIce = {}

local function createPartIce(position, size, color, shape)
	local position = position or Vector3.new(-1, 1.5, 0)	-- Default position
	local size = size or Vector3.new(4, 1, 2)				-- Default size
	local color = color or Color3.fromRGB(200, 230, 255)  	-- Default color
	local shape = shape or Enum.PartType.Block				-- Default shape

	local part = Instance.new("Part")
	part.Name = "PartIce" .. #partsIce + 1
	part.Position = position
	part.Size = size
	part.Color = color
	part.Shape = shape
	part.Material = Enum.Material.Ice
	part.Transparency = 0.25
	part.CustomPhysicalProperties = PhysicalProperties.new(1, 0, 0, 100, 1)
	part.Anchored = true
	part.Parent = workspace

	table.insert(partsIce, part)
end

-- createPartIce(item.Position, item.Size, item.Color, item.Shape)

Erweiterung Part als Laser:

local partsLaser = {}

local function createPartLaser(position, size, color, shape)
	local position = position or Vector3.new(-1, 1.5, 0)	-- Default position
	local size = size or Vector3.new(4, 1, 2)				-- Default size
	local color = color or Color3.fromRGB(255, 0, 0)		-- Default color
	local shape = shape or Enum.PartType.Block				-- Default shape

	local part = Instance.new("Part")
	part.Name = "PartLaser" .. #partsLaser + 1
	part.Position = position
	part.Size = size
	part.Color = color
	part.Shape = shape
	part.Material = Enum.Material.Neon
	part.Anchored = true
	part.Parent = workspace
	
	-- Laserstrahlen
	local rayLength = 10
	local function createLasers(part, rows, cols)
		local size = part.Size
		local beams = {}

		for row = 0, rows - 1 do
			for col = 0, cols - 1 do
				-- Position gleichmäßig über die Fläche verteilen
				local x = (col / (cols - 1) - 0.5) * size.X
				local z = (row / (rows - 1) - 0.5) * size.Z

				local att0 = Instance.new("Attachment")
				att0.Position = Vector3.new(x, 0, z)
				att0.Parent = part

				local att1 = Instance.new("Attachment")
				att1.Position = Vector3.new(x, rayLength, z)
				att1.Parent = part  -- bewegt sich mit dem Part mit

				local beam = Instance.new("Beam")
				beam.Attachment0 = att0
				beam.Attachment1 = att1
				beam.Color = ColorSequence.new(color)
				beam.Width0 = 0.05
				beam.Width1 = 0.05
				beam.LightEmission = 1
				beam.LightInfluence = 0
				beam.FaceCamera = true
				beam.Parent = part

				table.insert(beams, {att0 = att0, att1 = att1})
			end
		end

		return beams
	end
	createLasers(part, 4, 4)  -- 4x4 = 16 Strahlen
	
	part.Touched:Connect(function(otherPart)
		if otherPart.Name ~= "HumanoidRootPart" then return end	-- nur wenn ein Spieler berührt
		local character = otherPart.Parent
		local humanoid = character:FindFirstChild("Humanoid")
		if humanoid then
			humanoid.Health = 0  -- Spieler stirbt sofort
		end
	end)
	
	table.insert(partsLaser, part)
end

-- createPartLaser(item.Position, item.Size, item.Color, item.Shape)

Erweiterung Part als Trampolin:

local partsJumper = {}

local function createPartJumper(position, size, color, shape)
	local position = position or Vector3.new(-1, 1.5, 0)	-- Default position
	local size = size or Vector3.new(4, 1, 2)				-- Default size
	local color = color or Color3.fromRGB(0, 255, 0)		-- Default color
	local shape = shape or Enum.PartType.Block				-- Default shape

	local part = Instance.new("Part")
	part.Name = "PartJumper" .. #partsJumper + 1
	part.Position = position
	part.Size = size
	part.Color = color
	part.Shape = shape
	part.Anchored = true
	part.Parent = workspace
	
	local debounces = {}
	part.Touched:Connect(function(otherPart)
		if otherPart.Name ~= "HumanoidRootPart" then return end
		if debounces[otherPart] then return end
		debounces[otherPart] = true

		local bv = Instance.new("BodyVelocity")
		bv.Velocity = Vector3.new(0, 100, 0)
		bv.MaxForce = Vector3.new(0, math.huge, 0)
		bv.Parent = otherPart
		game:GetService("Debris"):AddItem(bv, 0.1)  -- nach 0.1s automatisch entfernen

		task.wait(1)
		debounces[otherPart] = nil
	end)
	
	table.insert(partsJumper, part)
end

-- createPartJumper(item.Position, item.Size, item.Color, item.Shape)

Erweiterung TrussPart als Leiter:

local partsLadder = {}

local function createPartLadder(position, size, color, style)
	local position = position or Vector3.new(0, 0, 0)		-- Default position
	local size = size or Vector3.new(2, 40, 2)				-- Default size = nur Höhe relevant, ein Vielfaches von 2, Maximum von 512
	local color = color or Color3.fromRGB(163, 162, 165)	-- Default color
	local style = style or Enum.Style.AlternatingSupports	-- Default style

	local part = Instance.new("TrussPart")
	part.Name = "PartLadder" .. #partsLadder + 1
	part.Position = position
	part.Size = size
	part.Color = color
	part.Style = style
	part.Anchored = true
	part.Parent = workspace
	table.insert(partsLadder, part)
end

-- createPartLadder(item.Position, item.Size, item.Color, item.Style)

Erweiterung Part als Förderband:

local partsBelt = {}

local function createPartBelt(position, size, color, velocity, rotation)
	local position = position or Vector3.new(-1, 1.5, 0)	-- Default position
	local size = size or Vector3.new(10, 2, 40)				-- Default size
	local color = color or Color3.fromRGB(4, 175, 236)		-- Default color
	local velocity = velocity or Vector3.new(0, 0, -20)		-- Default speed
	local rotation = rotation or 180						-- Default rotation

	local part = Instance.new("Part")
	part.Name = "PartBelt" .. #partsBelt + 1
	part.Position = position
	part.Size = size
	part.Color = color
	part.Material = Enum.Material.Metal
	part.AssemblyLinearVelocity = velocity
	part.Anchored = true
	part.Parent = workspace
	
	local texture = Instance.new("Texture")
	texture.Texture = "rbxassetid://6669861035"  -- Asset ID aus dem Marketplace
	texture.Rotation = 180
	texture.Face = Enum.NormalId.Top          
	texture.StudsPerTileU = 10
	texture.StudsPerTileV = 10
	texture.Parent = part
	
	table.insert(partsBelt, part)
end

-- reatePartBelt(item.Position, item.Size, item.Color, item.Velocity, item.Rotation)

Spieler kollidiert mit Part
#

-- ServerScriptService/Script
local COOLDOWN_SECONDS = 0.1

local players = game:GetService("Players")
local debounces = {}

for i, child in workspace:GetDescendants() do
	if child:IsA("Part") and child.Name:match("Coin") then
		child.Touched:Connect(function(hit)
			-- nur HumanoidRootPart reagiert (einmal pro Spieler, nicht jedes Körperteil)
			if hit.Name ~= "HumanoidRootPart" then return end
			local character = hit.Parent
			local player = players:GetPlayerFromCharacter(character)
			if debounces[player] then return end

			debounces[player] = true
			print(player.Name .. " hat " .. child.Name .." berührt!")
			task.wait(COOLDOWN_SECONDS)
			debounces[player] = false
		end)
	end
end

Character wird nach oben geschleudert
#

local players = game:GetService("Players"):GetChildren()
for _, player in players do
	player.Character:FindFirstChild("HumanoidRootPart").Velocity = Vector3.new(0, 500, 0)
end

Parts beim Spielstart generieren
#

ServerScriptService

-- ServerScriptService/Script
-- Läuft einmal beim Start, erstellt Parts für alle Spieler sichtbar
local RunService = game:GetService("RunService")

local coins = {}

for i = 1, 20 do
	local coin = Instance.new("Part")
	coin.Position = Vector3.new(math.random(-50, 50), 1, math.random(-50, 50))
	coin.Parent = workspace
	coin.Name = "Coin"..i
	coin.Shape = Enum.PartType.Cylinder
	coin.Size = Vector3.new(0.2, 1, 1)
	coin.BrickColor = BrickColor.new("Gold")
	coin.Transparency = 0.5
	coin.Anchored = true 
	coin:SetAttribute("Value", 10)
	table.insert(coins, coin)
end

RunService.Heartbeat:Connect(function(deltaTime)
	for _, coin in coins do
		coin.CFrame = coin.CFrame * CFrame.Angles(0, math.rad(90) * deltaTime, 0)
	end
end)

Parts zur Laufzeit spawnen (z.B. Projektile)
#

ServerScriptService

-- Reaktion auf Spieleraktion, spawnt Part dynamisch
remoteEvent.OnServerEvent:Connect(function(player)
    local projectile = Instance.new("Part")
    projectile.Parent = workspace
end)

Part nur für einen Spieler
#

StarterPlayerScripts

-- LocalScript – nur dieser Spieler sieht die Parts
local part = Instance.new("Part")
part.Parent = workspace  -- nur lokal sichtbar

Property via key, value
#

local Part = game.Selection:Get()[1]

local changes = {
    BrickColor = BrickColor.new("Bright red"),
    Transparency = 1,
    Material = Enum.Material.Neon,
    Anchored = true,
}

for property, value in pairs(changes) do
    Part[property] = value
end

Objekte klonen
#

Alternative zu Instance.new() oder Instance.fromExisting(). Vorlage einmal erstellen (z.B. in ServerStorage) und klonen.

local ServerStorage = game:GetService("ServerStorage")
local template = ServerStorage.MyPartTemplate  -- vorkonfiguriertes Part

local clone = template:Clone()
clone.Position = Vector3.new(0, 5, 0)
clone.Parent = workspace  -- sollte zuletzt gesetzt werden

Vorteile gegenüber Instance.new():

  • alle Properties werden übernommen
  • auch Childs (Skripte, Welds, Meshes…) werden kopiert
  • schneller

Für wiederkehrende gleichartige Objekte (Münzen, Gegner, Plattformen) ist Clone der Standard in Roblox. Für einmalige oder sehr unterschiedliche Objekte bleibt Instance.new() sinnvoll.

Tag
#

In Studio Tag (einmalig) erstellen und an beliebige Objekte anhängen.

local CollectionService = game:GetService("CollectionService")

local taggedItems = CollectionService:GetTagged("AnyTag")
for _, item in taggedItems do
	if item:IsA("Part") then    -- auf bestimmte Klasse filtern
		-- beliebige Aktion, z.B. item.touched:Connect(AnyFunction)
	end
end

Tag an ein Partbinden:

local CollectionService = game:GetService("CollectionService")

local part = workspace.Part
CollectionService:AddTag(part, "AnyTag") 

Tag entfernen:

local CollectionService = game:GetService("CollectionService")

local part = workspace.Part
CollectionService:RemoveTag(part, "AnyTag")

Events:

-- Wenn ein neues Objekt den Tag bekommt:
local CollectionService = game:GetService("CollectionService")
CollectionService:GetInstanceAddedSignal("AnyTag"):Connect(function(part)
    print(part.Name .. " hat jetzt Tag AnyTag!")
end)

-- Wenn ein Objekt den Tag verliert:
CollectionService:GetInstanceRemovedSignal("AnyTag"):Connect(function(part)
    print(part.Name .. " hat Tag AnyTag verloren!")
end)

Funktioniert nicht mit Tags die zur Laufzeit über Studio gesetzt werden, allerdings mit Tags die mittels Developer Console gesetzt werden:

local CollectionService = game:GetService("CollectionService")
CollectionService:AddTag(workspace.AnyPart, "AnyTag")

Begriffe
#

Client
#

TBD

Server
#

TBD

(Server) Cluster
#

TBD

(Server) Farm
#

TBD

Datacenter (Rechenzentrum)
#

Tbd

Lua
#

ist das portugiesische Wort für “Mond”. Die Programmiersprache wurde in Brasilien entwickelt und nach ihrem Vorgänger-Projekt “Sol” (Sonne) benannt, daher der Name “Lua” (Mond) als logische Fortführung dieser Namensgebung. Lua ist eine leichtgewichtige, interpretierte Skriptsprache, die 1993 in Brasilien entwickelt wurde. Sie zeichnet sich aus durch:

  • Einfachheit: kleiner und übersichtliche Syntax
  • Geschwindigkeit: einer der schnellsten Interpreter unter den Skriptsprachen
  • Einbettbarkeit: speziell dafür gemacht in andere Anwendungen (z. B. Spiele, Software) integriert zu werden, um diese erweiterbar/skriptfähig zu machen
  • Geringer Ressourcenverbrauch: läuft auch auf eingeschränkter Hardware Bekanntestes Einsatzgebiet: Spieleentwicklung (z. B. World of Warcraft-Addons, Roblox) sowie Konfigurations- und Erweiterungsskripte in vielen Anwendungen (z. B. Neovim, Wireshark).

Luau
#

ist ein Wortspiel: “Luau” ist eigentlich ein hawaiianisches Wort für ein traditionelles Festessen, der Name spielt damit auf “Lua” an. Technisch ist Luau eine von Roblox entwickelte Variante/Obermenge von Lua (basierend auf Lua 5.1), die zusätzliche Features bietet wie:

  • Optionale Typisierung (Gradual Typing)
  • Performance-Optimierungen
  • Zusätzliche Syntax-Erweiterungen (z. B. neue String-Methoden, Compound-Operatoren wie +=) Luau wird hauptsächlich für die Skripterstellung in der Roblox-Plattform verwendet.

Roblox
#

ein Kunstwort. Es setzt sich zusammen aus “Robot” und “Blocks”. Der Name spielt auf die robotischen, blockartigen Avatare und die Bauklötzchen-Ästhetik der Plattform an, die stark an LEGO-Steine erinnert. Roblox wurde 2004 von David Baszucki und Erik Cassel gegründet und ist heute eine Online-Plattform, auf der Nutzer eigene Spiele erstellen und mit anderen spielen können.

Robux
#

ein Kunstwort aus “Robo(t)” ubd “Bucks” (umgangssprachlich für Geld/Dollar). Es handelt sich um die virtuelle Währung innerhalb von Roblox, mit der Nutzer im Spiel Gegenstände, Avatar-Kleidung, Zugang zu bestimmten Spielen oder Spielfunktionen kaufen können. Robux kann mit echtem Geld erworben werden und Entwickler können durch den Verkauf von Inhalten in ihren Spielen ebenfalls Robux verdienen, die sie dann in echtes Geld umwandeln können (Developer Exchange/DevEx).

Roblox Studio
#

ist die kostenlose Entwicklungsumgebung (IDE) von Roblox, mit der Nutzer eigene Spiele und Erlebnisse für die Plattform erstellen können. Wichtigste Merkmale:

  • 3D-Editor: Bauen von Welten, Objekten und Umgebungen per Drag & Drop
  • Skripting: Programmierung der Spiellogik mit Luau (der Roblox-eigenen Lua-Variante)
  • Vorgefertigte Assets: Zugriff auf Modelle, Texturen, Sounds aus dem Roblox-Katalog/Marketplace
  • Physik-Engine: integrierte Physiksimulation für realistisches Verhalten von Objekten
  • Test-Modus: Spiele direkt in der Studio-Umgebung testen, bevor sie veröffentlicht werden
  • Plattformübergreifende Veröffentlichung: erstellte Spiele laufen auf PC, Mobile, Konsole und VR Roblox Studio ist kostenlos nutzbar und richtet sich sowohl an Einsteiger (z. B. Kinder/Jugendliche, die erste Spiele bauen) als auch an professionelle Entwickler, die komplexe, monetarisierte Erlebnisse erstellen.

Nützliche Ressourcen
#