Try Live
Add Docs
Rankings
Pricing
Docs
Install
Theme
Install
Docs
Pricing
More...
More...
Try Live
Rankings
Enterprise
Create API Key
Add Docs
Polytoria
https://github.com/polytoria/docs
Admin
Polytoria is a multiplayer game development platform that simplifies game creation with an
...
Tokens:
56,514
Snippets:
541
Trust Score:
5.3
Update:
2 months ago
Context
Skills
Chat
Benchmark
79
Suggestions
Latest
Show doc for...
Code
Info
Show Results
Context Summary (auto-generated)
Raw
Copy
Link
# Polytoria Scripting Documentation Polytoria is a multiplayer game development platform that simplifies creating multiplayer games with an easy-to-learn Lua scripting API. The platform provides a comprehensive object-oriented framework where all objects inherit from a base `Instance` class, enabling developers to create, manipulate, and destroy game objects programmatically. Polytoria uses a hierarchical tree structure with `game` as the root object, containing services like `Environment` (world objects), `Players` (connected players), `Lighting`, and `ScriptService`. The scripting API offers static classes for common operations (Http, Datastore, Input, Tween, Achievements), data types for 3D math and colors (Vector3, Vector2, Color), and networking capabilities through NetworkEvent and NetMessage for client-server communication. Scripts can be server-side (Script), client-side (LocalScript), or reusable modules (ModuleScript), with clear separation between server-exclusive and client-exclusive functionality for security and performance. ## Core API Reference ### Instance - Base Object Class Instance is the foundation class from which all Polytoria objects inherit. It provides core functionality for creating, finding, cloning, and destroying objects, as well as events for detecting interactions like touches and clicks. ```lua -- Creating new instances local newPart = Instance.New("Part") local partInEnvironment = Instance.New("Part", game["Environment"]) -- Finding and accessing children local myPart = game["Environment"]["myPart"] local foundPart = game["Environment"]:FindChild("myPart") local children = game["Environment"]:GetChildren() local partsByClass = game["Environment"]:GetChildrenOfClass("Part") -- Instance events for interaction game["Environment"]["Part"].Touched:Connect(function(otherPart) if otherPart:IsA("Player") then print(otherPart.Name .. " touched the part!") end end) game["Environment"]["Part"].Clicked:Connect(function(player) print(player.Name .. " clicked on this part!") end) -- Mouse hover events part.MouseEnter:Connect(function() part.Color = Color.New(1, 0, 0) -- Red on hover end) part.MouseExit:Connect(function() part.Color = Color.New(0, 1, 0) -- Green on exit end) -- Child management events game["Environment"].ChildAdded:Connect(function(child) print(child.Name .. " was added") end) -- Using Shared table for metadata local players = game["Players"]:GetChildren() local lucky = players[math.random(1, #players)] lucky.Shared.IsZombie = true -- Check metadata in another script if player.Shared.IsZombie then print("This player is a zombie!") end ``` ### Game - Root Object Game is the root object in the Polytoria instance tree from which everything descends. It provides access to game properties and the render loop event. ```lua -- Accessing game properties print("Game ID: " .. game.GameID) -- Returns 0 when testing locally print("Total instances: " .. game.InstanceCount) print("Players connected: " .. game.PlayersConnected) -- Frame-by-frame updates (use in LocalScripts for best results) game.Rendered:Connect(function(deltaTime) -- deltaTime is time since last frame in seconds local speed = 10 * deltaTime part.Position = part.Position + Vector3.New(speed, 0, 0) end) -- Check if running locally vs on live server if game.GameID == 0 then print("Running in local test mode") else print("Running on live server") end ``` ### Players and Player - Player Management Players is the service containing all connected Player instances. Player represents an individual player with their character, health, movement, and appearance properties. ```lua -- Player join/leave events game["Players"].PlayerAdded:Connect(function(player) print(player.Name .. " joined! UserID: " .. player.UserID) -- Set player properties player.WalkSpeed = 20 player.JumpPower = 50 player.MaxHealth = 150 player.Health = 150 -- Customize appearance colors player.HeadColor = Color.New(1, 0.8, 0.6) player.TorsoColor = Color.New(0, 0.5, 1) end) game["Players"].PlayerRemoved:Connect(function(player) print(player.Name .. " left the server") end) -- Get local player (client-side only) local localPlayer = game["Players"].LocalPlayer print("You are: " .. localPlayer.Name) -- Player events player.Chatted:Connect(function(message, event) print(player.Name .. " said: " .. message) -- Cancel the message to hide from others -- event.Canceled = true end) player.Died:Connect(function() print(player.Name .. " died!") end) player.Respawned:Connect(function() print(player.Name .. " respawned!") end) -- Player methods player:Kick("You've been kicked from the server.") player:Respawn() player:LoadAppearance(2) -- Load avatar of user ID 2 player:ClearAppearance() -- Set to gray avatar player:ResetAppearance() -- Restore original avatar -- Check item ownership (async with callback) player:OwnsItem(24122, function(error, owns) if not error and owns then print("Player owns Polytoria Cap!") player.WalkSpeed = 25 -- Bonus speed for owners end end) -- Iterate all players for i, player in ipairs(game["Players"]:GetPlayers()) do print(player.Name .. " is in the server!") end -- Get player by name or ID local specificPlayer = game["Players"]:GetPlayer("username") local playerByID = game["Players"]:GetPlayerByID(12345) -- Disable player collisions game["Players"].PlayerCollisionEnabled = false ``` ### Part - Physical World Objects Parts are the fundamental physical objects in the game world. They can be anchored (static) or unanchored (physics-enabled), and support forces, collisions, and visual properties. ```lua -- Create and configure a part local part = Instance.New("Part", game["Environment"]) part.Name = "MyPart" part.Position = Vector3.New(0, 10, 0) part.Size = Vector3.New(4, 2, 4) part.Color = Color.New(1, 0, 0) -- Red part.Anchored = true part.CanCollide = true part.CastShadows = true -- Part shapes and materials part.Shape = PartShape.Wedge -- Block, Sphere, Cylinder, Wedge part.Material = PartMaterial.Concrete -- Wood, Metal, Grass, etc. -- Physics properties part.Anchored = false part.UseGravity = true part.Mass = 10 -- kilograms part.Friction = 0.5 part.Bounciness = 0.3 part.Drag = 0.1 part.AngularDrag = 0.05 -- Apply forces (for unanchored parts) part:AddForce(Vector3.New(0, 1000, 0), ForceMode.Impulse) part:AddTorque(Vector3.New(0, 100, 0), ForceMode.Force) part:AddForceAtPosition(Vector3.New(100, 0, 0), Vector3.New(0, 5, 0), ForceMode.Impulse) -- Move with physics consideration part:MovePosition(Vector3.New(50, 0, 0)) part:MoveRotation(Vector3.New(0, 180, 0)) -- Access velocity print("Velocity: " .. tostring(part.Velocity)) print("Angular velocity: " .. tostring(part.AngularVelocity)) -- Spawn point configuration part.IsSpawn = true -- Players can spawn here ``` ### Environment - World Container and Physics Environment is the primary container for world objects and provides physics queries like raycasting, overlap detection, and explosions. ```lua -- Raycasting local hit = game["Environment"]:Raycast(barrel.Position, barrel.Forward) if hit and hit.Instance:IsA("Player") then hit.Instance.Health = 0 print("Hit player at position: " .. tostring(hit.Position)) end -- Raycast with max distance and ignore list local ignoreList = { game["Players"].LocalPlayer } local hit = game["Environment"]:Raycast( Vector3.New(0, 10, 0), Vector3.New(0, -1, 0), 100, ignoreList ) -- Raycast all (get all hits) local hits = game["Environment"]:RaycastAll(Vector3.New(0, 10, 0), Vector3.New(0, -1, 0), 100) for i, hit in pairs(hits) do print("Hit " .. hit.Instance.Name .. " at " .. tostring(hit.Position)) end -- Overlap detection (find objects in area) local intersections = game["Environment"]:OverlapSphere(Vector3.New(100, 0, 45), 25) for i, v in ipairs(intersections) do print(v.Name .. " is intersecting the sphere!") end local boxIntersections = game["Environment"]:OverlapBox( Vector3.New(0, 0, 0), Vector3.New(10, 10, 10), Vector3.New(0, 45, 0) ) -- Create explosion game["Environment"]:CreateExplosion( Vector3.New(0, 0, 0), -- Position 30, -- Radius 5000, -- Force false, -- AffectAnchored (unanchor parts if true) nil, -- Callback per part 10 -- Damage ) -- Environment properties game["Environment"].Gravity = Vector3.New(0, -75, 0) game["Environment"].FogEnabled = true game["Environment"].FogColor = Color.New(0.5, 0.5, 0.5) game["Environment"].FogStartDistance = 50 game["Environment"].FogEndDistance = 200 game["Environment"].PartDestroyHeight = -2000 -- NPC Navigation mesh game["Environment"]:RebuildNavMesh() local navPoint = game["Environment"]:GetPointOnNavMesh(Vector3.New(0, 0, 0)) ``` ### Datastore - Persistent Data Storage Datastore is a server-side service for storing player data between game sessions. It supports key-value storage with callbacks for async operations. ```lua -- Get or create a datastore (server-side only) local ds = Datastore:GetDatastore("Player_" .. player.UserID) -- Wait for datastore to load ds.Loaded:Connect(function() print("Datastore loaded!") -- Set initial values ds:Set("Coins", 100, function(success, error) if success then print("Coins saved!") else print("Error: " .. error) end end) end) -- Alternative: wait with while loop while ds.Loading do wait() end -- Get data ds:Get("Coins", function(value, success, error) if success then print(player.Name .. " has " .. value .. " coins.") else print("Error loading coins: " .. error) end end) -- Update data ds:Set("Coins", newCoinValue, function(success, error) if not success then print("Failed to save: " .. error) end end) -- Remove data ds:Remove("Coins", function(success, error) if success then print("Coins data removed!") end end) -- Complete player data example game["Players"].PlayerAdded:Connect(function(player) local ds = Datastore:GetDatastore("Player_" .. player.UserID) ds.Loaded:Connect(function() ds:Get("Level", function(value, success, error) if success and value then player.Shared.Level = value else player.Shared.Level = 1 ds:Set("Level", 1) end end) end) end) -- Rate limit: (30 + 10 * playerCount) requests per minute -- Max datastore size: 65,535 bytes -- Max key length: 32 characters ``` ### Http - HTTP Requests Http is a server-side static class for making HTTP requests to external APIs. It supports GET, POST, PUT, and DELETE methods with callbacks. ```lua -- GET request Http:Get("https://api.polytoria.com/v1/store/25272", function(data, error, errmsg) if not error then print("Response: " .. data) else print("Error: " .. errmsg) end end, {}) -- Empty headers table -- GET with custom headers Http:Get("https://api.example.com/data", function(data, error, errmsg) if not error then local parsed = json.parse(data) print("Name: " .. parsed["name"]) end end, { ["Authorization"] = "Bearer token123", ["Content-Type"] = "application/json" }) -- POST request (parameters as query string) Http:Post("https://example.com/api/post", "id=1&name=Hello", function(data, error, errmsg) if not error then print("POST successful: " .. data) else print("POST failed: " .. errmsg) end end, {}) -- PUT request Http:Put("https://example.com/api/update", "id=1&content=Updated", function(data, error, errmsg) if not error then print("Updated successfully") end end, {}) -- DELETE request Http:Delete("https://example.com/api/delete", "id=1", function(data, error, errmsg) if not error then print("Deleted successfully") end end, {}) -- Rate limit: 90 requests per minute per server -- Note: Place ID is sent as header "PT-Game-ID" ``` ### json - JSON Parsing json is a static class for converting between Lua tables and JSON strings, essential for working with HTTP API responses. ```lua -- Parse JSON string to table Http:Get("https://api.polytoria.com/v1/asset/owner?userID=1&assetID=234", function(data, error, errmsg) if not error then local result = json.parse(data) print("Success: " .. tostring(result["Success"])) print("Owner ID: " .. tostring(result["OwnerID"])) end end, {}) -- Serialize table to JSON string local playerData = { Name = "Cool Sword", Damage = 10, Enchantments = { "Fire", "Ice" }, Stats = { Attack = 50, Defense = 20 } } local jsonString = json.serialize(playerData) print(jsonString) -- {"Name":"Cool Sword","Damage":10,...} -- Check for null values if json.isNull(value) then print("Value is null") end -- Create null value for JSON local data = { name = "Test", optional = json.null() } ``` ### NetworkEvent and NetMessage - Client-Server Communication NetworkEvent enables bidirectional communication between server and clients. NetMessage is the data container for sending typed values across the network. ```lua -- Create NetworkEvent in Environment local netEvent = Instance.New("NetworkEvent", game["Environment"]) netEvent.Name = "MyNetworkEvent" -- SERVER-SIDE: Listen for client messages netEvent.InvokedServer:Connect(function(sender, message) local action = message:GetString("action") local amount = message:GetInt("amount") print(sender.Name .. " requested: " .. action) -- Send response back to specific client local response = NetMessage.New() response:AddBool("success", true) response:AddInt("newBalance", 500) netEvent:InvokeClient(response, sender) end) -- SERVER-SIDE: Broadcast to all clients local announcement = NetMessage.New() announcement:AddString("message", "Server restarting in 5 minutes!") announcement:AddInt("countdown", 300) netEvent:InvokeClients(announcement) -- CLIENT-SIDE: Send message to server local request = NetMessage.New() request:AddString("action", "purchase") request:AddInt("itemID", 12345) request:AddVector3("position", player.Position) netEvent:InvokeServer(request) -- CLIENT-SIDE: Listen for server messages netEvent.InvokedClient:Connect(function(sender, message) local success = message:GetBool("success") local balance = message:GetInt("newBalance") if success then print("Purchase successful! New balance: " .. balance) end end) -- NetMessage supports multiple data types local msg = NetMessage.New() msg:AddString("name", "Player1") msg:AddInt("score", 100) msg:AddNumber("multiplier", 1.5) -- float msg:AddBool("isActive", true) msg:AddVector2("screenPos", Vector2.New(100, 200)) msg:AddVector3("worldPos", Vector3.New(0, 10, 0)) msg:AddColor("teamColor", Color.New(1, 0, 0)) msg:AddInstance("target", somePart) -- Retrieve values local name = msg:GetString("name") local score = msg:GetInt("score") local multiplier = msg:GetNumber("multiplier") local isActive = msg:GetBool("isActive") local screenPos = msg:GetVector2("screenPos") local worldPos = msg:GetVector3("worldPos") local color = msg:GetColor("teamColor") local target = msg:GetInstance("target") -- Warning: Strings over 65,535 characters will be silently dropped ``` ### Input - User Input Handling Input is a client-side static class for detecting keyboard, mouse, and screen input. It provides both event-based and polling-based input detection. ```lua -- Keyboard events Input.KeyDown:Connect(function(key) print(key .. " was pressed!") if key == "P" then print("Pause menu!") elseif key == "Space" then print("Jump!") end end) Input.KeyUp:Connect(function(key) print(key .. " was released!") end) -- Polling-based input (use in game loop) game.Rendered:Connect(function(deltaTime) if Input:GetKey("W") then -- W is being held end if Input:GetKeyDown("E") then -- E was just pressed this frame end if Input:GetKeyUp("E") then -- E was just released this frame end -- Mouse buttons (0=left, 1=right, 2=middle) if Input:GetMouseButton(0) then -- Left mouse being held end if Input:GetMouseButtonDown(1) then -- Right click this frame end end) -- Mouse position and raycasting local mousePos = Input.MousePosition -- Vector2 local worldPos = Input:GetMouseWorldPosition() -- Vector3 -- Screen to world raycasting local ignoreList = { game["Players"].LocalPlayer } local hit = Input:ScreenPointToRay(Vector3.New(mousePos.x, mousePos.y, 0), ignoreList) if hit then print("Mouse is over: " .. hit.Instance.Name) end -- Coordinate conversions local screenPos = Input:WorldToScreenPoint(part.Position) local worldPos = Input:ScreenToWorldPoint(Vector2.New(100, 100)) local viewportPos = Input:ScreenToViewportPoint(Vector3.New(100, 100, 0)) -- Cursor control Input.CursorLocked = true -- Lock cursor to center Input.CursorVisible = false -- Hide cursor -- Screen dimensions print("Screen: " .. Input.ScreenWidth .. "x" .. Input.ScreenHeight) -- Check if typing in text field if Input.IsInputFocused then return -- Don't process game input while typing end -- Axis input (for analog controls) local horizontal = Input:GetAxis("Horizontal") local vertical = Input:GetAxis("Vertical") ``` ### Tween - Animation and Interpolation Tween is a static class for smoothly animating properties over time. It supports various easing types and can tween positions, rotations, sizes, colors, numbers, and vectors. ```lua -- Tween position local tweenID = Tween:TweenPosition(part, Vector3.New(100, 0, 0), 2, TweenType.linear, function() print("Position tween finished!") end) -- Tween rotation (euler angles) Tween:TweenRotation(part, Vector3.New(0, 360, 0), 1, TweenType.easeInOut, function() print("Rotation complete!") end) -- Tween size Tween:TweenSize(part, Vector3.New(10, 10, 10), 0.5, TweenType.easeOut, function() print("Grown to full size!") end) -- Tween color with per-step callback Tween:TweenColor( Color.New(1, 1, 1, 1), -- Start (white) Color.New(1, 0, 0, 0), -- End (transparent red) 2, -- Duration function(val) -- Called each step part.Color = val end, TweenType.easeIn, function() -- Completion callback print("Fade complete!") end ) -- Tween number (useful for UI, scores, etc.) Tween:TweenNumber(0, 100, 1, function(val) scoreLabel.Text = "Score: " .. math.floor(val) end, TweenType.linear, function() print("Counting finished!") end) -- Tween Vector2 (for UI positioning) Tween:TweenVector2( Vector2.New(0, 0), Vector2.New(0, 100), 0.5, function(val) uiElement.PositionOffset = val end, TweenType.easeOut, function() print("UI slide complete!") end ) -- Tween Vector3 Tween:TweenVector3( Vector3.New(0, 0, 0), Vector3.New(0, 50, 0), 2, function(val) part.Position = val end, TweenType.bounce, nil ) -- Cancel a tween local moveTween = Tween:TweenPosition(part, Vector3.New(100, 0, 0), 5, TweenType.linear, nil) wait(2) Tween:Cancel(moveTween) -- Stop after 2 seconds -- TweenType options: linear, easeIn, easeOut, easeInOut, bounce, elastic ``` ### Camera - Player View Control Camera is a client-side service for controlling the local player's camera view, including modes, field of view, and positioning. ```lua -- Camera modes Camera.Mode = CameraMode.FollowPlayer -- Default third-person Camera.Mode = CameraMode.Scripted -- Full script control Camera.Mode = CameraMode.Freecam -- Free-flying camera -- FollowPlayer mode settings Camera.Distance = 15 -- Distance from player Camera.MinDistance = 5 -- Minimum zoom Camera.MaxDistance = 50 -- Maximum zoom Camera.FollowLerp = true -- Smooth following Camera.LerpSpeed = 15 -- Lerp speed Camera.HorizontalSpeed = 120 -- Horizontal rotation speed Camera.VerticalSpeed = 120 -- Vertical rotation speed -- Camera offsets Camera.PositionOffset = Vector3.New(0, 5, 0) -- Above player Camera.RotationOffset = Vector3.New(15, 0, 0) -- Tilt down -- Field of view Camera.FOV = 90 -- Default is ~60 -- Orthographic (2D) mode Camera.Orthographic = true Camera.OrthographicSize = 30 -- Freecam settings Camera.FlySpeed = 10 Camera.FastFlySpeed = 50 Camera.FreeLookSensitivity = 3 -- Scripted camera control Camera.Mode = CameraMode.Scripted Camera.Position = Vector3.New(0, 50, -50) Camera.Rotation = Vector3.New(45, 0, 0) -- Other properties Camera.ClipThroughWalls = false Camera.ScrollSensitivity = 15 Camera.SensitivityMultiplier = 1 -- Check if first person if Camera.IsFirstPerson then print("Player is in first person view") end ``` ### Vector3 and Color - Data Types Vector3 represents 3D positions, directions, and sizes. Color represents RGBA color values. Both support mathematical operations and utility functions. ```lua -- Vector3 creation local v1 = Vector3.New() -- (0, 0, 0) local v2 = Vector3.New(5) -- (5, 5, 5) local v3 = Vector3.New(1, 2, 3) -- (1, 2, 3) -- Vector3 properties print(v3.x, v3.y, v3.z) -- Components print(v3.magnitude) -- Length print(v3.sqrMagnitude) -- Squared length (faster) local normalized = v3.normalized -- Unit vector -- Vector3 math operations local sum = v1 + v2 local diff = v1 - v2 local scaled = v1 * 2 local divided = v1 / 2 -- Vector3 utility functions local dist = Vector3.Distance(v1, v2) local angle = Vector3.Angle(v1, v2) local dot = Vector3.Dot(v1, v2) local cross = Vector3.Cross(v1, v2) local lerped = Vector3.Lerp(v1, v2, 0.5) -- Halfway between local clamped = Vector3.ClampMagnitude(v1, 10) local projected = Vector3.Project(v1, v2) local reflected = Vector3.Reflect(v1, v2) local maxVec = Vector3.Max(v1, v2) local minVec = Vector3.Min(v1, v2) local scaled = Vector3.Scale(v1, v2) -- Component-wise multiply -- Move towards target local newPos = Vector3.MoveTowards(current, target, maxDelta) -- Color creation local black = Color.New() -- Black local gray = Color.New(0.5) -- 50% gray local red = Color.New(1, 0, 0) -- Red (alpha=1) local transparentBlue = Color.New(0, 0, 1, 0.5) -- 50% transparent blue local fromHex = Color.FromHex("#FF5500") -- Orange from hex local randomColor = Color.Random() -- Random RGB -- Color properties print(color.r, color.g, color.b, color.a) -- Components (0-1 range) -- Color interpolation local blended = Color.Lerp(Color.New(1,0,0), Color.New(0,0,1), 0.5) -- Purple ``` ### UI Elements - User Interface UIView, UIButton, UILabel, and UIImage provide building blocks for in-game user interfaces. UI elements support styling, positioning, and events. ```lua -- UIView (rectangle container) local view = Instance.New("UIView", game["Players"].LocalPlayer.PlayerGUI) view.Position = Vector2.New(0.5, 0.5) -- Center of screen (0-1 range) view.Size = Vector2.New(200, 150) -- Pixel size view.Color = Color.New(0.2, 0.2, 0.2, 0.9) view.BorderColor = Color.New(1, 1, 1, 1) view.BorderWidth = 2 view.CornerRadius = 10 -- UIButton (clickable element) local button = Instance.New("UIButton", view) button.Text = "Click Me!" button.Size = Vector2.New(100, 40) button.Interactable = true button.Clicked:Connect(function() print("Button was clicked!") button.Text = "Clicked!" end) -- UILabel (text display) local label = Instance.New("UILabel", view) label.Text = "Score: 0" label.TextColor = Color.New(1, 1, 1) label.FontSize = 24 -- UIImage (image display) local image = Instance.New("UIImage", view) image.ImageID = 12345 -- Asset ID -- Common UIField properties (inherited by all UI elements) element.Visible = true element.Position = Vector2.New(0.5, 0.5) element.PositionOffset = Vector2.New(0, 0) -- Pixel offset element.Size = Vector2.New(100, 100) element.AnchorPoint = Vector2.New(0.5, 0.5) -- Center anchor element.Rotation = 0 ``` ### Achievements - Player Achievements Achievements is a server-side static class for awarding and checking place achievements. ```lua -- Award achievement when player joins game["Players"].PlayerAdded:Connect(function(player) wait(2) -- Wait for player to fully load Achievements:Award(player.UserID, 31472, function(success, error) if success then print("Awarded 'First Login' achievement to " .. player.Name) else print("Failed to award achievement: " .. error) end end) end) -- Check if player has achievement Achievements:HasAchievement(player.UserID, 31472, function(hasAchievement, success, error) if success then if hasAchievement then print(player.Name .. " already has the achievement!") player.WalkSpeed = 20 -- Bonus for achievement holders else print(player.Name .. " doesn't have it yet") end else print("Error checking achievement: " .. error) end end) -- Rate limit: 30 + (10 * playerCount) requests per minute ``` ## Summary Polytoria provides a comprehensive Lua scripting framework for multiplayer game development with clear separation between server and client code. The API follows an object-oriented design where all game objects inherit from Instance, enabling consistent patterns for creating, finding, and manipulating objects. Key static classes handle specialized functionality: Datastore for persistence, Http for external APIs, Input for player controls, Tween for animations, and Achievements for progression systems. NetworkEvent with NetMessage enables secure client-server communication with typed data transfer. Common integration patterns include: using PlayerAdded events to initialize player data and datastores, combining Http with json for external API integration, using NetworkEvent for client-server RPCs (remote procedure calls), and leveraging Tween for smooth animations without manual frame-by-frame updates. The Environment service provides physics queries (raycasting, overlap detection) essential for gameplay mechanics like shooting and collision detection. Understanding the server-exclusive vs client-exclusive restrictions is crucial - Datastore, Http, and Achievements only work on the server, while Input, Camera, and LocalPlayer only work on the client.