{"id":4654,"date":"2024-10-29T08:59:17","date_gmt":"2024-10-29T08:59:17","guid":{"rendered":"https:\/\/www.drmop.com\/?page_id=4654"},"modified":"2024-10-29T08:59:17","modified_gmt":"2024-10-29T08:59:17","slug":"unity-to-roblox-reference","status":"publish","type":"page","link":"http:\/\/www.drmop.com\/index.php\/unity-to-roblox-reference\/","title":{"rendered":"Unity to Roblox Reference"},"content":{"rendered":"\n<h1 class=\"wp-block-heading\">Overview<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">This document is an attempt to summarise important parts of the Roblox API from a Unity game developers perspective.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Note that this document is living and in progress so is incomplete and may contain errors.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Data Model<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Objects<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Every Object inherets from the Instance class.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3D Building Blocks<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">BasePart is the core class for pysically simulated 3D building blocks that render in the world. Various parts types exist such as Part, MeshPart, WedgePart etc..<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Scripts<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Script \u2013 Exists on server, clients cannot access<\/li>\n\n\n\n<li>LocalScript \u2013 Exists on client cnanot be accessed by server<\/li>\n\n\n\n<li>ModuleScript \u2013 Re-usable script that you require() from server and client. Once a module has been loaded it is cached so future requires of that module will use the cached version.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Object organisation<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Workspace \u2013 Stores all objects that exist in the world<\/li>\n\n\n\n<li>Environment \u2013 Containers for lighting, SoundService etc..<\/li>\n\n\n\n<li>Replication \u2013 Containers for logic and content that replicates between server and client such as ReplicatedStorage and ReplicatedFirst<\/li>\n\n\n\n<li>Server \u2013 Containers for service side only ontent and logic<\/li>\n\n\n\n<li>Client \u2013 Containers for client side only ontent and logic<\/li>\n\n\n\n<li>Chat \u2013 Containers for ibjects that enable chat features such as TextChatService and VoiceChatService<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Replication<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Replication is the process of the server synchronising the state of your place with all connected clients. The Roblox engine automatically replicates data, physics, and chat messages between the server and client for many cases, but you can also specify certain objects to replicate by placing them in specific containers.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>ReplicatedFirst &#8211; Contains objects that you want to replicate to a client when they join the game. It contains objects that are essential to initialize a player, such as client side LocalScript objects and objects associated with these scripts. All content in this container is replicated from server to client just the once.<\/li>\n\n\n\n<li>ReplicatedStorage &#8211; Contains objects that are available to both the server and connected clients. Any changes that occur on the client persist but won&#8217;t be replicated to the server. The server can overwrite changes on the client to maintain consistency. This container is typically used for ModuleScript objects that need to be shared and accessed by both Script (server-side) and LocalScript (client-side) objects. In addition, you can use this container to replicate any objects that don&#8217;t need to exist in the 3D world until needed, such as a ParticleEmitter for cloning and parenting to all incoming character models.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Server<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">This data model defines dedicated containers for server side only objects that are never replicated to the client.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>ServerScriptService &#8211; Contains Script objects, ModuleScript objects that are required by server scripts, and other scripting-related objects that are only meant for server use. If your scripts require other, non-scripting objects, you must place them in ServerStorage. Scripts in this container are never replicated to clients, which allows secure, server-side logic.<\/li>\n\n\n\n<li>ServerStorage &#8211; Contains objects that are only meant for server use. You can use this container to store objects that you want to clone and parent to the workspace or other containers at runtime. For example, you can store large objects such as maps in this container until they are needed and move them into the workspace only when required This lets you decrease client network traffic on initial join.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">When a game starts everything is copied to the client except these folders<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Client<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Client container services are meant for objects that are replicated to every connected client. This category of container replicate to every connected client and typically contain 3D objects and associated LocalScript objects. All objects you store in these containers are non-persistent across sessions and reset every time a client rejoins. You can put objects in these containers such as player GUIs, client-side scripts, and other objects that are only relevant to the client. When a client connects to a server, the Players container service listens for users joining your place and creates a Player object for every client. The server copies the objects from the client containers in the edit data model to the corresponding location in the runtime data model inside the Players object. The following table describes the original container it resides on in the container and the resulting container they are copied to on the client:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>StarterPack \u2013 Player.Backpack &#8211; Scripts that set up the player&#8217;s inventory and generally contain Tool objects but often contains local scripts as well.<\/li>\n\n\n\n<li>StarterGui \u2013 Player.PlayerGui &#8211; Scripts that can manage the player&#8217;s local GUI. When a player respawns, the contents of PlayerGui are emptied. The server copies the objects inside StarterGui into the PlayerGui.<\/li>\n\n\n\n<li>StarterPlayerScripts \u2013 Player.PlayerScripts &#8211; General purpose scripts for the client. For example, if you want to create special effects on the client when certain conditions are met, you can place a local script in this container to do that. The server cannot access this container.<\/li>\n\n\n\n<li>StarterCharacterScripts \u2013 Player.Character- Scripts that are copied to the client when they spawn. These scripts do not persist when the player respawns.<\/li>\n\n\n\n<li>ReplicatedFirst &#8211; The contents of this container are replicated to all clients (but not back to the server) first, before anything else.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Folders and Models<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">There are two primary methods for grouping objects in the data model: folders and models. Both are containers for objects, but they have different purposes.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Folders are best for storing sections of an environment, such as the lobby or a combat arena.<\/li>\n\n\n\n<li>Models are used for sets of objects, such as a desk set that includes a chair, table, and a lamp. To organize more complex sets, nest models inside models.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Saving game state<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The state of the game has to be saved so that it survives sessions \/ server restarts etc. There are two ways to save data on the server:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>DataStoreService &#8211; If the game state needs to persist across server shutdowns \/ updates and shares data across instances, Data containing the entire game state can be stored in a global key<\/li>\n\n\n\n<li>Server Storage &#8211; If the game world state only needs to be available while the server is running then it can be stored directly in server memory, so basically in a table in a server script<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">An example showing how to use the DataStoreService to store and retrieve game state:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>local GameState = {\n\tVersion = 1,\n\tBricks = 0\n} \n\nfunction SaveGameState()\n\tlocal success, error = pcall(function()\n\t\tVersion = 2;\n\t\tGameStateStore:SetAsync(\"GameState\", GameState)\n\tend)\n\tif not success then\n\t\twarn(error)\n\tend\t\nend\n\nfunction LoadGameState()\n\tlocal success, gameState = pcall(function()\n\t\treturn GameStateStore:GetAsync(\"GameState\")\n\tend)\n\tif success and gameState ~= nil then\n\t\tprint(gameState)\n\t\tGameState = gameState\n\telse\n\t\twarn(\"Could not load game state\")\n\tend\t\nend<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Update<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The main way we update objects in Unity is using the Update \/ FixedUpdate methods. This sae behaviour can be accomplished by connecting a function to the script objects heartbeat event, e.g.:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>RunService.Heartbeat:Connect(function(Delta)\n  -- Do stuff in this script every frame\nend)<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Note that this function is called at the end of the frame after physics updates have taken place.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">There are other update events that can also be tapped into including:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>RenderStepped &#8211; Called every frame, prior to the frame being rendered<\/li>\n\n\n\n<li>Stepped &#8211; Called every frame prior to the physics simulation<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Prefabs<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Whilst Roblox appears that it does not appear to support prefabs, it does allow you to define objects \/ models somewhere outside of the workspace and then Clone() it into the workspace.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>local prefab = script.Parent.prefab1\nlocal instance = prefab:Clone()\ninstance.Parent = workspace<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Places<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">A Roblox game is called an experience, it is made up of individual scenes within called places. Each place contains all components for that portion of the experience, including specific environment, parts, meshes, scripts user interface and so on.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">All experiences have a start place which is the default place a player goes when they run the experience. Once there the player can be teleported to other places using the TeleportService.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>local Players = game:GetService(\"Players\")\nlocal TeleportService = game:GetService(\"TeleportService\")\n\nlocal TARGET_PLACE_ID = 1234 -- replace with your own place ID\n\nlocal playerToTeleport = Players:GetPlayers()&#91;1] -- get the first user in the experience\n\nTeleportService:TeleportAsync(TARGET_PLACE_ID, {playerToTeleport}, teleportOptions)<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Adding new places to an experience is done via the Assets Manager in Roblox Studio.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">See <a href=\"https:\/\/create.roblox.com\/docs\/production\/publishing\/publishing-experiences-and-places\">https:\/\/create.roblox.com\/docs\/production\/publishing\/publishing-experiences-and-places<\/a> for more info.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Global namespace<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Roblox has a global namespace (well table) called _G that can be accessed across scripts (but not across clients or server)<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Lua Overview<\/h1>\n\n\n\n<h2 class=\"wp-block-heading\">Everything a table<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>MyTable = {1, 2, 3, 4}\nMyDic = {key1 = \"data1\", key2 = \"data2\"}\nprint(MyTable)<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Functions are all like Unity coroutines<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">All functions basically wait until the preceding instruction is complete, so if you call an async function it will not continue execution of instructions in that function until the task has completed, for example, getting data from an external server.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Loops<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>for t = 1, 10 do\n    print(t)\nend<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>for i,v in pairs(MyTable) do\n    print(i..\" \"..v)\nend<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>for k,v in pairs(MyDic) do\n    print(k..\" \"..v)\nend<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>while (true) do\n    print(\"loop\");\n    task.wait(1)\nend<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Random numbers<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>local randomInt = math.random(1, 10)\nrandomInt += 1\nprint(randomInt)<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Odd operators<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>-- Not equal\nlocal var1 = 50\nif (var1 ~= 10) then\n    print \"No Equal\"\nend\n-- logical operators and, or and not (yuk)<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Functions<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>function Function1(var1, var2)\n    return 100\nend<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>local function localFunc(...)\n    local allNumbers = {...}\n    print(allNumbers)\nend\nlocalFunc(1, 3, 5, 7, 9, 11)<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Metatables<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>-- Metatables\nlocal myTable2 = {1, 2, 3}\nlocal metaTable = {\n\t__add = function(table1, number)\n\t\tlocal result = {}\n\t\tfor i,v in table1 do\n\t\t\tresult&#91;i] = number + v\n\t\tend\n\t\treturn result\n\tend,\n\t__index = function(table1, key)\n\t\tprint(\"key \" .. key .. \" not found\")\n\t\treturn \"N\/a\"\n\tend,\n}\nmetaTable.\t__call = function(table1, ...)\n\tprint(\"Called table with values\")\n\tprint(...)\nend\n\nsetmetatable(myTable2,  metaTable)\n\nprint(myTable2 + 4)\nprint(myTable2&#91;10])\nmyTable2(1, 2, 3, 4)<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Coroutines<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>-- Coroutines\nlocal thread = coroutine.create(function()\n\twhile true do\n\t\tprint(\"In a coroutine\")\n\t\ttask.wait(1)\n\tend\nend)\ncontinue.resume(thread)<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Colon Operator<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The colon operator is just a way of passing a hidden self to a function when calling it<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>local function MyClass:Speak(extra)\n\treturn self.speech .. extra\nend<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Modules<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Module lets you pack code and data that can be shared across multiple scripts:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>A module<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>local PickupManager = {}\n\nlocal defaultMultiplier = 1.25\nlocal rarityMultipliers = {\n\tcommon = 10,\n    uncommon = 20,\n\trare = 50,\n\tlegendary = 100\n}\n\n-- Add the getPickupBonus function to the PickupManager module table\nfunction PickupManager.getPickupBonus(rarity)\n\tlocal bonus = rarityMultipliers&#91;rarity] * defaultMultiplier\n\treturn bonus\nend\n\nreturn PickupManager<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Using a module<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>-- Script in ReplicatedStorage\nlocal ReplicatedStorage = game:GetService(\"ReplicatedStorage\")\n\n-- Get value returned by ModuleScript\nlocal PickupManager = require(ReplicatedStorage:WaitForChild(\"PickupManager\"))\n\n-- Call a ModuleScript function\nlocal bonus = PickupManager.getPickupBonus(\"legendary\")\nprint(bonus) --&gt; 125<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If we require() a ModuleScript from both sides of the client-server boundary, then the ModuleScript returns a unique reference for each side.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Object Orientation<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">A basic class using metatables<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>-- The class\nlocal Enemy = {Name = \"\", Health = 0, Damage = 0, Speed = 0}\nEnemy.__index = Enemy\n\n-- Class functions\nfunction Enemy:Attack()\n\tprint(\"The \"..self.Name..\" attacked with \"..self.Damage..\" damage!\")\nend\n\n-- Constructor\nfunction Enemy.new(name, health, damage, speed)\n\tlocal self = setmetatable({}, Enemy)\n\tself.Name = name\n\tself.Health = health\n\tself.Damage = damage\n\tself.Speed = speed\n\t\n\treturn self\nend\n\n-- Creating an object\nlocal goblin = Enemy.new(\"Goblin\", 100, 50, 10)\ngoblin:Attack()\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Example of inheritence<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>local Animal = { -- Superclass\n\t-- Properties for all animals\n\tName = \"Unknown\",\n\tSound = \"Silent\",\n}\nAnimal.__index = Animal\n\n-- Function for all animals\nfunction Animal:Speak()\n\tprint(self.Name .. \" says \" .. self.Sound)\nend\n\nlocal Cat = {} -- Subclass\nCat.__index = Cat\nsetmetatable(Cat, Animal) -- Cat class inherits properties\/behavior from Animal superclass\n\nCat.Name = \"Cat\"\nCat.Sound = \"Meow\"\n\n-- Function just for cats\nfunction Cat:Sneak()\n\tprint(self.Name..\" is sneaking around.\")\nend\n\nlocal myCat = setmetatable({}, Cat)\nmyCat:Speak()\nmyCat:Sneak()<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Script Reference<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">A script is also a table, its children can be accessed as follows:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>script&#91;\"myImage\"] -- This accesses the myImage instane of the scripts children<\/code><\/pre>\n\n\n\n<h1 class=\"wp-block-heading\">Roblox Objects<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Roblox has many different types of objects (called classes) that can be created in the editor and \/ or in script. There are too many to mention here so we will just cover a few common ones:<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Player<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">A player object represents a client that is connected to the game. Players are added to the Players service when they join and removed when they disconnect.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The player object has a number of important properties:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Name &#8211; The players username<\/li>\n\n\n\n<li>DisplayName &#8211; The DisplayName of the UserId associated with the Player<\/li>\n\n\n\n<li>UserId &#8211; The players unique user id<\/li>\n\n\n\n<li>Character &#8211; A Model that controlled by the player which contains a Humanod object, body parts, scripts and other objects<\/li>\n\n\n\n<li>CameraMode &#8211; Players camera mode<\/li>\n\n\n\n<li>GameplayPaused &#8211; Players client side paused state<\/li>\n\n\n\n<li>RespawnLocation &#8211; Location spawn point<\/li>\n\n\n\n<li>Many other properties\u2026<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Useful examples<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>-- Get list of players\nlocal Players = game:GetService(\"Players\")<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>-- Set up player added \/ removing events\nPlayers.PlayerAdded:Connect(function(player) \nend)\n\t\nPlayers.PlayerRemoving:Connect(function(player)\nend)<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>-- Get associated Humanoid (server side) - Need to make sure that the character has loaded using CharacterAdded event\nlocal humanoid = player.Character:FindFirstChildWhichIsA(\"Humanoid\")\n\n-- Get associated Humanoid (client side)\nlocal character = Players.LocalPlayer.Character\nlocal humanoid = character.Humanoid<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">[TODO: Update as we go]<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">See <a href=\"https:\/\/create.roblox.com\/docs\/reference\/engine\/classes\/Player\">https:\/\/create.roblox.com\/docs\/reference\/engine\/classes\/Player<\/a> for more info<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Humanoid<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The humanoid object is a special object type that gives models the ability of a character. Humanoid objects can walk around and interact the level. Humanoids are always parented inside a Model, the model is expected to be an assembly of BasePart and Motor6D.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">There are two types of rig types for characters which are called R6 and R15.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The Humanoid object has a number of important properties:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>CameraOffset &#8211; Camera offset from player<\/li>\n\n\n\n<li>DisplayName &#8211; Name displayed above the characters head<\/li>\n\n\n\n<li>FloorMaterial &#8211; The material the character is currently stood on or Air if not<\/li>\n\n\n\n<li>Health &#8211; Amount of health<\/li>\n\n\n\n<li>MaxHealth &#8211; Max health of character<\/li>\n\n\n\n<li>JumpHeight &#8211; Jump height of character<\/li>\n\n\n\n<li>Many more properties<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">See <a href=\"https:\/\/create.roblox.com\/docs\/reference\/engine\/classes\/Humanoid\">https:\/\/create.roblox.com\/docs\/reference\/engine\/classes\/Humanoid<\/a> for more info<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Parts<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The Part object is a basic 3D part and a type of BasePart (BasePart is abstract). A part comes in a number of different primitive shapes including Ball, Block, Cylinder, Wedge, and CornerWedge as well as more complex parts such as MeshPart\u2019s. Lets take a look at creating and destroying a part in code:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>local part = Instance.new(\"Part\")\npart.Name = \"MyBall\"\npart.Anchored = true\npart.Shape = Enum.PartType.Ball\npart.Color = Color3.new(1, 1, 1)\npart.Parent = workspace -- Put the part into the Workspace\n\n-- Destroy part\npart:Destroy()<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Note that parts automatically have physics applied to them.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Parts support all sorts of events which are fired when something happens to the part for example when the part is being destroyed:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>local part = Instance.new(\"Part\", workspace)\n\nlocal function onPartDestroying()\n    print(\"Before yielding:\", part:GetFullName(), #part:GetChildren())\n    task.wait()\n    print(\"After yielding:\", part:GetFullName(), #part:GetChildren())\nend\npart.Destroying:Connect(onPartDestroying)\n\npart:Destroy()<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Another example is Touched and TouchEnded events:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>local part = script.Parent\n\nlocal billboardGui = Instance.new(\"BillboardGui\")\nbillboardGui.Size = UDim2.new(0, 200, 0, 50)\nbillboardGui.Adornee = part\nbillboardGui.AlwaysOnTop = true\nbillboardGui.Parent = part\n\nlocal tl = Instance.new(\"TextLabel\")\ntl.Size = UDim2.new(1, 0, 1, 0)\ntl.BackgroundTransparency = 1\ntl.Parent = billboardGui\n\nlocal numTouchingParts = 0\n\nlocal function onTouch(otherPart)\n\tprint(\"Touch started: \" .. otherPart.Name)\n\tnumTouchingParts = numTouchingParts + 1\n\ttl.Text = numTouchingParts\nend\n\nlocal function onTouchEnded(otherPart)\n\tprint(\"Touch ended: \" .. otherPart.Name)\n\tnumTouchingParts = numTouchingParts - 1\n\ttl.Text = numTouchingParts\nend\n\npart.Touched:Connect(onTouch)\npart.TouchEnded:Connect(onTouchEnded)<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Many different kinds of events are supported.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">See <a href=\"https:\/\/create.roblox.com\/docs\/reference\/engine\/classes\/Part\">https:\/\/create.roblox.com\/docs\/reference\/engine\/classes\/Part<\/a> and <a href=\"https:\/\/create.roblox.com\/docs\/reference\/engine\/classes\/BasePart\">https:\/\/create.roblox.com\/docs\/reference\/engine\/classes\/BasePart<\/a> for more info<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">GuiObject<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">A GuiObject is an abstract base class that forms the base of all GUI objects, it provides some base properties such as size and position. UIComponent&#8217;s can be attached to GUI objects as children to affect their behaviour, such as forcing the layout of its children, adding padding etc..<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Types of GUI objects:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Frame &#8211; Like a Unity panel, these are used to group GUI elements together.<\/li>\n\n\n\n<li>TextLabel &#8211; Displays text.<\/li>\n\n\n\n<li>TextButton &#8211; Button with text<\/li>\n\n\n\n<li>TextBox &#8211; Text entry<\/li>\n\n\n\n<li>ImageLabel &#8211; Displays an image.<\/li>\n\n\n\n<li>ImageButton &#8211; Button with an image<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Size and Positions<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Elements are positioned and sized using scale and offset. Offset represents the pixel size \/ position, whilst scale represents size \/ position of parent. For example an element positioned at 0.5 scale and offset 100 would position the element half way across the screen + 100 pixels. Setting its size to scale of 0.1 and offset of 0 will make it 10% of the screen size (assuming the elements parent is the screen)<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">See <a href=\"https:\/\/create.roblox.com\/docs\/reference\/engine\/classes\/GuiObject\">https:\/\/create.roblox.com\/docs\/reference\/engine\/classes\/GuiObject<\/a> for info on GuiObject\u2019s<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">See <a href=\"https:\/\/create.roblox.com\/docs\/ui\">https:\/\/create.roblox.com\/docs\/ui<\/a> for more general GUI info<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">[TODO: Add more object types]<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Roblox API<\/h1>\n\n\n\n<h2 class=\"wp-block-heading\">The Game Object<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>game<\/strong> object is the big table for the whole game, both wonderful and nightmarish.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">See <a href=\"https:\/\/create.roblox.com\/docs\/reference\/engine\/classes\/DataModel\">https:\/\/create.roblox.com\/docs\/reference\/engine\/classes\/DataModel<\/a> for more info<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Task Library<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>task.wait(time) Yields a thread, we generally call this inside a loop of a spawned task<\/li>\n\n\n\n<li>task.spawn(function) \u2013 Spawns a function immediately<\/li>\n\n\n\n<li>task.defer(function) \u2013 Spawns a function at the end of the frame with all the other deferred tasks<\/li>\n\n\n\n<li>task.delay(time, function) \u2013 RunAfterTime basically<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">These functions all return a thread type which can be manipulated, e.g.:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>local thread = task.delay(5, function()\n\tDoSomeShiz\nend\nprint(coroutine.status(thread)<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">See <a href=\"https:\/\/create.roblox.com\/docs\/reference\/engine\/libraries\/task\">https:\/\/create.roblox.com\/docs\/reference\/engine\/libraries\/task<\/a> for more info<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Basic Data Types<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Examples:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>local position = Vector3.new(1, 2, 3)\nworkspace.YellowPart.Position = position\nworkspace.YellowPart.Color = Color3.fromRGB(50, 100, 255)\n\nlocal newPart = Instance.new(\"Part\") \u2013 Creates an instance of a new Part\nnewPart.Anchored = true\nnewPart.Position = Vector3.new(1, 2, 3)\nnewPart.Shape = Enum.PartType.Ball\n\nlocal rng = Random.new()\nprint(rng.NextInteger(1, 100))<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Attributes<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Attributes can be added to any object and accessed from code. They can be added in the editor under the Attributes section of the object or added in code. You can also delete attributes, get a list of all attributes and listen for changes to the attributes:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>-- Add or update attribute\nlocal weapon = script.Parent\nweapon:SetAttribute(\"ReloadTime\", 3)\n\n-- Get the attribute value\nlocal reloadTimeValue = weapon:GetAttribute(\"ReloadTime\")\nprint(reloadTimeValue)\n\n-- Get all instance attributes\nlocal weaponAttributes = weapon:GetAttributes()\nfor name, value in weaponAttributes do\n\tprint(name, value)\nend\n\n-- Delete an existing attribute\nweapon:SetAttribute(\"ReloadTime\", nil)\n\n--- Listen for one specific attribute change\nweapon:GetAttributeChangedSignal(\"ReloadTime\"):Connect(function()\n\tprint(weapon:GetAttribute(\"ReloadTime\"))\nend)\n\n-- Listen for any attribute change on the instance\nweapon.AttributeChanged:Connect(function(attributeName)\n\tprint(attributeName, weapon:GetAttribute(attributeName))\nend)<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">See <a href=\"https:\/\/create.roblox.com\/docs\/studio\/properties\">https:\/\/create.roblox.com\/docs\/studio\/properties<\/a> for more info<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Coordinate Frames (CFrame)<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Unity Transform without scale. Cframe is actually a matrix so if you multiple them together its like multipliying matrices. Cframes support Lerp:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>local redBlock = workspace.RedBlock\nlocal blueCube = workspace.BlueCube\n\n-- Create a Vector3 for both the start position and target position\nlocal startPosition = Vector3.new(0, 3, 0)\nlocal targetPosition = blueCube.Position\n\n-- Put the redBlock at startPosition and point its front surface at targetPosition\nredBlock.CFrame = CFrame.new(startPosition, targetPosition)<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">See <a href=\"https:\/\/create.roblox.com\/docs\/workspace\/cframes\">https:\/\/create.roblox.com\/docs\/workspace\/cframes<\/a> for more info<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Event Driven<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Roblox is very event drivem:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>local part = workspace.EventPart\n\n-- Touched event\npart.Touched:Connect(function(otherPart)\n\tprint(otherPart.Name)\nend)\n\n-- Child \/ Descendant added event\npart.ChildAdded:Connect(function(child)\n\tprint(child.Name)\nend)\n\npart.DescendantAdded:Connect(function(descendant)\n\tprint(descendant.Name)\nend)\n\nfor i = 1, 2 do\n\tlocal newPart = Instance.new(\"Part\")\n\tnewPart.Name = \"NewPart\"..i\n\tnewPart.Parent = part:FindFirstChildWhichIsA(\"BasePart\") or part\nend<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">See <a href=\"https:\/\/create.roblox.com\/docs\/scripting\/events\">https:\/\/create.roblox.com\/docs\/scripting\/events<\/a> for more info<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Animation<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Animations can be played both server and client side.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Remote events<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">A remote event instance allows the server to communicate information to the client or the client to the server.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Create a new RemoteEvent in ReplicatedStorage in the editor so that the client and server has access to the event and then:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Client<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>local replicatedStorage = game:GetService(\"ReplicatedStorage\")\nlocal event = ReplicatedStorage.RemoteEvent\nevent:FireServer(\"Hello\")<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Server<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>local replicatedStorage = game:GetService(\"ReplicatedStorage\")\nlocal event = ReplicatedStorage.RemoteEvent\nevent:OnServerEvent:Connect(function(player, data)\n\tprint(player.Name, data)\nend)<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">See <a href=\"https:\/\/create.roblox.com\/docs\/scripting\/events\/remote\">https:\/\/create.roblox.com\/docs\/scripting\/events\/remote<\/a> for more info<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Remote functions<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">A remote function instance allows the client to call the server and get a result returned. Can be used for calls to client from server too but not recommended because the elient may have left<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Create a new RemoteFunction in ReplicatedStorage in the editor so that the client and server has access to the function and then:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Client<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>local replicatedStorage = game:GetService(\"ReplicatedStorage\")\nlocal event = ReplicatedStorage.RemoteFunction\nlocal result = event:InvokeServer(\"Hello\")<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Server<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>local replicatedStorage = game:GetService(\"ReplicatedStorage\")\nlocal event = ReplicatedStorage.RemoteFunction\nevent:OnServerInvoke =  function(player, password)\n\tif (password == \"Hello\") then\n\t\treturn true\n\tend\n\treturn false\nend<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">See <a href=\"https:\/\/create.roblox.com\/docs\/reference\/engine\/classes\/RemoteFunction\">https:\/\/create.roblox.com\/docs\/reference\/engine\/classes\/RemoteFunction<\/a> for more info<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Bindable Functions and Events<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Bindable Function and Events are like Remote functions and events but only operate on the same side of the client-server divide. This allows for synchronous two-way communication between scripts on the same side of the client-server boundary. The code invoking the function yields until the corresponding callback is found, and the callback receives the arguments that you passed to Invoke(). If the callback was never set, the script that invokes it will not resume execution.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">See <a href=\"https:\/\/create.roblox.com\/docs\/reference\/engine\/classes\/BindableFunction\">https:\/\/create.roblox.com\/docs\/reference\/engine\/classes\/BindableFunction<\/a> for more info<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Tween Service<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">TweenService can animate most properties, quick example of a looping tween;<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>local TweenService = game:GetService(\"TweenService\")\n\nlocal part = Instance.new(\"Part\")\npart.Position = Vector3.new(0, 10, 0)\npart.Anchored = true\npart.Parent = workspace\n\nlocal tweenInfo = TweenInfo.new(\n\t2, -- Time\n\tEnum.EasingStyle.Linear, -- EasingStyle\n\tEnum.EasingDirection.Out, -- EasingDirection\n\t-1, -- RepeatCount (when less than zero the tween will loop indefinitely)\n\ttrue, -- Reverses (tween will reverse once reaching it's goal)\n\t0 -- DelayTime\n)\n\nlocal tween = TweenService:Create(part, tweenInfo, { Position = Vector3.new(0, 30, 0) })\ntween:Play()\ntask.wait(10)\ntween:Cancel() -- cancel the animation after 10 seconds<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">See <a href=\"https:\/\/create.roblox.com\/docs\/reference\/engine\/classes\/TweenService\">https:\/\/create.roblox.com\/docs\/reference\/engine\/classes\/TweenService<\/a> for more info<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">User Input Service<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Used to detect and capture different types of input from the users device, for example:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>local UserInputService = game:GetService(\"UserInputService\")\n\nUserInputService.InputBegan:Connect(function(inputObj, processed)\n\tprint(\"Was processed by UI:\", processed)\n\n\tif inputObj.UserInputType == Enum.UserInputType.MouseButton1 then\n\t\tprint(\"mouse was held down\")\n\telseif inputObj.KeyCode == Enum.KeyCode.E then\n\t\tprint(\"key E was held down\")\n\tend\nend)\n\nUserInputService.InputEnded:Connect(function(inputObj, processed)\n\tprint(\"Was processed by UI:\", processed)\n\n\tif inputObj.UserInputType == Enum.UserInputType.MouseButton1 then\n\t\tprint(\"mouse was released\")\n\telseif inputObj.KeyCode == Enum.KeyCode.E then\n\t\tprint(\"key E was released\")\n\tend\nend)\n\nUserInputService.TouchTapInWorld:Connect(function(screenPos, processed)\n\tprint(\"Was processed by UI:\", processed)\n\tprint(\"screen tap at position:\", screenPos)\nend)<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">See <a href=\"https:\/\/create.roblox.com\/docs\/reference\/engine\/classes\/UserInputService\">https:\/\/create.roblox.com\/docs\/reference\/engine\/classes\/UserInputService<\/a> for more info<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Context Action Service<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Allows you to bind user input to contextual actions, or actions that are only enabled under certain condition or at specific points n of time. An example is allowing a player to open a door only while close to the door, this will pop up a small contextual action bubble.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>local ContextActionService = game:GetService(\"ContextActionService\")\n\nlocal function onAction(actionName, inputState, inputObj)\n\tif inputState == Enum.UserInputState.Begin then\n\t\tprint(\"Input began!\", actionName)\n\telseif inputState == Enum.UserInputState.End then\n\t\tprint(\"Input ended!\", actionName)\n\tend\n\treturn Enum.ContextActionResult.Pass\nend\n\n-- Allows us to listen to multiple different inputs &amp; creates a button on screen\nContextActionService:BindAction(\"ExampleAction1\", onAction, true, Enum.KeyCode.P, Enum.UserInputType.Touch, Enum.UserInputType.MouseButton1)\nContextActionService:BindAction(\"ExampleAction2\", onAction, true, Enum.KeyCode.P, Enum.UserInputType.Touch, Enum.UserInputType.MouseButton1)\nlocal button = ContextActionService:GetButton(\"ExampleAction1\")\nbutton:SetTitle(\"Example Action 1\")\n\n-- When we are done with listening to these actions we can unbind them\nContextActionService:UnbindAction(\"ExampleAction1\")\nContextActionService:UnbindAction(\"ExampleAction2\")<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">See <a href=\"https:\/\/create.roblox.com\/docs\/reference\/engine\/classes\/ContextActionService\">https:\/\/create.roblox.com\/docs\/reference\/engine\/classes\/ContextActionService<\/a> for more info<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Collection Service<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">CollectionService manages collections of instances with tags. Tags are sets of strings applied to objects that replicate from the server to the client. They are also serialized when places are saved. You can set a tag to objects in the workspace as well as in script.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>local CollectionService = game:GetService(\"CollectionService\")\n\n-- Get all instances marked with KillBrick tag\nlocal bricks = CollectionService:GetTagged(\"KillBrick\")\nlocal connections = {}\n\nlocal function onTouched(otherPart)\n\tlocal humanoid = otherPart.Parent:FindFirstChildWhichIsA(\"Humanoid\")\n\tif humanoid then\n\t\thumanoid.Health = 0\n\tend\nend\n\n-- Sets up all current kill bricks in the game\nfor _, brick in bricks do\n\tconnections&#91;brick] = brick.Touched:Connect(onTouched)\nend\n\n-- Sets up any kill bricks added after the game starts\nCollectionService:GetInstanceAddedSignal(\"KillBrick\"):Connect(function(brick)\n\tprint(\"new killbrick was added!\")\n\tconnections&#91;brick] = brick.Touched:Connect(onTouched)\nend)\n\n-- Cleans up any parts that have this tag removed\nCollectionService:GetInstanceRemovedSignal(\"KillBrick\"):Connect(function(brick)\n\tif connections&#91;brick] then\n\t\tconnections&#91;brick]:Disconnect()\n\t\tconnections&#91;brick] = nil\n\tend\nend)<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Dee <a href=\"https:\/\/create.roblox.com\/docs\/reference\/engine\/classes\/CollectionService\">https:\/\/create.roblox.com\/docs\/reference\/engine\/classes\/CollectionService<\/a> for more info<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Players Service<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The Players service contains Player objects for all connected clients to a Roblox server. It contains information about a place&#8217;s configuration. It can also collect info about players that are not connected to the server, i.e. players character appearances, friends and avatar thumbnail etc..<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Players Joining \/ Leaving Events<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>local Players = game:GetService(\"Players\")\n    Players.PlayerAdded:Connect(function(player)\n    print(player.Name .. \" joined the game!\")\nend)\n\nPlayers.PlayerRemoving:Connect(function(player)\n    print(player.Name .. \" left the game!\")\nend)<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Getting a players name from their ID<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>local Players = game:GetService(\"Players\")\nlocal name = Players:GetNameFromUserIdAsync(118271)<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Accessing backpack<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>-- Backpack from a Server Script\ngame.Players.PlayerName.Backpack\n\n-- Backpack from a LocalScript\ngame.Players.LocalPlayer.Backpack<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Adding a tool via code<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>local Players = game:GetService(\"Players\")\n\nlocal function giveTool(player, tool)\n\tlocal backpack = player:FindFirstChildOfClass(\"Backpack\")\n\tif backpack then\n\t\ttool.Parent = backpack\n\tend\nend\n\nlocal function onPlayerAdded(player)\n\tlocal tool = Instance.new(\"Tool\")\n\tgiveTool(player, tool)\nend\n\nPlayers.PlayerAdded:Connect(onPlayerAdded)<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Adding a tool via editor<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">See <a href=\"https:\/\/create.roblox.com\/docs\/reference\/engine\/classes\/Players\">https:\/\/create.roblox.com\/docs\/reference\/engine\/classes\/Players<\/a> for more info<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Data Store Service<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The DataStoreService allows us to store data that needs to persist between sessions, such as items in a player&#8217;s inventory or skill points. Data stores are consistent per experience, so any place in an experience can access and change the same data, including places on different servers. Also supports Ordered Data Store.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>local Players = game:GetService(\"Players\")\nlocal DataStoreService = game:GetService(\"DataStoreService\")\n\nlocal moneyDataStore = DataStoreService:GetDataStore(\"PlayerMoney\")\nlocal erroredPlayers = {}\n\nlocal function getMoneyDataFor(player)\n\tlocal success, result = pcall(function()\n\t\treturn moneyDataStore:GetAsync(player.UserId)\n\tend)\n\t\n\tif success then\n        if not result then\n            -- no result means this is a new player in our game\n\t\t\tresult = 0\n\t\tend\n\n\t\treturn result\n\tend\n\t\n\twarn(\"Failed to grab money data for player:\", player.UserId, result)\n\t--&#91;&#91; What if we failed to grab data? \n\tthen we don't want to save this data for the player when they leave.\n\tStore them in a table so we can keep track of errored players\n\t]]\n\terroredPlayers&#91;player.Name] = true\n\t\n\treturn 0\nend\n\nlocal function saveMoneyDataFor(player, amount)\n    -- Don't wont want to save data for nonreal player accounts\n    if player.UserId &lt; 1 then\n        warn(\"Unable to save data for nonreal player accounts!\")\n        return\n    end\n\n\tif erroredPlayers&#91;player.Name] then\n\t\twarn(\"Can't save data for an errored player!\")\n\t\treturn\n\tend\n\tlocal success, err = pcall(function()\n\t\tmoneyDataStore:UpdateAsync(player.UserId, function(oldData)\n            -- this function is NOT allowed to yield!\n\t\t\toldData = amount\n\t\t\treturn oldData\n\t\tend)\n\tend)\n\t\n\tif not success then\n\t\twarn(\"Failed to save data for player:\", player.UserId, err)\n\tend\nend\n\nlocal function setupLeaderboardFor(player)\n\tlocal folder = Instance.new(\"Folder\")\n\tfolder.Name = \"leaderstats\"\n\tfolder.Parent = player\n\t\n\tlocal money = Instance.new(\"NumberValue\")\n\tmoney.Name = \"Money\"\n\tmoney.Value = getMoneyDataFor(player) -- grabs players money from data store\n\tmoney.Parent = folder\nend\n\nlocal function saveMoneyDataForAllPlayers()\n\tfor _, player in Players:GetPlayers() do\n\t\ttask.spawn(function()\n\t\t\tsaveMoneyDataFor(player, player.leaderstats.Money.Value)\n\t\tend)\n\tend\nend\n\nPlayers.PlayerAdded:Connect(function(player)\n\tsetupLeaderboardFor(player)\nend)\nPlayers.PlayerRemoving:Connect(function(player)\n    -- Saves a players money when leaving the game\n\tsaveMoneyDataFor(player, player.leaderstats.Money.Value)\n\terroredPlayers&#91;player.Name] = nil\nend)\nfor _, player in Players:GetPlayers() do\n\tsetupLeaderboardFor(player)\nend\n\ngame:BindToClose(function()\n\t-- Saves players money when game is shutdown\n\tsaveMoneyDataForAllPlayers()\nend)\n\nwhile true do\n\t-- saves players money every 5 minutes\n\ttask.wait(300)\n\tsaveMoneyDataForAllPlayers()\nend<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">See <a href=\"https:\/\/create.roblox.com\/docs\/reference\/engine\/classes\/DataStoreService\">https:\/\/create.roblox.com\/docs\/reference\/engine\/classes\/DataStoreService<\/a> for more info<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Text Chat Service<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">TextChatService handles text chat, including managing channels, decorating messages, filtering text, creating commands, and developing custom chats interfaces.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>-- text chat service &amp; rich text markup\nlocal TextChatService = game:GetService(\"TextChatService\")\nlocal Players = game:GetService(\"Players\")\n\nTextChatService.OnIncomingMessage = function(msg)\n\tif not msg.TextSource then\n\t\treturn\n\tend\n\tlocal properties = Instance.new(\"TextChatMessageProperties\")\n\tlocal player = Players:GetPlayerByUserId(msg.TextSource.UserId)\n\tlocal hasVIP = player:GetAttribute(\"HasVIP\")\n\tif hasVIP then\n\t\t-- account for any previous prefixes by concatenating\n\t\tproperties.PrefixText = \"&lt;font color='#F5CD30'&gt;&#91;VIP]&lt;\/font&gt; \"..msg.PrefixText\n\tend\n\t\n\treturn properties\nend\n\nTextChatService.OnBubbleAdded = function(msg, adornee)\n\tif not msg.TextSource then\n\t\treturn\n\tend\n\tlocal bubbleProperties = Instance.new(\"BubbleChatMessageProperties\")\n\tlocal player = Players:GetPlayerByUserId(msg.TextSource.UserId)\n\tlocal hasVIP = player:GetAttribute(\"HasVIP\")\n\tif hasVIP then\n\t\tbubbleProperties.TextColor3 = Color3.fromRGB(255, 149, 0)\n\t\tbubbleProperties.BackgroundColor3 = Color3.fromRGB(81, 81, 81)\n\t\tbubbleProperties.FontFace = Font.fromEnum(Enum.Font.Arcade)\n\tend\n\treturn bubbleProperties\nend<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">See <a href=\"https:\/\/create.roblox.com\/docs\/reference\/engine\/classes\/TextChatService\">https:\/\/create.roblox.com\/docs\/reference\/engine\/classes\/TextChatService<\/a> for more info<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Messaging Service<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">MessagingService allows servers of the same game to communicate with each other in real time using topics. Topics are developer\u2011defined strings (1\u201380 characters) that servers use to send and receive messages.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Delivery is not guaranteed so we have to plan the game around delivery failures being possible.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>local MessagingService = game:GetService(\"MessagingService\")\nlocal Players = game:GetService(\"Players\")\n\nlocal function onPlayerAdded(player)\n\t--subscribe to the topic\n\tlocal topic = \"player-\" .. player.UserId\n\tlocal connection = MessagingService:SubscribeAsync(topic, function(message)\n\t\tprint(\"Received message for\", player.Name, message.Data)\n\tend)\n\n\tplayer.AncestryChanged:Connect(function()\n\t\t-- unsubscribe from the topic\n\t\tconnection:Disconnect()\n\tend)\nend\n\nPlayers.PlayerAdded:Connect(onPlayerAdded)<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">See <a href=\"https:\/\/create.roblox.com\/docs\/reference\/engine\/classes\/MessagingService\">https:\/\/create.roblox.com\/docs\/reference\/engine\/classes\/MessagingService<\/a> for more info<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Content Provider Service<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">This service is used to load content \/ assets into the game. The main use of this service is to preload assets into the game. Assets are loaded using PreloadAysnc().<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Example:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>local ContentProvider = game:GetService(\"ContentProvider\")\n\nlocal LOGO_ID = \"rbxassetid:\/\/658743164\"\nlocal PAGE_TURN_ID = \"rbxassetid:\/\/12222076\"\n\nlocal decal = Instance.new(\"Decal\")\ndecal.Texture = LOGO_ID\n\nlocal sound = Instance.new(\"Sound\")\nsound.SoundId = PAGE_TURN_ID\n\nlocal assets = { decal, sound }\n\nContentProvider:PreloadAsync(assets)\n\nprint(\"All assets loaded.\")<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">See <a href=\"https:\/\/create.roblox.com\/docs\/reference\/engine\/classes\/ContentProvider\">https:\/\/create.roblox.com\/docs\/reference\/engine\/classes\/ContentProvider<\/a> for more info<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Path Finding Service<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">[TODO]<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Leaderboard Service<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">[TODO]<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">HTTP Service<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">[TODO]<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Sound Service<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">[TODO]<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">MarketplaceService<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">[TODO]<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Other Things<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Instance Streaming<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Roblox can stream larger environments instead of loading it all at once. This is automatic but can be customised<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">[TODO: Expand on this section]<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Raycasting<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>-- raycast tool script\nlocal tool = script.Parent\nlocal handle = tool.Handle\n\nlocal params = RaycastParams.new()\nparams.FilterType = Enum.RaycastFilterType.Exclude\n\ntool.Activated:Connect(function()\n\tparams.FilterDescendantsInstances = {tool.Parent} -- excludes player's character's descendants from the raycast\n\tlocal origin = handle.Position\n\tlocal direction = handle.CFrame.LookVector\n\n\tlocal result = workspace:Raycast(origin, direction * 100, params)\n\tif result then\n\t\tprint(\"Hit instance:\", result.Instance.Name, \"at position:\", result.Position)\n\n\t\t-- visualizing the raycast\n\t\tlocal part = Instance.new(\"Part\")\n\t\tpart.Size = Vector3.new(0.05, 0.05, result.Distance)\n\t\tpart.Color = Color3.fromRGB(255, 255, 255)\n\t\tpart.Anchored = true\n\t\tpart.CanCollide = false\n\t\tpart.CFrame = CFrame.lookAt(origin, result.Position) * CFrame.new(0, 0, -result.Distance\/2)\n\t\tpart.Parent = workspace\n\telse\n\t\tprint(\"The ray hit nothing!\")\n\tend\nend)<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Teleporting<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>-- Teleport the player server side\nfunction TeleportTo(player, position)\n\tlocal character = player.Character\n\tif character then\n\t\tlocal primaryPart = character.PrimaryPart\n\t\tif primaryPart then\n\t\t\tprimaryPart.CFrame = CFrame.new(position)\n\t\tend\n\tend\t\nend<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Collision<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Parts that are anchored are not generally under control of the physics system so do not register touched events unless touched by an unanchored part. We can respond to a touch star \/ end events by connecting a function to the Touched function<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>local function onTouch(otherPart)\n\tprint(\"Touch started: \" .. otherPart.Name)\nend\n\nlocal function onTouchEnded(otherPart)\n\tprint(\"Touch ended: \" .. otherPart.Name)\nend\n\npart.Touched:Connect(onTouch)\npart.TouchEnded:Connect(onTouchEnded)<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Note that there are options to check if parts overlap in the WorldRoot API such as ArePartsTouchingOthers(), GetPartBoundsInBox(), GetPartBoundsInRadius(), GetPartsInPart(), Raycast() etc..<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Camera rotate with player<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Some games find it useful for the camera to align behind the player, e.g.:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>local UP_VECTOR = Vector3.new(0, 1, 0);\nRunService.Heartbeat:Connect(function(time: number, deltaTime: number)\n\tUpdateCamera(deltaTime)\nend)\n\nfunction UpdateCamera(dt)\n\t-- Get the camera to rotate with the player \n\tlocal part = self.Player.Character.PrimaryPart\n\tpart.CFrame = CFrame.fromMatrix(part.Position, self.Camera.CFrame.RightVector, UP_VECTOR);\nend<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Offsetting the camera<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Its offset useful to be able to offset the camera from the player for example have a shoulder cam set up, e.g.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>local humanoid = self.Player.Character.Humanoid\nif (humanoid) then\n\thumanoid.CameraOffset = Vector3.new(3, 0, 0)\nend<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Detecting tool changes<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Its possible to detect when the player changes tools server and client side, the same script can be used inside a server or local script with the script placed within the tool as child:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>local RunService = game:GetService(\"RunService\")\nlocal Tool = script.Parent\nlocal IsServer = RunService:IsServer()\n\nTool.Equipped:Connect(function()\n\tprint(\"GrenadeLauncher Equipped \" .. tostring(IsServer))\nend)\n\nTool.Unequipped:Connect(function()\n\tprint(\"GrenadeLauncher Unequipped \" .. tostring(IsServer))\nend)\n\n-- Only Activated() does not run server side\nTool.Activated:Connect(function()\n\tprint(\"GrenadeLauncher Activated \" .. tostring(IsServer))\nend)<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Note that the script does not need to be placed within the tool, it can be hosted elsewhere such as in a module however you will need to find the tool within the players backpack in order to access it:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>local Tool = player.Character:FindFirstChildOfClass(\"Tool\")<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Note that for the above to work it requires that the Player and its Character must already be loaded<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Plugins<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">[TODO]<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">See <a href=\"https:\/\/create.roblox.com\/docs\/studio\/plugins\">https:\/\/create.roblox.com\/docs\/studio\/plugins<\/a> for more info<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Overview This document is an attempt to summarise important parts of the Roblox API from a Unity game developers perspective. Note that this document is living and in progress so is incomplete and may contain errors. Data Model Objects Every Object inherets from the Instance class. 3D Building Blocks BasePart is the core class for [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-4654","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"http:\/\/www.drmop.com\/index.php\/wp-json\/wp\/v2\/pages\/4654","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/www.drmop.com\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"http:\/\/www.drmop.com\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"http:\/\/www.drmop.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.drmop.com\/index.php\/wp-json\/wp\/v2\/comments?post=4654"}],"version-history":[{"count":2,"href":"http:\/\/www.drmop.com\/index.php\/wp-json\/wp\/v2\/pages\/4654\/revisions"}],"predecessor-version":[{"id":4657,"href":"http:\/\/www.drmop.com\/index.php\/wp-json\/wp\/v2\/pages\/4654\/revisions\/4657"}],"wp:attachment":[{"href":"http:\/\/www.drmop.com\/index.php\/wp-json\/wp\/v2\/media?parent=4654"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}