
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 werdenTypisches 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 nichtWie 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) -- 42Weg 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) -- 100Weg 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.
- Script erstellen
- im
Explorer-Panel + neben dem Objekt (z.B.ServerScriptService) betätigen - Object auswählen oder suchen →
Script(serverseitig) oderLocalScript(clientseitig)
- 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 = 0Bedingungen #
if punkte > 10 then
print("Gut gemacht!")
endSchleifen #
for i = 1, 5 do
print(i)
endFunktionen #
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)
-- ...
endKonstanten #
→ 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
endGenerisch (ü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)
endVergleich 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💡
continuegibt es in Luau seit 2022:continuespringt zum nächsten Durchlauf ohnebreak.
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 wegDas 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) -- 10GetChildren 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
endIf #
Grundstruktur #
if bedingung then
-- code
elseif andereBedingung then
-- code
else
-- code
endVergleichsoperatoren #
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 gleichlogische Operatoren #
if x > 0 and x < 10 then -- und
if x < 0 or x > 10 then -- oder
if not x then -- nichtTruthy / 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 falsyKurzform 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ürzerTernä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 = workspaceMath #
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)
endWorkspace #
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)
endDatentypen #
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ärtsPraktische 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 ExplodeFolgendes 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) --boomCraterParts 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
endCharacter 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)
endParts 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 sichtbarProperty 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
endObjekte 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 werdenVorteile 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
endTag 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 #
- Offizielle Doku: https://create.roblox.com/docs/de-de
- Übersicht der Klassen: https://create.roblox.com/docs/de-de/reference/engine/classes
- Roblox Education: education.roblox.com
- DevForum: devforum.roblox.com