Community CreationsCheck out these amazing showcase experiences created members of the community!
diff --git a/content/en-us/art/overview-studio.md b/content/en-us/art/overview-studio.md
index f012f084b..4eecac996 100644
--- a/content/en-us/art/overview-studio.md
+++ b/content/en-us/art/overview-studio.md
@@ -294,7 +294,7 @@ For more information, see [Terrain](../parts/terrain.md).
Lighting can be categorized into the following:
-- **Global lighting** - Refers to the luminescence from either the sun or moon in an outdoor environment. You can set the properties of your global lighting by adjusting the Lighting service. For additional hands-on instructions on adjusting global lighting, see the [Customize Global Lighting](../tutorials/core/building/customize-global-lighting.md) lesson of our Core Curriculum.
+- **Global lighting** - Refers to the luminescence from either the sun or moon in an outdoor environment. You can set the properties of your global lighting by adjusting the Lighting service. For additional hands-on instructions on adjusting global lighting, see the [Customize Global Lighting](../tutorials/curriculums/core/building/customize-global-lighting.md) lesson of our Core Curriculum.
- **Local lighting** - Refers to light sources placed within your experiences, such as pointlights, spotlights, and surface lights. You can modify lighting scenarios based on different interior rooms or sections of your experience by using one or more light sources.
For additional information on modifying your environment's lighting, see [Lighting](../environment/lighting.md).
diff --git a/content/en-us/assets/art/Shrine-Detailed.jpg b/content/en-us/assets/art/Shrine-Detailed.jpg
new file mode 100644
index 000000000..675ce3dda
--- /dev/null
+++ b/content/en-us/assets/art/Shrine-Detailed.jpg
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:62374eca806cec977d57b8d4f49b30af1f67f3976f7573f0da2fb6bdbf6fee99
+size 449663
diff --git a/content/en-us/assets/landing/get-started/Laser-Tag-Template.jpg b/content/en-us/assets/landing/get-started/Laser-Tag-Template.jpg
new file mode 100644
index 000000000..5f2f029db
--- /dev/null
+++ b/content/en-us/assets/landing/get-started/Laser-Tag-Template.jpg
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:f531f93e08c7dedce8f7e272a6966e7e2c7593f363ba4544fa55e688f65fa839
+size 99238
diff --git a/content/en-us/assets/landing/get-started/Laser-Tag-Template.png b/content/en-us/assets/landing/get-started/Laser-Tag-Template.png
deleted file mode 100644
index 86ad5950f..000000000
--- a/content/en-us/assets/landing/get-started/Laser-Tag-Template.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:9f53bb566092effdb40094a415d7ca4ab84ae7848fd564ea8326a875b29e0c6c
-size 85225
diff --git a/content/en-us/assets/landing/get-started/Racing-Detailed.jpg b/content/en-us/assets/landing/get-started/Racing-Detailed.jpg
new file mode 100644
index 000000000..37dba8337
--- /dev/null
+++ b/content/en-us/assets/landing/get-started/Racing-Detailed.jpg
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:e6c6f2cd857fa553609f4a4943aaf80803fb980617342d83174e008749f0ca20
+size 573171
diff --git a/content/en-us/assets/studio/properties/Folder-Sandboxed.png b/content/en-us/assets/studio/properties/Folder-Sandboxed.png
new file mode 100644
index 000000000..903251124
--- /dev/null
+++ b/content/en-us/assets/studio/properties/Folder-Sandboxed.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:867e75d39654a8d9ce199950166f073542fd9302a0ef8b6d29660626d2c4c860
+size 32593
diff --git a/content/en-us/cloud/open-cloud/usage-assets.md b/content/en-us/cloud/open-cloud/usage-assets.md
index 0abcb7e31..3d84737b2 100644
--- a/content/en-us/cloud/open-cloud/usage-assets.md
+++ b/content/en-us/cloud/open-cloud/usage-assets.md
@@ -118,7 +118,7 @@ Updating asset metadata using the **Update Asset** endpoint is not subject to th
Up to 30 seconds of duration.
Up to 4096x2160 resolution.
Up to 375 MB.
-
Currently, only English audio and text is allowed.
+
Currently, only English and/or Spanish audio and text is allowed.
Up to 3 uploads per month if you're 13+ and ID-verified.
diff --git a/content/en-us/get-started.md b/content/en-us/get-started.md
index b1ba1174f..6fafc771f 100644
--- a/content/en-us/get-started.md
+++ b/content/en-us/get-started.md
@@ -85,7 +85,7 @@ knowledge. Give them a try and add on to them when you're ready!
-
+
Laser TagBuild your own **first-person shooter** with customizable blasters, round systems, and modular building assets to reconfigure a high-quality arena!
@@ -103,7 +103,7 @@ knowledge. Give them a try and add on to them when you're ready!
-
+
RacingBuild your own **kart racer** with a customizable driving mechanics, checkpoints, and modular winding track pieces that you can restructure for countless courses!
@@ -133,7 +133,7 @@ that teaches you the skills you need to create and monetize your experiences.
CoreCore teaches you how to build a simple 3D platformer where players collect coins to trade for jump power.
-
+
@@ -151,7 +151,7 @@ that teaches you the skills you need to create and monetize your experiences.
Environmental ArtEnvironmental Art teaches you how to create a high-quality environment for a laser tag experience.
-
+
@@ -169,7 +169,7 @@ that teaches you the skills you need to create and monetize your experiences.
Gameplay ScriptingGameplay Scripting teaches you how to organize and implement the scripting logic for large, complex project.
-
+
diff --git a/content/en-us/production/promotion/referral-system.md b/content/en-us/production/promotion/referral-system.md
new file mode 100644
index 000000000..9ed960177
--- /dev/null
+++ b/content/en-us/production/promotion/referral-system.md
@@ -0,0 +1,134 @@
+---
+title: Player Referral System
+description: Generate shareable referral links that allow players to invite friends to join them inside an experience.
+---
+
+
+This feature is still in beta. If you'd like to provide Roblox with feedback about this feature, join the [User Acquisition Referrals](https://www.guilded.gg/i/kbQ4Po42) Guilded group.
+
+
+The referral system encourages existing players to bring new players into your experience, increasing player retention and overall engagement. Players can access and share referral links from [player invite prompts](./invite-prompts.md) or directly from the default in-experience invite menu.
+
+As a developer, you can use these shareable referral links to:
+
+- Track which players have successfully invited other players into your experience.
+- Track which players have joined your experience using a referral link invitation from another player.
+- Create and distribute rewards to both inviters and invitees.
+
+To implement a referral system, [set up a referral event](#set-up-a-referral-event) and [create referral rewards](#grant-referral-rewards). The `ReferredByPlayerId` property of `Class.Player:GetJoinData()|GetJoinData()` automatically populates for all types of invitations and gives you access to the user ID of the referring player. You can then access this data in the `Players.PlayerAdded` event to identify the inviter and grant rewards to the inviter and the invitee.
+
+```lua
+function onPlayerAdded(player)
+
+ local referredByPlayerId = player:GetJoinData().ReferredByPlayerId
+
+ local referrerEvent: RemoteEvent = ReplicatedStorage:FindFirstChild("ReferralReceivedEvent")
+ referrerEvent:FireClient(player, referredByPlayerId)
+end
+
+Players.PlayerAdded:Connect(onPlayerAdded)
+```
+
+## Set Up a Referral Event
+
+To set up a referral event:
+
+1. Set up a `RemoteEvent` in `ReplicatedStorage` to create a remote event to communicate with the client when a referral is received.
+2. Retrieve the inviter's user ID using `ReferredByPlayerId` to track player joins and handle the referral logic in your server-side script during the `Players.PlayerAdded` event.
+
+```lua
+local Players = game:GetService("Players")
+local ReplicatedStorage = game:GetService("ReplicatedStorage")
+
+-- Create or get the RemoteEvent for handling referrals
+local referrerEvent: RemoteEvent = ReplicatedStorage:FindFirstChild("ReferralReceivedEvent")
+
+-- Function that triggers when a player joins
+function onPlayerAdded(player)
+ local joinData = player:GetJoinData()
+ local referredByPlayerId = joinData.ReferredByPlayerId
+
+ -- Check if the player was invited through a referral
+ if referredByPlayerId then
+ -- Fire the referral event to the client, passing the inviter's ID
+ referrerEvent:FireClient(player, referredByPlayerId)
+
+ -- Additional logic for rewarding inviter and invitee can be added here
+ -- e.g., rewardReferrer(referredByPlayerId)
+ -- e.g., rewardInvitee(player)
+ end
+end
+
+-- Connect the function to the PlayerAdded event
+Players.PlayerAdded:Connect(onPlayerAdded)
+```
+
+## Grant Referral Rewards
+
+To encourage participation, grant rewards to both inviters and invitees. For example, you can give inviters a badge or in-experience currency when their friend joins the experience, and give invitees a welcome reward for joining the experience through a referral link.
+
+```lua
+local Players = game:GetService("Players")
+local ReplicatedStorage = game:GetService("ReplicatedStorage")
+
+-- Create or get the RemoteEvent for handling referrals
+local referrerEvent: RemoteEvent = ReplicatedStorage:FindFirstChild("ReferralReceivedEvent")
+
+-- Function that triggers when a player joins
+function onPlayerAdded(player)
+ local joinData = player:GetJoinData()
+ local referredByPlayerId = joinData.ReferredByPlayerId
+
+ -- Check if the player was invited through a referral
+ if referredByPlayerId then
+ -- Fire the referral event to the client, passing the inviter's ID
+ referrerEvent:FireClient(player, referredByPlayerId)
+
+ -- Reward the inviter
+ function rewardReferrer(referrerId)
+ local referrerPlayer = Players:GetPlayerByUserId(referrerId)
+ if referrerPlayer then
+ -- Grant the inviter their reward
+ -- Example: referrerPlayer.leaderstats.Coins.Value += 100
+ end
+ end
+
+ -- Reward the invitee
+ function rewardInvitee(player)
+ -- Grant the invitee their reward
+ -- Example: player.leaderstats.WelcomeBonus.Value += 50
+ end
+ end
+end
+
+-- Connect the function to the PlayerAdded event
+Players.PlayerAdded:Connect(onPlayerAdded)
+```
+
+## Manage Abuse Prevention
+
+You can implement safeguards to prevent players from exploiting the referral system.
+
+- Offer one-time rewards to track invitees and make sure they're only rewarded once.
+- Introduce a cooldown period before an inviter can submit another referral.
+- Monitor unusual activity and implement corrective measures like banning users or canceling rewards.
+
+```lua
+-- Table to track players who have already been referred
+local referredPlayers = {}
+
+function onPlayerAdded(player)
+ local joinData = player:GetJoinData()
+ local referredByPlayerId = joinData.ReferredByPlayerId
+
+ -- Check if the player was invited and has not already used a referral
+ if referredByPlayerId and not referredPlayers[player.UserId] then
+ -- Mark the player as referred
+ referredPlayers[player.UserId] = true
+
+ -- Reward inviter and invitee
+ rewardReferrer(referredByPlayerId)
+ rewardInvitee(player)
+ end
+end
+```
diff --git a/content/en-us/projects/assets/index.md b/content/en-us/projects/assets/index.md
index 2a53009bb..cc5bd510d 100644
--- a/content/en-us/projects/assets/index.md
+++ b/content/en-us/projects/assets/index.md
@@ -102,11 +102,15 @@ Within Studio, you can convert single assets or asset hierarchies into **package
For more information, see [Packages](../../projects/assets/packages.md).
-## Asset Format Strings
+## Asset URIs
-Assets are reflected through formatted strings, each of which points to an online file or a file saved to the client's device. The basic structure is a **protocol** followed by `://` and a **string** that varies according to the protocol.
+Assets and other content stored outside of the current place are identified through **Uniform Resource Identifiers** (URIs) which are formatted strings that point to a file stored online, within the Roblox application package, or saved to the client's device.
-
+The basic structure is a **scheme** followed by `://` and a **path** that varies according to the scheme.
+
+
+
+The Roblox engine supports several custom URI schemes for referencing content stored on the platform.
### rbxassetid
diff --git a/content/en-us/reference/engine/classes/AssetService.yaml b/content/en-us/reference/engine/classes/AssetService.yaml
index 38bba85cf..4e77d9685 100644
--- a/content/en-us/reference/engine/classes/AssetService.yaml
+++ b/content/en-us/reference/engine/classes/AssetService.yaml
@@ -18,8 +18,14 @@ deprecation_message: ''
properties: []
methods:
- name: AssetService:CreateEditableImage
- summary: ''
- description: ''
+ summary: |
+ Creates a new `Class.EditableImage`.
+ description: |
+ Creates a new `Class.EditableImage`. By default, the resolution
+ is set at 512×512 but it can be specified via the returned object's
+ `Class.EditableImage.Size` parameter. If the device‑specific editable
+ memory budget is exhausted, creation will fail and this method will return
+ `nil`.
code_samples: []
parameters: []
returns:
@@ -32,8 +38,13 @@ methods:
capabilities: []
writeCapabilities: []
- name: AssetService:CreateEditableMesh
- summary: ''
- description: ''
+ summary: |
+ Creates a new, empty `Class.EditableMesh`.
+ description: |
+ Creates a new, empty `Class.EditableMesh`. Vertices,
+ triangles and their attributes can be added dynamically to it.
+ If the device‑specific editable memory budget is exhausted,
+ creation will fail and this method will return `nil`.
code_samples: []
parameters: []
returns:
@@ -54,6 +65,8 @@ methods:
texture. Non-asset texture IDs such as `rbxthumb://` are supported. If
using an image asset, it must be associated with and/or owned by a creator
of the experience, or it must have been created inside the experience.
+ If the device-specific editable memory budget is exhausted, creation
+ will fail and this method will return `nil`.
code_samples: []
parameters:
- name: textureId
@@ -78,7 +91,13 @@ methods:
content ID.
description: |
Returns a new `Class.EditableMesh` instance created from an existing mesh
- content ID.
+ content ID. By default a `Class.EditableMesh` created from this method will
+ be fixed size such that mesh data can only be modified, not added nor removed.
+ A fixed size `Class.EditableMesh` consumes less memory and should be preferred
+ when possible.
+
+ If the device-specific editable memory budget is exhausted, creation
+ will fail and this method will return `nil`.
code_samples: []
parameters:
- name: meshId
diff --git a/content/en-us/reference/engine/classes/EditableMesh.yaml b/content/en-us/reference/engine/classes/EditableMesh.yaml
index a960b4df6..c18444ccd 100644
--- a/content/en-us/reference/engine/classes/EditableMesh.yaml
+++ b/content/en-us/reference/engine/classes/EditableMesh.yaml
@@ -5,28 +5,36 @@ memory_category: Instances
summary: |
Instance which allows for the runtime creation and manipulation of meshes.
description: |
- `Class.EditableMesh` changes the applied visual mesh when parented to a
+ `EditableMesh` changes the applied visual mesh when linked to a
`Class.MeshPart`, allowing for querying and modification of the mesh both in
Studio and in experience.
- An `Class.EditableMesh` can be created from an existing mesh ID using
- `Class.AssetService:CreateEditableMeshAsync()`, or a blank
- `Class.EditableMesh` can be created with `Datatype.Instance.new()`. It can
- then be displayed, modified, and its collision model updated. Not all of the
- steps are necessary; for example, you might want to create an
- `Class.EditableMesh` just to raycast without ever displaying it.
+ An `EditableMesh` can be created from an existing 'DataType.Content' of a
+ 'Class.MeshPart' or a mesh ID using `Class.AssetService:CreateEditableMeshAsync()`,
+ or a blank `EditableMesh` can be created with `Class.AssetService:CreateEditableMesh()`.
+ It can then be displayed, modified, and its collision model updated. Not all
+ of the steps are necessary; for example, you might want to create an
+ `EditableMesh` just to raycast without ever displaying it.
+
+ An `EditableMesh` is displayed when it's linked to a new `Class.MeshPart`,
+ through `Class.AssetService:CreateMeshPartAsync()`. You can create more `Class.MeshPart`
+ instances that reference the same `EditableMesh` content, or link to an existing
+ `Class.MeshPart` through `Class.MeshPart:ApplyMesh()`.
+
+ Calling `Class.AssetService:CreateMeshPartAsync()` will recalculate collision
+ and fluid geometry with any edits and update the existing `Class.MeshPart`. It
+ is generally recommended to do this at the end of a conceptual edit operation.
+ `Class.MeshPart:ApplyMesh()` will update the colission and fluid geometry of
+ the target `Class.MeshPart`.
- An `Class.EditableMesh` is displayed when it's parented to a `Class.MeshPart`,
- but only the part's appearance changes while the collision model remains the
- same.
#### Stable Vertex/Face IDs
- Many `Class.EditableMesh` methods take **vertex**, **normal**, **UV**,
+ Many `EditableMesh` methods take **vertex**, **normal**, **UV**,
**color** and **face** IDs. These are represented as integers in Luau but they
require some special handling. The main difference is that IDs are stable and
they remain the same even if other parts of the mesh change. For example, if
- an `Class.EditableMesh` has five vertices `{1, 2, 3, 4, 5}` and you remove
+ an `EditableMesh` has five vertices `{1, 2, 3, 4, 5}` and you remove
vertex `4`, the new vertices will be `{1, 2, 3, 5}`.
Note that the IDs are not guaranteed to be in order and there may be holes in
@@ -53,6 +61,8 @@ description: |
example, this code will create a sharp cube:
```lua
+ local AssetService = game:GetService("AssetService")
+
-- Given 4 vertex IDs, adds a new normal and 2 triangles, making a sharp quad
local function addSharpQuad(eMesh, vid0, vid1, vid2, vid3)
local nid = eMesh:AddNormal() -- This creates a normal ID which is automatically computed
@@ -66,7 +76,7 @@ description: |
-- Makes a cube with creased edges between the 6 sides
local function makeSharpCube()
- local eMesh = Instance.new("EditableMesh")
+ local eMesh = AssetService:CreateEditableMesh()
local v1 = eMesh:AddVertex(Vector3.new(0, 0, 0))
local v2 = eMesh:AddVertex(Vector3.new(1, 0, 0))
@@ -103,7 +113,7 @@ description: |
#### Limitations
- `Class.EditableMesh` currently has a limit of 60,000 vertices and 20,000
+ `EditableMesh` currently has a limit of 60,000 vertices and 20,000
triangles. Attempting to add too many vertices or triangles will cause an
error.
code_samples: []
diff --git a/content/en-us/reference/engine/classes/Instance.yaml b/content/en-us/reference/engine/classes/Instance.yaml
index 5ad4d4c56..a42c6b33f 100644
--- a/content/en-us/reference/engine/classes/Instance.yaml
+++ b/content/en-us/reference/engine/classes/Instance.yaml
@@ -56,8 +56,14 @@ properties:
capabilities: []
writeCapabilities: []
- name: Instance.Capabilities
- summary: ''
- description: ''
+ summary: |
+ The set of capabilities allowed to be used for scripts inside this container.
+ description: |
+ The set of capabilities allowed to be used for scripts inside this instance.
+ For the capabilities to take effect, `Class.Instance.Sandboxed` property has to be enabled.
+
+ This property is used by an experimental feature. See [Script Capabilities](../../../scripting/capabilities.md) page for
+ further details.
code_samples: []
type: SecurityCapabilities
tags: []
@@ -235,8 +241,15 @@ properties:
capabilities: []
writeCapabilities: []
- name: Instance.Sandboxed
- summary: ''
- description: ''
+ summary: |
+ Turns the instance to be a Sandboxed Container.
+ description: |
+ Turns the instance to be a Sandboxed Container.
+ Sandboxed Containers are an experimental feature which limits the actions
+ that scripts inside a particular container can perform.
+
+ See [Script Capabilities](../../../scripting/capabilities.md) page for
+ further details.
code_samples: []
type: bool
tags:
diff --git a/content/en-us/reference/engine/classes/Player.yaml b/content/en-us/reference/engine/classes/Player.yaml
index 3247a7aab..81bd2a8dc 100644
--- a/content/en-us/reference/engine/classes/Player.yaml
+++ b/content/en-us/reference/engine/classes/Player.yaml
@@ -1163,6 +1163,11 @@ methods:
number
The Class.DataModel.PlaceId of the place the Player teleported from. Only present if the player teleports to the current place and a server calls the teleport function.
+
+
ReferredByPlayerId
+
number
+
The Class.Player.UserId of the player who invited the current player to the experience. Use this data to identify the referrer and trigger reward logic.
+
Members
array
diff --git a/content/en-us/reference/engine/datatypes/Content.yaml b/content/en-us/reference/engine/datatypes/Content.yaml
index 39277d098..8967e17b1 100644
--- a/content/en-us/reference/engine/datatypes/Content.yaml
+++ b/content/en-us/reference/engine/datatypes/Content.yaml
@@ -1,73 +1,99 @@
name: Content
type: datatype
summary: |
- A formatted string with a specific structure to reference some form of
- content.
+ Represents a reference to asset content stored externally or as an object within the place.
description: |
- Assets and other content are reflected through formatted strings, each of
- which points to an online file or a file saved to the client's device. The
- basic structure is a **protocol** followed by `://` and a **string** that
- varies according to the protocol.
-
- `[Protocol]://[String]`
-
-
Loads a temporary asset. Often generated by `Class.File:GetTemporaryId()`.
-
rbxtemp://1
-
-
-
https/http
-
A website URL
-
Fetches content from a website using a URL.
-
https://www.roblox.com/asset/?id=9723979220
-
-
-
-
- For further guidance on using content, see
- [Asset Format Strings](../../../projects/assets/index.md#asset-format-strings).
+ The `Content` data type represents a reference to asset content stored externally or as an object
+ within the place, wrapping a single value of one of the supported `Enum.ContentSourceType` values.
code_samples:
tags: []
deprecation_message: ''
-constructors: []
-constants: []
-properties: []
+constructors:
+ - name: Content.fromUri
+ summary: |
+ Returns a new `Content` with an [asset URI](../../../projects/assets/index.md#asset-uris) `string` value referencing content external to the place.
+ description: |
+ Returns a new `Content` with an [asset URI](../../../projects/assets/index.md#asset-uris) `string` value referencing content external to the place.
+
+ `Datatype.Content.SourceType` will be `Enum.ContentSourceType|Uri`, and `Datatype.Content.Uri` will contain a non‑`nil` `string` value.
+
+ If `uri` is empty, `Datatype.Content.none` will be returned instead.
+ parameters:
+ - name: uri
+ type: string
+ default:
+ summary: |
+ The [asset URI](../../../projects/assets/index.md#asset-uris) string.
+ code_samples: []
+ tags: []
+ deprecation_message: ''
+ - name: Content.fromObject
+ summary: |
+ Returns a new `Content` with a strong reference to an `Class.Object`.
+ description: |
+ Returns a new `Content` with a strong reference to an `Class.Object`.
+
+ `Datatype.Content.SourceType` will be `Enum.ContentSourceType|Object`, and `Datatype.Content.Object` will contain a non‑`nil` `Class.Object` reference.
+
+ `Datatype.Content.Object` references are **strong** references that hold **shared ownership** of the `Class.Object`. Any `Datatype.Content.Object` reference will extend the lifetime of that `Class.Object` and prevent it from being garbage collected.
+
+ Throws if `object` is `nil`.
+ parameters:
+ - name: object
+ type: Object
+ default:
+ summary: |
+ The `Class.Object` to reference.
+ code_samples: []
+ tags: []
+ deprecation_message: ''
+constants:
+ - name: Content.none
+ type: Content
+ summary: |
+ An empty `Content` value with `Datatype.Content.SourceType` of `Enum.ContentSourceType|None`.
+ description: |
+ An empty `Content` value with `Datatype.Content.SourceType` of `Enum.ContentSourceType|None`.
+ code_samples: []
+ tags: []
+ deprecation_message: ''
+properties:
+ - name: Content.none
+ type: Content
+ summary: |
+ An empty `Content` value with `Datatype.Content.SourceType` of `Enum.ContentSourceType|None`.
+ description: |
+ An empty `Content` value with `Datatype.Content.SourceType` of `Enum.ContentSourceType|None`.
+ code_samples: []
+ tags: []
+ deprecation_message: ''
+ - name: SourceType
+ type: Enum.ContentSourceType
+ summary: |
+ The source type of the contained value.
+ description: |
+ The source type of the contained value. Indicates which property contains a non‑`nil` value.
+ code_samples: []
+ tags: []
+ deprecation_message: ''
+ - name: Uri
+ type: string?
+ summary: |
+ A URI `string` if `Datatype.Content.SourceType` is `Enum.ContentSourceType|Uri`, otherwise `nil`.
+ description: |
+ A URI `string` if `Datatype.Content.SourceType` is `Enum.ContentSourceType|Uri`, otherwise `nil`.
+ code_samples: []
+ tags: []
+ deprecation_message: ''
+ - name: Object
+ type: Object?
+ summary: |
+ A reference to a non-`nil` `Class.Object` if `Datatype.Content.SourceType` is `Enum.ContentSourceType|Object`, otherwise `nil`.
+ description: |
+ A reference to a non-`nil` `Class.Object` if `Datatype.Content.SourceType` is `Enum.ContentSourceType|Object`, otherwise `nil`.
+ code_samples: []
+ tags: []
+ deprecation_message: ''
methods:
functions:
math_operations:
diff --git a/content/en-us/reference/engine/enums/ContentSourceType.yaml b/content/en-us/reference/engine/enums/ContentSourceType.yaml
index 84ba238f7..ef4cbd657 100644
--- a/content/en-us/reference/engine/enums/ContentSourceType.yaml
+++ b/content/en-us/reference/engine/enums/ContentSourceType.yaml
@@ -1,23 +1,28 @@
name: ContentSourceType
type: enum
-summary: ''
-description: ''
+summary: |
+ The source type of a `Datatype.Content` value.
+description: |
+ The source type of `Datatype.Content` value. Indicates which properties of a `Datatype.Content` contain the referenced content.
code_samples: []
tags: []
deprecation_message: ''
items:
- name: None
- summary: ''
+ summary: |
+ Empty value with no source type. Does not reference any content or hold any non‑`nil` value.
value: 0
tags: []
deprecation_message: ''
- name: Uri
- summary: ''
+ summary: |
+ An [asset URI](../../../projects/assets/index.md#asset-uris) `string` value contained in `DataType.Content.Uri`.
value: 1
tags: []
deprecation_message: ''
- name: Object
- summary: ''
+ summary: |
+ A non-`nil` `Class.Object` reference contained in `DataType.Content.Object`.
value: 2
tags: []
deprecation_message: ''
diff --git a/content/en-us/scripting/capabilities.md b/content/en-us/scripting/capabilities.md
new file mode 100644
index 000000000..132d8b87c
--- /dev/null
+++ b/content/en-us/scripting/capabilities.md
@@ -0,0 +1,268 @@
+---
+title: Script Capabilities
+description: Script Capabilities is a system that controls which actions scripts can perform.
+---
+
+
+This page describes a feature that is still experimental and is available as a client beta. Features described here might undergo additional changes based on developer feedback and/or bug fixes.
+
+
+Script Capabilities is a system that offers control over actions that scripts can perform inside the `Class.DataModel` subtree. It provides better control over experience scripts rather than being an "all or nothing" system where any script can do anything that other scripts can.
+
+- This system lets you limit what models taken from the toolbox can do and makes it easier to include user-generated content inside the experience, even those that contain scripts.
+- It can also help ensure better security of experiences that allow players to run their own code, which is often executed in a restricted or emulated environment.
+- It can also be used to share libraries that restrict what they can do themselves. For example, a library providing additional math methods can be restricted to the smallest set of capabilities it needs so that other developers using that library don't have to validate the entire codebase to make sure it doesn't include malicious code.
+
+## Enabling Script Capabilities
+
+To enable this feature, change the `Class.Workspace.SandboxedInstanceMode|SandboxedInstanceMode` setting from `Default` to `Experimental` in the Explorer.
+
+When the client beta test is completed, this step will no longer be required.
+
+## Sandboxed Container
+
+This system introduces a concept of a **sandboxed container**.
+An instance of type `Class.Model`, `Class.Folder`, `Class.Script`, or descendants of any of those classes have a `Class.Instance.Sandboxed|Sandboxed` property available in the Studio **Properties** window, under the **Permissions** section.
+
+
+
+Enabling the `Class.Instance.Sandboxed|Sandboxed` property designates the instance as a sandboxed container inside the `Class.DataModel` tree, which limits the actions that the scripts inside that container can perform based on the set of values in the `Class.Instance.Capabilities|Capabilities` property.
+
+## Capabilities
+
+The `Capabilities` property is a set of values that control different aspects of execution, split into four groups:
+
+- **Execution control** - Specifies if a script can run on client or server
+- **Instance access control** - Specifies which `Class.DataModel` parts a script can interact with
+- **Script functionality control** - Specifies which Luau functions scripts can call
+- **Engine API access control** - Specifies which parts of the Roblox Engine API can be used
+
+When a script attempts to perform an action that is not in the set of capabilities for the current execution state, an error is reported. Errors typically include the action being attempted, the target of an action, and the first capability that is missing, for example:
+
+```text
+The current thread cannot modify 'Workspace' (lacking capability AccessOutsideWrite)
+
+The current thread cannot call 'Clone' (lacking capability CreateInstances)
+
+The current thread cannot call 'GetSecret' (lacking capability Network)
+```
+
+### Execution Control
+
+This set includes two capabilities:
+
+- **RunClientScript** - `Class.LocalScript` or `Class.Script` with a `Class.BaseScript.RunContext|RunContext` value of `Enum.RunContext.Client|Client` is allowed to execute on the client
+- **RunServerScript** - `Class.Script` with a `Class.BaseScript.RunContext|RunContext` value of `Enum.RunContext.Server|Server` is allowed to execute on the server
+
+If the script is `Class.BaseScript.Enabled|Enabled`, but the capability corresponding to the location it attempts to start in is not available, a warning message is displayed in the **Output** window. If a script wasn't supposed to run in that context, disable or delete it.
+
+Note that `Class.ModuleScript|ModuleScripts` are not required to have these execution capabilities to be required.
+
+When a script fails to start because the execution control capability is missing, it is reported as a warning in the output, for example:
+
+```text
+Cannot start server script 'Script' (lacking capability RunServerScript)
+```
+
+### Instance Access Control
+
+This set includes only a single capability:
+
+- **AccessOutsideWrite** - Script is allowed to fetch and receive instances from outside the sandboxed container
+
+When the capability is not available, the script can only look up instances that are inside its own sandboxed container. For example, if the script is placed directly in the sandboxed container, `script.Parent.Parent` returns `nil`.
+
+Additionally, any Roblox API event that passes in an `Class.Instance` instead passes in `nil` for any `Class.Instance` outside the sandboxed container. For example, if the `Class.BasePart.Touched` is signalled by a touch from an instance outside the sandboxed container, the event is still received, but the argument is `nil`.
+
+Avoid setting this capability; sandboxing guarantees are weaker when scripts can interact with any instance in an experience.
+
+#### Access to Services
+
+Even without **AccessOutsideWrite**, scripts in the sandboxed container can still access to `game`, `workspace`, and services. This access is provided so that scripts can still call useful methods of those globals, like `Class.DataModel.GetService`, but access to their child instances is still validated.
+
+#### Internally Passed Instances
+
+If an instance is passed through a function call that doesn't go through Roblox APIs, the reference is preserved. However, if a `Class.ModuleScript` is passed in this way, it can't be required without **AccessOutsideWrite**. This is because the return of the `Class.ModuleScript` is often mutable and can be modified by a script in a sandboxed container.
+
+### Script Functionality Control
+
+This set of capabilities controls some general aspects of scripts:
+
+- **AssetRequire** - Script is allowed to call `Global.LuaGlobals.require` with an asset ID
+- **LoadString** - Script is allowed to call `Global.LuaGlobals.loadstring`
+- **ScriptGlobals** - Script has `Global.LuaGlobals.shared` and `Global.LuaGlobals._G` available
+- **CreateInstances** - Script can create new instances using `Datatype.Instance.new`, `Datatype.Instance.fromExisting`, or `Class.Instance:Clone`
+
+Keep in mind that default function restrictions still apply. Even if **LoadString** is enabled, the experience still has to turn enable it in `Class.ServerScriptService`, and it is still only available on the server.
+
+To create new instances, aside from **CreateInstances**, an additional Engine API capability providing access to that instance is required.
+
+### Engine API Access Control
+
+This last group of capabilities controls script access to various Engine APIs:
+
+- **Basic** - Access to simple instances and essential building blocks
+- **Audio** - Access to instances related to audio APIs
+- **DataStore** - Access to data store and memory store APIs
+- **Network** - Access to HTTP networking APIs
+- **Physics** - Access to instances related to physics
+- **UI** - Access to instances related to user interfaces
+- **CSG**: access to instances and functions related to constructive solid geometry (CSG)
+- **Chat**: access to instances related to in-experience chat
+- **Animation**: access to instances related to animations
+- **Avatar**: access to instances related to avatars
+- **Input**: access to instances related to user input
+- **Environment**: access to instances related to the control of how the environment is displayed
+- **RemoteEvent**: access to instances for internal networking operations
+
+There are also instances that are available without any capabilities aside from being able to execute the scripts. These include the following `Class.HttpService` methods:
+
+- `Class.HttpService:JSONDecode()`
+- `Class.HttpService:JSONEncode()`
+- `Class.HttpService:GenerateGUID()`
+
+If an instance property or method is accessed without a required capability, an error is reported describing the missing capability.
+
+Finally, capabilities do not cover every instance in the Roblox engine today. Instances not listed in this section or the following one are not available for interaction from a sandboxed container and throw an error saying that an **Unassigned** capability is not available to the current script.
+
+An additional limitation is that `Global.LuaGlobals.getfenv` and `Global.LuaGlobals.setfenv` functions are not available for scripts in a sandboxed container.
+
+Only script access to instances is limited. The instances themselves can still exist and operate by themselves inside a sandboxed container. Lights still shine, user interfaces are still visible, and audio setups that are already wired play sounds.
+
+#### Engine API Capability Assignments
+
+
+This feature is currently in the experimental stage, so the assignments of the APIs are not final. The capability of each instance is displayed on the documentation page for that instance.
+
+
+Here is the list of instances and methods (if different from the instance capability) for each Engine API capability:
+
+- **Basic**
+ - `Class.Attachment`
+ - `Class.Beam`, `Class.ParticleEmitter`, `Class.Smoke`, `Class.Sparkles`, `Class.Trail`
+ - `Class.SurfaceAppearance`, `Class.Decal`, `Class.FaceInstance`, `Class.Texture`
+ - `Class.Light`, `Class.PointLight`, `Class.SpotLight`
+ - `Class.Part`, `Class.MeshPart`, `Class.CornerWedgePart`, `Class.TriangleMeshPart`, `Class.TrussPart`, `Class.WedgePart`
+ - `Class.FloatCurve`, `Class.RotationCurve`, `Class.EulerRotationCurve`, `Class.Vector3Curve`
+ - `Class.Tween`, `Class.TweenService`
+ - `Class.Wire`
+ - `Class.WorldModel`
+ - `Class.CollectionService`, `Class.Debris`, `Class.RunService`
+
+- **Audio**
+ - `Class.AudioAnalyzer`, `Class.AudioChorus`, `Class.AudioCompressor`, `Class.AudioDistortion`, `Class.AudioEcho`, `Class.AudioEqualizer`, `Class.AudioFader`, `Class.AudioFader`, `Class.AudioFilter`, `Class.AudioFlanger`, `Class.AudioLimiter`, `Class.AudioPitchShifter`, `Class.AudioReverb`
+ - `Class.AudioEmitter`, `Class.AudioPlayer`
+ - `Class.AudioDeviceOutput`, `Class.AudioListener`
+
+- **DataStore**
+ - `Class.DataStore`, `Class.OrderedDataStore`, `Class.GlobalDataStore`
+ - `Class.DataStoreService`, `Class.MemoryStoreService`
+ - `Class.DataStoreGetOptions`, `Class.DataStoreIncrementOptions`, `Class.DataStoreInfo`, `Class.DataStoreKey`, `Class.DataStoreKeyInfo`, `Class.DataStoreObjectVersionInfo`, `Class.DataStoreOptions`, `Class.DataStoreSetOptions`
+ - `Class.MemoryStoreHashMap`, `Class.MemoryStoreQueue`, `Class.MemoryStoreSortedMap`
+
+- **Network**
+ - `Class.HttpService:GetAsync`, `Class.HttpService:RequestAsync`, `Class.HttpService:PostAsync`, `Class.HttpService:UrlEncode`, `Class.HttpService:GetSecret`
+
+- **Physics**
+ - `Class.AlignOrientation`, `Class.AlignPosition`, `Class.DynamicRotate`
+ - `Class.JointInstance`, `Class.Motor`, `Class.Motor6D`
+ - `Class.AngularVelocity`, `Class.LinearVelocity`, `Class.LineForce`, `Class.Torque`, `Class.VectorForce`
+ - `Class.Weld`
+ - `Class.Constraint`, `Class.BallSocketConstraint`, `Class.CylindricalConstraint`, `Class.HingeConstraint`, `Class.NoCollisionConstraint`, `Class.PlaneConstraint`, `Class.PrismaticConstraint`, `Class.RigidConstraint`, `Class.RodConstraint`, `Class.RopeConstraint`, `Class.SlidingBallConstraint`, `Class.SpringConstraint`, `Class.TorsionSpringConstraint`, `Class.UniversalConstraint`, `Class.WeldConstraint`
+
+- **UI**
+ - `Class.BasePlayerGui`, `Class.PlayerGui`, `Class.BillboardGui`, `Class.GuiBase`, `Class.GuiBase2d`, `Class.GuiBase3d`, `Class.LayerCollector`, `Class.ScreenGui`, `Class.SurfaceGui`, `Class.SurfaceGuiBase`, `Class.UIBase`
+ - `Class.CanvasGroup`, `Class.Frame`, `Class.ScrollingFrame`
+ - `Class.GuiButton`, `Class.GuiLabel`, `Class.GuiObject`, `Class.ImageButton`, `Class.ImageLabel`
+ - `Class.Dialog`, `Class.DialogChoice`, `Class.ProximityPrompt`
+ - `Class.TextBox`, `Class.TextButton`, `Class.TextFilterResult`, `Class.TextFilterTranslatedResult`, `Class.TextLabel`, `Class.TextService`, `Class.GetTextBoundsParams`
+ - `Class.Path2D`
+ - `Class.UIComponent`, `Class.UICorner`, `Class.UIDragDetector`, `Class.UIFlexItem`, `Class.UIGradient`, `Class.UIGridLayout`, `Class.UIGridStyleLayout`, `Class.UILayout`, `Class.UIListLayout`, `Class.UIPadding`, `Class.UIPageLayout`, `Class.UIScale`, `Class.UIStroke`, `Class.UITableLayout`
+ - `Class.UIConstraint`, `Class.UIAspectRatioConstraint`, `Class.UISizeConstraint`, `Class.UITextSizeConstraint`
+ - `Class.VideoFrame`, `Class.ViewportFrame`
+
+- **CSG**
+ - `Class.GeometryService`
+ - `Class.BasePart` methods: `Class.BasePart:IntersectAsync`, `Class.BasePart:SubtractAsync`, `Class.BasePart:UnionAsync`
+ - `Class.IntersectOperation` (also requires **Basic**), `Class.NegateOperation` (also requires **Basic**), `Class.PartOperation` (also requires **Basic**), `Class.UnionOperation` (also requires **Basic**)
+
+- **Chat**
+ - `Class.BubbleChatConfiguration`, `Class.BubbleChatMessageProperties`
+ - `Class.ChannelTabsConfiguration`
+ - `Class.ChatInputBarConfiguration`, `Class.ChatWindowConfiguration`, `Class.ChatWindowMessageProperties`
+ - `Class.TextChannel`, `Class.TextChatCommand`, `Class.TextChatConfigurations`, `Class.TextChatMessage`, `Class.TextChatMessageProperties`, `Class.TextChatService`, `Class.TextSource`
+
+- **Animation**
+ - `Class.Bone` (also requires **Basic**)
+ - `Class.Animation`, `Class.AnimationClip`, `Class.AnimationClipProvider`, `Class.AnimationController`, `Class.AnimationRigData`, `Class.AnimationTrack`, `Class.Animator`
+ - `Class.CurveAnimation`
+ - `Class.FaceControls`, `Class.IKControl`
+ - `Class.Keyframe`, `Class.KeyframeMarker`, `Class.KeyframeSequence`
+ - `Class.MarkerCurve`
+ - `Class.PoseBase`, `Class.Pose`, `Class.NumberPose`
+
+- **Avatar**
+ - `Class.Accessory`, `Class.AccessoryDescription`
+ - `Class.Accoutrement`, `Class.Clothing`, `Class.Shirt`, `Class.Pants`
+ - `Class.BaseWrap`, `Class.WrapDeformer`, `Class.WrapLayer`, `Class.WrapTarget`
+ - `Class.BodyColors`, `Class.BodyPartDescription`, `Class.CharacterAppearance`, `Class.ShirtGraphic`
+ - `Class.CharacterMesh`
+ - `Class.Humanoid`, `Class.HumanoidDescription`
+
+- **Input**
+ - `Class.GamepadService`, `Class.KeyboardService`, `Class.MouseService`
+ - `Class.ContextActionService`, `Class.TouchInputService`, `Class.UserInputService`
+ - `Class.InputObject`, `Class.Mouse`, `Class.PlayerMouse`
+
+- **Environment**
+ - `Class.Atmosphere`, `Class.Clouds`, `Class.Lighting`, `Class.Sky`
+ - `Class.BloomEffect`, `Class.BlurEffect`, `Class.ColorCorrectionEffect`, `Class.ColorGradingEffect`, `Class.DepthOfFieldEffect`, `Class.PostEffect`, `Class.SunRaysEffect`
+
+- **RemoteEvent**
+ - `Class.BaseRemoteEvent`, `Class.RemoteEvent`, `Class.UnreliableRemoteEvent`
+ - `Class.RemoteFunction`
+
+## Interactions Between Containers
+
+### Nested Containers
+
+When one sandboxed container is nested inside another one, the instances of the inner container are accessible to the outer one.
+
+Capabilities of the inner container are limited by the capabilities of the outer one.
+For example, if the outer container has capabilities of **Basic**, **Audio** and **CSG**, while the inner container has **Basic** and **Network**, only **Basic** capabilities are available to the inner container at runtime.
+
+If there are no capabilities in common between the inner and outer containers, the resulting capability set is empty.
+
+### Bindable Functions and Events
+
+`Class.BindableEvent` and `Class.BindableFunction` provide the best way to communicate with the container or allow it to run callbacks with capabilities it itself is not allowed to use directly.
+
+When an event or a function is fired, connections are executed in the context of the function that registered them. This means that if the event or function callback is registered by the sandboxed container, it is called with the capabilities of that container. If the callback is registered by the code outside, when sandboxed container scripts invoke them, they execute your functions with capabilities available to your functions.
+
+It is important to note that even with the **AccessOutsideWrite** capability, scripts in sandboxed containers cannot invoke events or functions outside their containers if they have a larger capability set than the container itself.
+
+### Module Require
+
+Inner `Class.ModuleScript|ModuleScripts` can be required by the sandboxed container as usual.
+However, if the target instance is outside the container, the `Class.ModuleScript` can only be required if the capability set that is available to it is smaller or equal to the capabilities available to the container.
+
+This limitation does not apply to **RunClientScript** and **RunServerScript** capabilities. If the `Class.ModuleScript` is placed in a container with only **RunClientScript** but is required from a script that has the **RunServerScript** capability, it is allowed to succeed and run those functions on the server.
+
+### Directly Called Functions
+
+If a `Class.ModuleScript` in a sandboxed container is required from outside the container, some of the protections are not available. In particular, the target function is able to access all instances available to the caller. If the caller is not in a sandboxed container, the call acts as if **AccessOutsideWrite** is available to it.
+
+Other capability restrictions still apply. If you have a **DataStore** access capability, but the target module does not, it is unable to call `Class.DataStore` methods. However, if you pass your own function working with `Class.DataStore`, the target can run it during that call.
+If the target schedules a thread using methods like those from `Library.task`, those threads lose the ability to call that function.
+
+Instances can be passed to the target module or assigned to the module fields.
+
+If required, it is recommended to assign table members using `Global.LuaGlobals.rawset` to avoid running `__index`/`__newindex` metamethods that might be set on the table.
+
+The overall recommendation is to communicate with `Class.BindableEvent` and `Class.BindableFunction` whenever possible.
+
+### Movement of Instances
+
+Most instances do not have restrictions on movement between containers. Script instances, however, can only be moved into a container that has the same set of capabilities or a subset of those capabilities.
+
+This means that sandboxed container with **AccessOutsideWrite** cannot just re-parent a script inside itself to outside and get more capabilities.
diff --git a/content/en-us/studio/microprofiler/modes.md b/content/en-us/studio/microprofiler/modes.md
index 5b01027bd..74eff041a 100644
--- a/content/en-us/studio/microprofiler/modes.md
+++ b/content/en-us/studio/microprofiler/modes.md
@@ -11,10 +11,11 @@ The most basic mode, **frame mode** shows a bar graph of frames flowing from the
-- Orange bars indicate "standard" frames where the **Jobs Wall Time** exceeds the **Render Wall Time**.
-- Blue bars indicate frames where the **Render Wall Time** exceeds the **Jobs Wall Time**.
+- Orange bars indicate frames where the **Jobs Wall Time** exceeds the **Render Wall Time**. In these frames, at least one of the worker threads, which do things like run scripts, calculate physics, and play animations, took longer to run than the main render thread.
- Blue bars are common when you run the MicroProfiler inside of Studio, but a large number of these frames in the Roblox client indicates a rendering bottleneck. Common causes are excessive object density, object movement, and lighting. See [Improving Performance](../../performance-optimization/improving.md#rendering).
+- Blue bars indicate frames where the **Render Wall Time** exceeds the **Jobs Wall Time**. In these frames, the main render thread took more time than any of the worker threads.
+
+ If the experience is not reaching your frame time goals and has a large number of blue frames, that indicates a rendering bottleneck. Common causes are excessive object density, object movement, and lighting. See [Improving Performance](../../performance-optimization/improving.md#rendering).
- Red bars indicate frames where two conditions are true:
diff --git a/content/en-us/tutorials/curriculums/core/building/apply-polished-assets.md b/content/en-us/tutorials/curriculums/core/building/apply-polished-assets.md
index ae939b483..cf2385ec3 100644
--- a/content/en-us/tutorials/curriculums/core/building/apply-polished-assets.md
+++ b/content/en-us/tutorials/curriculums/core/building/apply-polished-assets.md
@@ -1,7 +1,7 @@
---
title: Apply Polished Assets
description: Explains how to finish your scene by replacing simple parts with complex, imported models.
-prev: /tutorials/core/building/customize-global-lighting
+prev: /tutorials/curriculums/core/building/customize-global-lighting
comments: The links to the Materials and PBR Modeling guides must be replaced by a single link to the Environmental Art curriculum once that is published. The link at the end should also be changed to link to the next sets of tutorials.
---
@@ -1175,7 +1175,7 @@ To playtest your experience:
-Congratulations on completing the Core Curriculum! Now that you have experience creating a simple experience from start to finish, you can extend your project with new gameplay features or additional levels, explore Studio's additional [features](../../../platform.md), or follow additional tutorial curricula, such as the [Environmental Art Curriculum](../../environmental-art/index.md) that teaches you how to create a high-quality laser tag environment. Happy creating!
+Congratulations on completing the Core Curriculum! Now that you have experience creating a simple experience from start to finish, you can extend your project with new gameplay features or additional levels, explore Studio's additional [features](../../../../platform.md), or follow additional tutorial curricula, such as the [Environmental Art Curriculum](../../environmental-art/index.md) that teaches you how to create a high-quality laser tag environment. Happy creating!
We're interested in hearing from you about your experience following the Core Curriculum. If you have any questions, concerns, or additional feedback on the process, please comment on our [Core Curriculum Q&A](https://devforum.roblox.com/t/feedback-on-core-curriculum/2592219).
diff --git a/content/en-us/tutorials/curriculums/core/building/create-a-project.md b/content/en-us/tutorials/curriculums/core/building/create-a-project.md
index 9549b1a18..616647ec9 100644
--- a/content/en-us/tutorials/curriculums/core/building/create-a-project.md
+++ b/content/en-us/tutorials/curriculums/core/building/create-a-project.md
@@ -1,8 +1,8 @@
---
title: Create a Project
description: This part of the tutorial gets you started with creating a project.
-prev: /tutorials/core/
-next: /tutorials/core/building/create-an-environment-with-terrain
+prev: /tutorials/curriculums/core/
+next: /tutorials/curriculums/core/building/create-an-environment-with-terrain
---
In order to start the process of recreating the **Island Jump** [3D platformer experience](https://www.roblox.com/games/14238807008), you must create a project within Roblox Studio. A project is a collection of places, assets, settings and other resources that together represent an experience. You can either start a project from scratch, or you can start with one of Studio's templates to provide a basis for your environment and gameplay mechanics, such as:
diff --git a/content/en-us/tutorials/curriculums/core/building/create-an-environment-with-terrain.md b/content/en-us/tutorials/curriculums/core/building/create-an-environment-with-terrain.md
index 875f57436..5367d4801 100644
--- a/content/en-us/tutorials/curriculums/core/building/create-an-environment-with-terrain.md
+++ b/content/en-us/tutorials/curriculums/core/building/create-an-environment-with-terrain.md
@@ -1,8 +1,8 @@
---
title: Create an Environment with Terrain
description: Explains how to create the island where players spawn using Studio's terrain tools.
-next: /tutorials/core/building/greybox-a-playable-area
-prev: /tutorials/core/building/create-a-project
+next: /tutorials/curriculums/core/building/greybox-a-playable-area
+prev: /tutorials/curriculums/core/building/create-a-project
---
diff --git a/content/en-us/tutorials/curriculums/core/building/create-basic-visual-effects.md b/content/en-us/tutorials/curriculums/core/building/create-basic-visual-effects.md
index 4a4aa5c4d..2bcb17595 100644
--- a/content/en-us/tutorials/curriculums/core/building/create-basic-visual-effects.md
+++ b/content/en-us/tutorials/curriculums/core/building/create-basic-visual-effects.md
@@ -1,8 +1,8 @@
---
title: Create Basic Visual Effects
description: Explains how to create two different kinds of visual effect using particle emitters.
-prev: /tutorials/core/scripting/script-an-upgrade-button
-next: /tutorials/core/building/customize-global-lighting
+prev: /tutorials/curriculums/core/scripting/script-an-upgrade-button
+next: /tutorials/curriculums/core/building/customize-global-lighting
---
diff --git a/content/en-us/tutorials/curriculums/core/building/customize-global-lighting.md b/content/en-us/tutorials/curriculums/core/building/customize-global-lighting.md
index db0c598bd..6007b5355 100644
--- a/content/en-us/tutorials/curriculums/core/building/customize-global-lighting.md
+++ b/content/en-us/tutorials/curriculums/core/building/customize-global-lighting.md
@@ -1,8 +1,8 @@
---
title: Customize Global Lighting
description: Explains how to use global lighting settings to refine the look and feel of your experience.
-prev: /tutorials/core/building/create-basic-visual-effects
-next: /tutorials/core/building/apply-polished-assets
+prev: /tutorials/curriculums/core/building/create-basic-visual-effects
+next: /tutorials/curriculums/core/building/apply-polished-assets
---
diff --git a/content/en-us/tutorials/curriculums/core/building/greybox-a-playable-area.md b/content/en-us/tutorials/curriculums/core/building/greybox-a-playable-area.md
index 280fb1ef3..9b4b1ee80 100644
--- a/content/en-us/tutorials/curriculums/core/building/greybox-a-playable-area.md
+++ b/content/en-us/tutorials/curriculums/core/building/greybox-a-playable-area.md
@@ -1,8 +1,8 @@
---
title: Greybox a Playable Area
description: Explains how to use Studio's solid modeling tools to plan out the basic structure of your platforms.
-next: /tutorials/core/scripting/script-game-behavior
-prev: /tutorials/core/building/create-an-environment-with-terrain
+next: /tutorials/curriculums/core/scripting/script-game-behavior
+prev: /tutorials/curriculums/core/building/create-an-environment-with-terrain
---
@@ -124,7 +124,7 @@ To insert a cylinder part for your first platform:
-1. Navigate back to the **Home** tab, then use the **Move**, **Scale**, and **Rotate** tools to position, scale, and rotate your cylinder until it's a large, flat surface in the middle of your island. For more information on these tools, see [Manipulating Parts](../../../parts/index.md#manipulating-parts).
+1. Navigate back to the **Home** tab, then use the **Move**, **Scale**, and **Rotate** tools to position, scale, and rotate your cylinder until it's a large, flat surface in the middle of your island. For more information on these tools, see [Manipulating Parts](../../../../parts/index.md#manipulating-parts).
diff --git a/content/en-us/tutorials/curriculums/core/index.md b/content/en-us/tutorials/curriculums/core/index.md
index 64a4e7ee6..de8e62cd8 100644
--- a/content/en-us/tutorials/curriculums/core/index.md
+++ b/content/en-us/tutorials/curriculums/core/index.md
@@ -1,7 +1,7 @@
---
title: Core Curriculum
description: //
-next: /tutorials/core/building/create-a-project
+next: /tutorials/curriculums/core/building/create-a-project
hideInPageNavigation: true
hideBreadcrumbs: true
---
@@ -35,7 +35,7 @@ platforms until they reach a flare on top of the highest platform.
This course is intended for readers who are familiar
with general coding concepts but are new to Roblox. If you need help learning
how to code, try the [absolute basics](../../first-experience/index.md) of working in Studio and
-[coding fundamentals](../fundamentals/coding-1/coding-fundamentals.md).
+[coding fundamentals](../../fundamentals/coding-1/coding-fundamentals.md).
diff --git a/content/en-us/tutorials/curriculums/core/scripting/create-player-hazards.md b/content/en-us/tutorials/curriculums/core/scripting/create-player-hazards.md
index a25fde2dd..4ca0113aa 100644
--- a/content/en-us/tutorials/curriculums/core/scripting/create-player-hazards.md
+++ b/content/en-us/tutorials/curriculums/core/scripting/create-player-hazards.md
@@ -1,8 +1,8 @@
---
title: Create Player Hazards
description: Explains how to create player hazards by modifying player behavior and creating a player life cycle.
-next: /tutorials/core/scripting/script-an-upgrade-button
-prev: /tutorials/core/scripting/record-and-display-player-data
+next: /tutorials/curriculums/core/scripting/script-an-upgrade-button
+prev: /tutorials/curriculums/core/scripting/record-and-display-player-data
---
diff --git a/content/en-us/tutorials/curriculums/core/scripting/script-an-upgrade-button.md b/content/en-us/tutorials/curriculums/core/scripting/script-an-upgrade-button.md
index 846529a2a..4d4c9318f 100644
--- a/content/en-us/tutorials/curriculums/core/scripting/script-an-upgrade-button.md
+++ b/content/en-us/tutorials/curriculums/core/scripting/script-an-upgrade-button.md
@@ -1,8 +1,8 @@
---
title: Script an Upgrade Button
description: Explains how to communicate with the Roblox server and handle GUI interactions.
-prev: /tutorials/core/scripting/create-player-hazards
-next: /tutorials/core/building/create-basic-visual-effects
+prev: /tutorials/curriculums/core/scripting/create-player-hazards
+next: /tutorials/curriculums/core/building/create-basic-visual-effects
---
@@ -104,8 +104,8 @@ Now that **PlayerData** is able to track jump power, you need to implement logic
on the server to upgrade jump power from a player's client request.
The server and client can communicate through either
-[Remote Events](../../../scripting/events/remote.md#remote-events) or
-[Remote Functions](../../../scripting/events/remote.md#remote-callbacks).
+[Remote Events](../../../../scripting/events/remote.md#remote-events) or
+[Remote Functions](../../../../scripting/events/remote.md#remote-callbacks).
Remote events do not yield when they are fired and are appropriate for one-way
communication. Remote functions yield until they receive a reply, which allows
for two-way communication. In this case, the client needs to know if the server
diff --git a/content/en-us/tutorials/curriculums/core/scripting/script-game-behavior.md b/content/en-us/tutorials/curriculums/core/scripting/script-game-behavior.md
index 4e2db07eb..346fbd2ae 100644
--- a/content/en-us/tutorials/curriculums/core/scripting/script-game-behavior.md
+++ b/content/en-us/tutorials/curriculums/core/scripting/script-game-behavior.md
@@ -1,8 +1,8 @@
---
title: Create a Coin Collection Mechanic
description: Explains how to implement event-driven logic in an experience.
-next: /tutorials/core/scripting/record-and-display-player-data
-prev: /tutorials/core/building/greybox-a-playable-area
+next: /tutorials/curriculums/core/scripting/record-and-display-player-data
+prev: /tutorials/curriculums/core/building/greybox-a-playable-area
---
diff --git a/content/en-us/tutorials/curriculums/environmental-art/assemble-an-asset-library.md b/content/en-us/tutorials/curriculums/environmental-art/assemble-an-asset-library.md
index c357497d4..56b97b83a 100644
--- a/content/en-us/tutorials/curriculums/environmental-art/assemble-an-asset-library.md
+++ b/content/en-us/tutorials/curriculums/environmental-art/assemble-an-asset-library.md
@@ -1,8 +1,8 @@
---
title: Assemble an Asset Library
description: Explains how to import and configure your assets within a central location in your experience.
-next: /tutorials/environmental-art/construct-your-world
-prev: /tutorials/environmental-art/develop-polished-assets
+next: /tutorials/curriculums/environmental-art/construct-your-world
+prev: /tutorials/curriculums/environmental-art/develop-polished-assets
---
@@ -254,7 +254,7 @@ To demonstrate this concept, reference the following images that display the hit
Original Mesh
-
+
Pink Team
@@ -1471,7 +1471,7 @@ To exactly recreate the force field screen within the sample [Laser Tag](https:/
1. Select the **UIGradient** object within the duplicate label, then in the **Properties** window,
1. Set **Rotation** to `-45` to flip the image so that it nearly mirrors each other along the Y axis.
-
+
1. Modify **Transparency** to make the shimmer look more organic.
1. Click the **Transparency** property, then click the **⋯** button. A number sequence pop-up displays.
diff --git a/content/en-us/tutorials/curriculums/user-interface-design/index.md b/content/en-us/tutorials/curriculums/user-interface-design/index.md
index 79ee01a41..08251fc5f 100644
--- a/content/en-us/tutorials/curriculums/user-interface-design/index.md
+++ b/content/en-us/tutorials/curriculums/user-interface-design/index.md
@@ -1,7 +1,7 @@
---
title: User Inferface Design Curriculum
description: //
-next: /tutorials/user-interface-design/choose-an-art-style
+next: /tutorials/curriculums/user-interface-design/choose-an-art-style
hideInPageNavigation: true
hideBreadcrumbs: true
---
diff --git a/content/en-us/tutorials/curriculums/user-interface-design/wireframe-your-layouts.md b/content/en-us/tutorials/curriculums/user-interface-design/wireframe-your-layouts.md
index 794bdcf1d..8a42273a5 100644
--- a/content/en-us/tutorials/curriculums/user-interface-design/wireframe-your-layouts.md
+++ b/content/en-us/tutorials/curriculums/user-interface-design/wireframe-your-layouts.md
@@ -1,8 +1,8 @@
---
title: Wireframe Your Layouts
description: Explains how to greybox the laser tag environment using basic parts.
-next: /tutorials/user-interface-design/implement-designs-in-studio
-prev: /tutorials/user-interface-design/choose-an-art-style
+next: /tutorials/curriculums/user-interface-design/implement-designs-in-studio
+prev: /tutorials/curriculums/user-interface-design/choose-an-art-style
---
**Wireframing your layouts** is the process of designing the structure and flow of the information you want to communicate through UI in various workflows. This critical step of the tutorial allows you to iterate on the arrangement of your UI elements, discover pain points, and improve the player's experience before you invest time and resources on a problematic design that doesn't work for your experience.
@@ -132,7 +132,7 @@ When blocking in UI elements for your layouts, consider the following:
- Interacting with UI that are far from the bottom corners of some mobile and tablet devices is either uncomfortable or impossible. **Place interactive elements in easy-to-reach zones** near the natural resting position for thumbs.
- When players navigate through your environment, the 3D space can become distracting from your on-screen UI. **Test your layouts against a variety of possible backgrounds** to ensure your on-screen UI elements remain clear and legible.
-For more information on what to consider as you design and block in your UI elements for multiple devices, see [Positioning and Sizing - Cross-Platform Factors](../../..ui/positioning-and-sizing.md#cross-platform-factors).
+For more information on what to consider as you design and block in your UI elements for multiple devices, see [Positioning and Sizing - Cross-Platform Factors](../../../ui/positioning-and-sizing.md#cross-platform-factors).
## Develop User Flows
diff --git a/content/en-us/tutorials/use-case-tutorials/audio/in-game-sounds.md b/content/en-us/tutorials/use-case-tutorials/audio/in-game-sounds.md
index b40cdbf3f..1382c6285 100644
--- a/content/en-us/tutorials/use-case-tutorials/audio/in-game-sounds.md
+++ b/content/en-us/tutorials/use-case-tutorials/audio/in-game-sounds.md
@@ -1,7 +1,6 @@
---
title: In-Game Sounds
description: The process for creating positional and feedback sounds to enhance an experience.
-prev: /tutorials/building/environments/playing-background-music
---
In addition to background music, in-game audio can enhance a player's experience. This tutorial will cover two forms of in-game sounds: **positional** and **feedback** sounds.
diff --git a/content/en-us/tutorials/use-case-tutorials/audio/playing-background-music.md b/content/en-us/tutorials/use-case-tutorials/audio/playing-background-music.md
index 97b5febfb..f5a01d0af 100644
--- a/content/en-us/tutorials/use-case-tutorials/audio/playing-background-music.md
+++ b/content/en-us/tutorials/use-case-tutorials/audio/playing-background-music.md
@@ -1,8 +1,6 @@
---
title: Playing Background Music
description: The process for creating background music in your experience.
-next: /tutorials/building/environments/in-game-sounds
-prev: /tutorials/building/environments/lighting-with-props
---
Audio in Roblox is created with a `Class.Sound` object. Sounds can be positional, such as the sound of a waterfall, or universal for all players. This tutorial will show you how to create a universal sound to play background music.
diff --git a/content/en-us/tutorials/use-case-tutorials/input-and-camera/controlling-the-users-camera.md b/content/en-us/tutorials/use-case-tutorials/input-and-camera/controlling-the-users-camera.md
index d8b6b6c4f..497d09c92 100644
--- a/content/en-us/tutorials/use-case-tutorials/input-and-camera/controlling-the-users-camera.md
+++ b/content/en-us/tutorials/use-case-tutorials/input-and-camera/controlling-the-users-camera.md
@@ -1,7 +1,6 @@
---
title: Controlling the User's Camera
description: Explains how to customize the default camera view for a user.
-next: /tutorials/scripting/input-and-camera/detecting-user-input
---
The user's view of the world is represented by a `Class.Camera` object. You can change the camera behavior to suit your experience in a variety of ways. For example, the camera can react to events in the world, such as shaking when a monster walks by, or locked to the side of the user character, as in a side-scroller.
diff --git a/content/en-us/tutorials/use-case-tutorials/input-and-camera/detecting-user-input.md b/content/en-us/tutorials/use-case-tutorials/input-and-camera/detecting-user-input.md
index 9dd34258b..02a5e9a11 100644
--- a/content/en-us/tutorials/use-case-tutorials/input-and-camera/detecting-user-input.md
+++ b/content/en-us/tutorials/use-case-tutorials/input-and-camera/detecting-user-input.md
@@ -1,7 +1,6 @@
---
title: Detecting User Input
description: Explains how to customize and connect user input to actions.
-prev: /tutorials/scripting/input-and-camera/controlling-the-users-camera
---
Connecting user input to actions gives users much better and more intuitive control over your experience's features. In this tutorial, you will bind a reloading action to a specific key.
diff --git a/content/en-us/tutorials/use-case-tutorials/lighting/lighting-with-props.md b/content/en-us/tutorials/use-case-tutorials/lighting/lighting-with-props.md
index bae956e17..21ba468ce 100644
--- a/content/en-us/tutorials/use-case-tutorials/lighting/lighting-with-props.md
+++ b/content/en-us/tutorials/use-case-tutorials/lighting/lighting-with-props.md
@@ -1,7 +1,6 @@
---
title: Lighting with Props
description: The process for creating light sources out of props.
-next: /tutorials/building/environments/playing-background-music
---
While overall world lighting is globally controlled through the `Class.Lighting` service, games can also include in-game **light sources** like lamps, torches, spotlights, TV screens, etc.
diff --git a/content/en-us/tutorials/use-case-tutorials/physics/building-a-ferris-wheel.md b/content/en-us/tutorials/use-case-tutorials/physics/building-a-ferris-wheel.md
index be3213a1c..63e70e35b 100644
--- a/content/en-us/tutorials/use-case-tutorials/physics/building-a-ferris-wheel.md
+++ b/content/en-us/tutorials/use-case-tutorials/physics/building-a-ferris-wheel.md
@@ -1,10 +1,9 @@
---
title: Building a Ferris Wheel
description: The process for creating a Ferris Wheel using a motor.
-prev: /tutorials/building/physics/building-a-hinged-door
---
-In the last lesson, you learned how to make a door with `Class.HingeConstraint|HingeConstraints`. Many contraptions in Roblox will use multiple constraints to build more complicated mechanisms. In particular, you can configure several constraints to be **actuated**, meaning they will move under their own power. This tutorial will show you how to actuate a `Class.HingeConstraint` to be a **motor** in order to make a ferris wheel.
+Many contraptions in Roblox will use multiple constraints to build more complicated mechanisms. In particular, you can configure several constraints to be **actuated**, meaning they will move under their own power. This tutorial will show you how to actuate a `Class.HingeConstraint` to be a **motor** in order to make a ferris wheel.
-With that, your sparkling part is complete. You can try complementing the sparkling effect with a gentle glow by adding a `Class.PointLight` to the part, as shown at the start of the course — check out the [Lighting with Props](../../../tutorials/building/environments/lighting-with-props.md) course to learn more about light objects.
+With that, your sparkling part is complete. You can try complementing the sparkling effect with a gentle glow by adding a `Class.PointLight` to the part, as shown at the start of the course — check out the [Lighting with Props](../../../tutorials/use-case-tutorials/lighting/lighting-with-props.md) course to learn more about light objects.
diff --git a/content/en-us/tutorials/use-case-tutorials/vfx/custom-particle-effects.md b/content/en-us/tutorials/use-case-tutorials/vfx/custom-particle-effects.md
index 8ac4e8ede..e538160e1 100644
--- a/content/en-us/tutorials/use-case-tutorials/vfx/custom-particle-effects.md
+++ b/content/en-us/tutorials/use-case-tutorials/vfx/custom-particle-effects.md
@@ -1,7 +1,6 @@
---
title: Custom Particle Effects
description: The process for creating a multicolor plume of smoke from an active volcano.
-prev: /tutorials/building/effects/basic-particle-effects
---
Time to look at a more complex example of particle effects. You'll make a multicolored plume of smoke pouring out of an active volcano.
diff --git a/tools/checks/utils/allowedHttpLinks.txt b/tools/checks/utils/allowedHttpLinks.txt
index 0af2dc40e..29e607e24 100644
--- a/tools/checks/utils/allowedHttpLinks.txt
+++ b/tools/checks/utils/allowedHttpLinks.txt
@@ -555,4 +555,5 @@ https://www.youtube.com/live/h8RD96Ciof0
https://docs.google.com/forms/d/e/1FAIpQLSfwtTgKdNcwHfpvhGW1OFYz1lMzbdBf0AUbUP6JOS4Sn4WFXQ/viewform
https://docs.google.com/forms/d/e/1FAIpQLSdjdN0JcmKfxsPCHJgwCO7MCkbN7WPWczy6g_38VwVBzRTm7Q/viewform
https://docs.google.com/forms/d/e/1FAIpQLSdihHNOQdTc_Ug91CpeFAjVqFDsvSuTb8_z_FNnWfNxFysAKg/viewform
+https://www.guilded.gg/i/kbQ4Po42
https://www.youtube.com/watch?v=6MPWLQmIKLk