Skip to content

Commit 094dc56

Browse files
update Open Source Docs from Roblox internal teams
1 parent 742b787 commit 094dc56

File tree

6 files changed

+299
-0
lines changed

6 files changed

+299
-0
lines changed

content/common/navigation/engine/guides.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,11 @@ navigation:
3939
path: /projects/groups
4040
- title: Collaboration
4141
path: /projects/collaboration
42+
- title: Experience Ownership Transfer
43+
path: /projects/experience-ownership-transfer
44+
section:
45+
- title: Transferring Roblox Animations
46+
path: /projects/transferring-animations
4247
- title: Activity History
4348
path: /projects/activity-history
4449
- title: External Tools
Lines changed: 3 additions & 0 deletions
Loading
Lines changed: 3 additions & 0 deletions
Loading
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
---
2+
title: Experience Ownership Transfer
3+
description: Transfer ownership of an experience to other Roblox users or groups.
4+
---
5+
6+
With **experience ownership transfer**, you can transfer your experiences to groups you have publish access to. This unlocks all of the features available to groups, including permissions and revenue management, and allows you to efficiently manage your content as your team scales and your priorities shift.
7+
8+
## Prerequisites
9+
10+
Before making a transfer or accepting a transfer, you must first:
11+
12+
- Verify your email address.
13+
- Upload your private `ModuleScripts` to the group you're transferring the experience to. If the experience uses packages where the package owner is a user and not a group, you might have to recreate those packages or replace them with packages that are already owned by a group.
14+
- Publish your animation assets to the group you're transferring the experience to.
15+
16+
- If you have a large number of animations to upload, you can use a community-supported third-party tool like Roblox Animation Transfer. See [Transferring Roblox Animations](./transferring-animations.md) for more details.
17+
- If you have a small number of animations to upload, you can manually re-upload them and then update your animation asset references to support old and new IDs based on the `CreatorID` and `CreatorType`. See the following code for an example:
18+
19+
```lua
20+
-- Maps animation IDs that belong to the original creator to animation IDs
21+
-- that belong to the new creator.
22+
local transferAnimationMap = {
23+
["6406676108"] = 14292200298,
24+
["6438293322"] = 14292082312,
25+
["6464978998"] = 14292224322,
26+
["6465240715"] = 14292226967,
27+
["6465244287"] = 14292229476,
28+
["6382318344"] = 14292213468,
29+
["6382564692"] = 14292207171,
30+
["6460651769"] = 14292098870,
31+
["6415507655"] = 14292218236,
32+
["6415509331"] = 14292221034
33+
}
34+
35+
function mapTransferAnimationId(id)
36+
37+
-- If experience has been transferred, maps old => new animation IDs
38+
if game:GetService("RunService"):IsStudio() or
39+
(game.CreatorType == Enum.CreatorType.Group and
40+
game.CreatorId == 32626384) then
41+
local animationId = string.match(id, "%d+$")
42+
local mappedId = transferAnimationMap[animationId]
43+
44+
if mappedId then
45+
return "rbxassetid://" .. mappedId
46+
end
47+
end
48+
49+
return id
50+
end
51+
52+
-- Creates an animation instance associated with the
53+
-- specified rbxassetid://<animation_id> url
54+
function createAnimation(id)
55+
local animation = Instance.new("Animation")
56+
animation.AnimationId = mapTransferAnimationId(id)
57+
58+
return animation
59+
end
60+
```
61+
62+
<Alert severity="info">
63+
As a best practice, if you're using Open Cloud API keys for the experience, create an API key as the new owner with the name `RobloxTransferApiKey`. During the transfer, the relevant scopes are added to this new key and removed from the original key. You can then use a feature flag to allow your backend services to start using the new key after the transfer is complete.
64+
</Alert>
65+
66+
## Transferring an Experience
67+
68+
To transfer an experience to a group:
69+
70+
1. Go to [Creations](https://create.roblox.com/dashboard/creations) and choose the experience you want to transfer.
71+
2. Go to **Configure** > **Settings**.
72+
3. Click **Initiate ownership transfer**.
73+
4. In the **Transfer Details** dialog, carefully read and acknowledge the implications of the transfer. Then, click **Next**.
74+
75+
<img src="./assets/projects/Transferring-Experience.png" width="450" />
76+
77+
5. Select a group to transfer the experience to. You must be able to publish experiences to this group.
78+
6. Verify the transfer by entering the experience name.
79+
7. Click **Initiate transfer**. The **Content Settings** page updates to include the pending group's username.
80+
81+
<Alert severity="warning">
82+
Once the group accepts the transfer, Roblox makes your experience private and closes all servers associated with the experience.
83+
</Alert>
84+
85+
<Alert severity="info">
86+
To cancel a pending transfer, click **Cancel transfer request** in the **Content Settings** page.
87+
</Alert>
88+
89+
## Receiving a Transferred Experience
90+
91+
To receive a transferred experience:
92+
93+
1. Go to the experience page of the experience you're receiving. You can navigate to this page by clicking the transfer request notification you received when the experience's current owner initiated the transfer, or by directly getting the overview page link from the current owner.
94+
2. In the **Transfer Details** dialog, carefully read and acknowledge the implications of the transfer. Then, click **Next**.
95+
96+
<img src="./assets/projects/Receiving-Experience-Transfer.png" width="450" />
97+
98+
3. Verify the transfer by entering the experience name.
99+
4. Click **Accept transfer**. Roblox makes the experience private and the transfer process completes in a few minutes.
100+
5. After the transfer to your group is complete, set up any new permissions you need and make the experience public again.
101+
102+
<Alert severity="info">
103+
If you don't want to receive the transfer, click **Decline transfer** in the **Transfer Details** dialog.
104+
</Alert>
105+
106+
## Frequently Asked Questions
107+
108+
**What kind of information does the transferred experience retain?**
109+
110+
The transferred experience retains its old experience ID, place ID, and URL.
111+
<br/>
112+
**Do transfer requests expire?**
113+
114+
Yes, transfer requests expire after 7 days.
115+
<br/>
116+
**How often can I transfer the same experience?**
117+
118+
After receiving a transferred experience, you must wait 30 days to transfer that experience again.
119+
<br/>
120+
**Can I make changes to an experience I'm transferring?**
121+
122+
You can continue making changes to the experience until the new group owner accepts the transfer and the transfer process begins. Changes you make during the active transfer process specifically aren't carried over.
123+
<br/>
124+
**What happens to my credit card information when I transfer my experience?**
125+
126+
Roblox removes your credit card information when you transfer an experience.
127+
128+
<br/>
129+
**What happens to my revenue from private server subscriptions when I transfer my experience?**
130+
131+
You continue to receive the revenue from existing private server subscriptions, but the new group owner receives the revenue from any new or renewed subscriptions.
132+
<br/>
133+
**Does transferring an experience impact discovery?**
134+
135+
Transferring an experience doesn't impact search as long as the experience title remains the same, the new group owner is not a moderated account, and the experience is made public again after the transfer.
136+
137+
Note that transferring an experience can impact discovery for up to 24 hours after the new group owner makes the experience public again.
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
---
2+
title: Transferring Roblox Animations
3+
description: Transfer animations when you transfer your experience to a new group owner.
4+
---
5+
6+
<Alert severity="info">
7+
The instructions on this page make use of a third-party tool. Roblox does not officially support this tool and is not responsible for its availability, updates, or functionality.
8+
</Alert>
9+
10+
In Roblox, animations are locked to experiences owned by users who also own those animations. To prevent animations from breaking when you transfer your experience to a group, you must publish your animation assets to the new experience group owner.
11+
12+
If you have a large number of animations to upload, you can use the community-supported tool [Roblox Animation Transfer](https://github.com/evaera/roblox-animation-transfer) to re-upload the animations and map their old `AnimationIds` to their new corresponding `AnimationIds`.
13+
14+
## Prerequisites
15+
16+
Before transferring your animations, you must have `npx` installed. `npx` lets you run commands from packages without having to install those packages on your system. To check for `npx`, install `node.js` and run `npx –version` in a terminal window.
17+
18+
For more information about prerequisites, see the [Roblox Animation Transfer README](https://github.com/evaera/roblox-animation-transfer?tab=readme-ov-file#roblosecurity).
19+
20+
## Mapping AnimationIds to Names
21+
22+
If your animations are stored as Animation instances under pre-prepared Character models in your experience, you can generate a text file to map the `AnimationIds` to their corresponding names.
23+
24+
1. In Roblox Studio, run the following script. Studio outputs the result as a single long string.
25+
26+
```lua
27+
local ANIMSTRING = ""
28+
29+
for _, character in pairs(workspace:GetChildren()) do
30+
if not character:IsA("Model") then
31+
continue
32+
end
33+
34+
local animations = character:FindFirstChild("Animations")
35+
if not animations then
36+
continue
37+
end
38+
39+
for _, animation in pairs(animations:GetChildren()) do
40+
local animationId = string.match(animation.AnimationId, "%d+")
41+
if animationId then
42+
ANIMSTRING ..= (animationId .. " " .. character.Name .. "_" .. string.gsub(animation.Name, " ", "_") .. "\n")
43+
end
44+
end
45+
end
46+
47+
print(ANIMSTRING)
48+
```
49+
50+
2. Create a new text file on your computer.
51+
3. Paste the string output by Studio into the text file.
52+
4. Clean up any discrepancies like extra `-Edit` and `-Studio` strings that have been automatically added to the file content.
53+
5. Replace all spaces with underscores to limit the number of moderated names overall.
54+
55+
## (Optional) Preparing Text Files
56+
57+
Roblox has an internal rate limit for animation uploads. The Roblox Animation Transfer tool doesn't respect this rate limit, which can cause issues during the transfer process and break your final text file. For example, you might transfer 1200 animations but end up with only 900 of them and no way of determining which ones failed to transfer.
58+
59+
To make sure the final file doesn't break, you can:
60+
61+
1. Split your text file into multiple files with up to 200 animations in each.
62+
2. Use the Roblox Animation Transfer tool on each individual file. To prevent any major rate-limit problems, wait a few minutes in-between each batch.
63+
64+
## Transferring Animations
65+
66+
After your text files are ready, start the transfer process:
67+
68+
1. Open a terminal window.
69+
2. Run `npx roblox-animation-transfer --inFile animations.txt --group YOUR_GROUP_ID --outFile newAnimations.txt`.
70+
- `--inFile` must point to the file with the animations you want to upload. This file can be either the large text file you initially created, or the first of several smaller files if you chose to break the larger file down.
71+
- `--group` must point to the `GroupId` of the group receiving the animation transfer. You can find the group ID in the URL of the group on the Roblox website.
72+
- `--outFile` must point to the file you want to put the new animations in.
73+
74+
If the transfer process is successful, the animations in the `outFile` are listed in the same order they were provided in the `inFile`. If a number of animations fail to transfer, the tool attempts to transfer them again; if this second attempt is successful, these animations are appended to the end of the list in the `outFile`.
75+
76+
## Loading Animations at Runtime
77+
78+
After transferring your animations to the new group owner, you must swap the old animations for the new animations.
79+
80+
1. In Studio, create an `Animations` module.
81+
2. Create two child modules, one corresponding to the user, or the original owner, and the other corresponding to the group, or the new owner.
82+
3. To prevent the experience from breaking if you choose to publish it to another location, run the following script. By default, the script returns the user's animations.
83+
84+
```lua
85+
local module = {}
86+
local GROUP_ID = 12345678
87+
local gameContext = {
88+
["User"] = require(script:WaitForChild("Animations_User")),
89+
["Group"] = require(script:WaitForChild("Animations_Group"))
90+
}
91+
92+
local function getAnimationMapForGameContext()
93+
if game.CreatorType == Enum.CreatorType.Group and game.CreatorId == GROUP_ID then
94+
return gameContext.Group
95+
end
96+
return gameContext.User
97+
end
98+
99+
local animationMap = getAnimationMapForGameContext()
100+
function module.getAnimation(animName: string)
101+
return animationMap[animName]
102+
end
103+
104+
return module
105+
```
106+
107+
4. Turn the generated text files into animation maps in Studio.
108+
1. Replace the animation list inside the `animFileText` variable with the contents of the text file that you want to change into an animation map.
109+
2. Run the following script to return a string:
110+
111+
```lua
112+
local animFileText = [[
113+
4215167 Animation_Name_1
114+
6171235 Animation_Name_2
115+
1251267 Animation_Name_3
116+
]]
117+
118+
local function convertFileToAnimationMap(animFileText: string)
119+
local NEW_ANIMATION_MAP = ""
120+
121+
local lines = string.split(animFileText, "\n")
122+
for _, line in pairs(lines) do
123+
local components = string.split(line, " ")
124+
if #components ~= 2 then
125+
continue
126+
end
127+
128+
local animationId = components[1]
129+
local animationName = components[2]
130+
131+
NEW_ANIMATION_MAP = string.format("%s\t[\"%s\"] = \"rbxassetid://%s\",\n", NEW_ANIMATION_MAP, animationName, animationId)
132+
end
133+
134+
return string.format("return {\n%s}", NEW_ANIMATION_MAP)
135+
end
136+
137+
print(convertFileToAnimationMap(animFileText))
138+
```
139+
140+
5. Create a new `ModuleScript` parented to your `Animations` module.
141+
6. Place the returned `animFileText` string inside the `ModuleScript`.
142+
7. Update the experience to source all animations through the `Animations` module by running the following script:
143+
144+
```lua
145+
local Animations = require(PATH.TO.ANIMATIONS)
146+
local warriorWalk = Instance.new("Animation")
147+
warriorWalk.AnimationId = Animations.getAnimation("Warrior_Walk")
148+
```

tools/checks/utils/allowedHttpLinks.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -577,3 +577,6 @@ https://impactacademies.de/
577577
https://impactacademies.me/
578578
https://www.youtube-nocookie.com/embed/5NvGzKVyKxg
579579
https://www.youtube-nocookie.com/embed/qfWKYgO63OI
580+
https://github.com/evaera/roblox-animation-transfer?tab=readme-ov-file#roblosecurity
581+
https://github.com/evaera/roblox-animation-transfer?tab=readme-ov-file
582+
https://github.com/evaera/roblox-animation-transfer

0 commit comments

Comments
 (0)