Roblox compatibility
Studz's API grew out of Roblox's so you can bring scripts and habits over. Where Roblox's spelling is clumsy Studz has its own, and the Roblox one is deprecated: it still works, gives the same result and warns once. This page lists what Studz adds, how the deprecated spellings map to the Studz ones, and the quirks you may run into.
What Studz adds
Everything below is official and PascalCase. The utility tables chat, server, ui and Sound are lowercase-named tables of their own.
| Addition | The problem it solves |
|---|---|
part.PlayerTouched, PlayerTouchEnded (player, character, hit) | Roblox Touched fires for every part that touches, so scripts check hit.Parent:FindFirstChild("Humanoid") and GetPlayerFromCharacter. These fire only for players. |
part.Clicked (player) | Forgetting the ClickDetector is the classic "my click does nothing". Clicked makes it. |
Instance.Create(class, props) | Setting properties after parenting replicates every intermediate state. This sets properties first and parent last, and leaves no half-made object if a property is wrong. |
inst:GetChild(name) | FindFirstChild returns nil and the script dies two lines later with "attempt to index nil". GetChild fails at the lookup and lists the children. |
inst:TweenTo(...), tween:Await() | Three objects and a Completed:Wait() for the most common animation. |
inst:DestroyAfter(seconds) | Debris:AddItem(inst, seconds) without the service. |
Players:ForEachPlayer(fn), player:ForEachCharacter(fn) | PlayerAdded misses players who joined before the script ran. CharacterAdded misses the current character. |
remote:Listen(schema, fn) | A validated FromClient: bad types, NaN and extra arguments never reach your code. |
signal:Once(fn) | A one-shot On without the disconnect-in-callback dance. |
ChildAdded, ChildRemoved, DescendantAdded, Destroying, GetPropertyChangedSignal | See Events, signals and tasks. |
task.after, task.every, task.debounce | Timers and debouncing without hand-written loops and flags. |
player:Tell(text), player:SendChat(text, author) | Private chat lines. |
part:Spin(degreesPerSecond, axis) | Constant rotation. |
part:WeldTo(other), part:BreakWelds() | A weld takes an Instance.new, three assignments and a parent. WeldTo is one call, and it can follow a player's limb. |
limb.Transform, Scale, Visible, Color, character:ResetLimbs() | Posing a character in Roblox means Motor6D joints and animation assets. Here each limb can simply be posed from a script. See Limbs. |
character.Animator, animator:Play(clip, options) | Roblox plays animation assets through Humanoid:LoadAnimation. Here the clips the character model ships play from one call, on the limbs you choose, and tell you when they end. See Animations. |
workspace:GetPartBoundsInRadius(position, radius) | Objects near a point. |
chat, server, ui, Sound tables | One-line helpers. See Globals and services. |
math.lerp, table.clone, table.clear | Small helpers from the Luau library. |
What differs from Roblox
| Roblox | Studz |
|---|---|
| Luau | Lua 5.4. No +=, continue, types or string interpolation. |
HttpService:GetAsync and friends | Not available. They raise an error. |
| Data stores hold any value | Data stores hold numbers only. See Saving data. |
WeldConstraint, Weld | They exist. Weld.C0 and C1 mean the same as in Roblox. A held part is anchored while a weld holds it. See Welds. |
Motor6D, animation assets (LoadAnimation) | Not available. Pose a character's limbs from a script (Limbs) or play the clips the character model ships with character.Animator (Animations). Your own clips and an animation editor come later. |
Many services (MarketplaceService, TeleportService, Teams, ...) | Inert objects that warn once. |
Many properties (Archivable, Locked, Massless, CanTouch, Reflectance, ...) | Accepted and ignored, with one warning. |
Unknown class in Instance.new | A plain Part, with a warning. |
| Misspelled member | An error with a suggestion, instead of nil. |
| Instances exist before parenting | Instance.new("Part") is in the workspace immediately. |
Deprecated spellings
All of these still work. Each prints one warning that names the replacement, and each will be removed in a later release. Spellings are resolved before anything else, so part.pos = ... is exactly part.Position = ... and humanoid.WalkSpeed = ... is exactly humanoid.Speed = ....
The lowercase, camelCase and snake_case forms of a Roblox name (getChildren, find_first_child, walkSpeed) point at the Studz name too.
Roblox spellings
Names shared with Roblox that are not deprecated: Instance.new, Destroy, Clone, IsA, IsDescendantOf, Touched, TouchEnded, Changed, Died, Raycast, TweenService:Create, PlayerAdded and the value types (Vector3, CFrame, Color3, ...).
Finding things:
| Roblox | Studz |
|---|---|
inst:FindFirstChild(name) | inst:FindChild(name) |
FindFirstChildOfClass, FindFirstChildWhichIsA | inst:FindChildOfClass(class) (it matches subclasses too) |
FindFirstAncestor | inst:FindAncestor(name) |
FindFirstAncestorOfClass, FindFirstAncestorWhichIsA | inst:FindAncestorOfClass(class) |
inst:GetChildren() | inst:Children() |
inst:GetDescendants() | inst:Descendants() |
inst:GetFullName() | inst:FullName() |
inst:WaitForChild(name, timeout) | inst:AwaitChild(name, timeout) |
game:GetService(name) | game:Service(name) |
Players and characters:
| Roblox | Studz |
|---|---|
Players:GetPlayers() | Players:List() |
Players:GetPlayerByName(name) | Players:FindByName(name) |
Players:GetPlayerByUserId(id) | Players:FindById(id) |
Players:GetPlayerFromCharacter(character) | Players:FromCharacter(character) |
player:LoadCharacter(), humanoid:LoadCharacter() | :Respawn() |
humanoid:TakeDamage(amount) | humanoid:Damage(amount) |
humanoid.WalkSpeed | humanoid.Speed |
humanoid.JumpPower | humanoid.JumpForce |
Signals and timers:
| Roblox | Studz |
|---|---|
signal:Connect(fn) | signal:On(fn) |
connection:Disconnect() | connection:Off() |
connection.Connected | connection.Active |
RunService.Heartbeat | RunService.Frame |
RunService.RenderStepped | RunService.Draw |
button.MouseButton1Click, button.Activated | button.Clicked |
task.delay(seconds, fn) | task.after(seconds, fn) |
Debris:AddItem(inst, seconds) | inst:DestroyAfter(seconds) |
Remotes (RemoteEvent and RemoteFunction):
| Roblox | Studz |
|---|---|
remote:FireServer(...) | remote:ToServer(...) |
remote:FireClient(player, ...) | remote:ToPlayer(player, ...) |
remote:FireAllClients(...) | remote:ToAll(...) |
remote.OnServerEvent | remote.FromClient |
remote.OnClientEvent | remote.FromServer |
remote:InvokeServer(...) | remote:CallServer(...) |
remote.OnServerInvoke, OnClientInvoke | remote.OnServerCall, OnClientCall |
Properties:
| Roblox | Studz |
|---|---|
sound.PlaybackSpeed | sound.Speed |
sound.Looped | sound.Loop |
sound.RollOffMaxDistance | sound.MaxDistance |
part.AssemblyLinearVelocity, AssemblyAngularVelocity | part.LinearVelocity, part.AngularVelocity |
part.Velocity | part.SurfaceVelocity. In Studz this has always been the surface (conveyor) velocity, not a push, so the name now says so. |
Color3 on a part, decal or limb | Color |
TextColor3, BackgroundColor3, BorderColor3 | TextColor, BackgroundColor, BorderColor |
BorderSizePixel | BorderWidth |
TextStrokeColor3, TextStrokeTransparency | ShadowColor, ShadowTransparency |
Older Studz spellings
Shorthand Studz had before its API was cleaned up. Same rules: they work, and warn once.
| Old | Use |
|---|---|
The lowercase, camelCase or snake_case form of any method (getChildren, findFirstChild, applyImpulse, takeDamage, kick, kill, heal, ...) | The PascalCase Studz name |
find | FindChild |
Remove, remove | Destroy |
FindFirstPlayer | Players:FindByName |
OwnsGamePass, UserOwnsGamePass | HasGamePass |
OwnsBadge | HasBadge |
IsInGroup, GetRankInGroup, GetRoleInGroup | IsInClan, GetRankInClan, GetRoleInClan |
AddAccessory, WearClothing, wear | WearAccessory |
RemoveClothing, unwear | RemoveAccessory |
ReplaceClothing | ReplaceAccessory |
SetAccessories | SetOutfit |
on_touch(fn(hit, player)), onTouch | part.PlayerTouched |
on_touch_end, onTouchEnd | part.PlayerTouchEnded |
on_click(fn), onClick | part.Clicked (parts) or button.Clicked (GUI) |
on_chat | player.Chatted |
on_player_added, on_player_removing | Players.PlayerAdded, Players.PlayerRemoving |
send(text) | Tell |
tp(pos), teleport(pos) | Teleport (players) or assign Position |
tween(...), Tween, TweenPosition, TweenSize, TweenColor, TweenTransparency | TweenTo(goals, seconds, style, direction) |
FadeIn(seconds), fade_in | TweenTo({ Transparency = 0 }, seconds) |
FadeOut(seconds), fade_out | TweenTo({ Transparency = 1 }, seconds) |
world:spawn({ name=, pos=, ... }) | Instance.Create("Part", { Name=, Position=, ... }) |
world:all(name) | Descendants() |
world:tagged(tag) | CollectionService:GetTagged(tag) |
world:near(pos, radius) | GetPartBoundsInRadius(pos, radius) |
Chat, Broadcast, Announce, PrivateBroadcast, SendMessage, SendNotification (on Players or a player) | chat.broadcast, chat.announce, chat.whisper, player:Tell |
CreateText, CreateFrame, CreateButton (on GuiService) | Instance.new("TextLabel"), ("Frame"), ("TextButton") |
ClearAllText, Clear, clearAll | GuiService:ClearAll() |
handle:cancel() | Cancel |
signal:wait, signal:once | Wait, Once |
The lowercase, camelCase or snake_case form of any property (part.position, part.canCollide, sound.sound_id) | The PascalCase Studz name |
pos, Pos | Position |
rot, Rot | Orientation |
solid, Solid | CanCollide |
alpha, opacity | Transparency. These are the inverse (alpha = 1 - Transparency) and keep that meaning. |
Pitch | Speed (sounds) |
IsPlaying | Playing |
FontSize, FontFamily | TextSize, Font |
Image | Texture |
Click | Clicked |
Assigning a table (part.Position = { 0, 5, 0 }) | Assign a Vector3, UDim2 or Color3 |
Globals
Deprecated globals cannot be intercepted, so they give no warning. Switch anyway.
| Old | Use |
|---|---|
world, World, scene, Scene | workspace |
players, plrs | Players |
lighting | Lighting |
camera, mouse | workspace.CurrentCamera, player:GetMouse() |
spawn, after, every, defer | task.spawn, task.after, task.every, task.defer |
vec3, v3, rgb, hex, color | Vector3.new, Color3.fromRGB and friends |
tween, fade_in, fade_out, spin | TweenTo, part:Spin |
Known quirks
Current behaviours worth knowing. Several are planned to change.
- Containers are open ended.
workspace.Foo,model.FooandPlayers.Fooarenilwhen nothing is calledFoo. Only parts, lights, values, sounds, GUI elements and humanoids check their members. - Models and containers are identified by name. Two models with the same name are treated as one container, and
workspace.Fooscans the scene linearly. Instance.new("Part")is in the workspace immediately.Instance.Createand "parent last" avoid showing a half-built object.part.Parent = nildestroys.FindChildOfClassbehaves like Roblox'sFindFirstChildWhichIsA, and some ancestor and child name searches are case-insensitive.workspace.Playerandworkspace.Characterresolve to the local player's character. This is a Studz convenience. Do not rely on it in server scripts.- GUI ids are unique per process. Elements created by a server script and by a client's
LocalScriptlive in separate tables. ChangedandGetPropertyChangedSignalonly see assignments made by scripts, not changes made by the engine (physics, the character controller).workspace:GetPartBoundsInRadiusreturns objects by position only, with no size, and includes non-physical objects.- A limb's
Transparencyis all or nothing. Below 0.5 shows it and from 0.5 up hides it. A limb can be scaled, coloured and hidden, but not drawn half see-through yet. - Limb poses are drawn on top of the animation. Turn the built-in run and jump animation off with
animator.Locomotion = false. A part welded to a limb follows the poses a script gave, not the animation or the clips a script plays. - The Animator plays only the clips the character model ships (
RunandJump), at most four at once. Your own clips and an editor are planned. - Welds are made while the game runs. A weld a script makes is not saved with the place, and a weld only holds on the server. Use the Weld tool in Polycarbonate for welds that belong to the place.
Humanoid.HealthChangedexists on rigs (NPCs) only. A player'sHumanoidhas no such signal yet: pollHealth, or useDied.
Roadmap
Planned, in rough order:
- Identify models and containers by id instead of name, and check container lookups (
workspace.Foo) the way parts are checked. HealthChangedon players' humanoids,Changedfor engine-driven changes, andDescendantRemoving.- Body movers and more constraints:
LinearVelocity,AlignPosition,AlignOrientation,SpringConstraint, and hinges. (Welds exist. ALinearVelocitymover would clash with thepart.LinearVelocityproperty, so movers will get names of their own.) - Animation clips of your own and an animation editor, to replace hand-written limb poses. The
Animatoralready plays and blends the clips that ship with the character model. - Remove the deprecated spellings (the Roblox ones and the older Studz ones), after the warnings have been out for a few releases.
- Luau as the runtime (
+=,continue, types, string interpolation). Deliberately postponed.
