Roblox 平台开发

SKILL开发
开发 未标注权限 许可证不明确
安装这个技能

Use when developing on the Roblox platform — Luau architecture, Remote trust boundaries, DataStore, UGC and monetization, plus moderation-risk checks — triggers include Roblox / Luau / Roblox Studio / Robux / Game Pass / UGC / 分层服装 / Roblox development / avatar / monetization. Not for generic engine or netcode design.

一句话选型结论

按资料字段整理

Roblox 平台开发是开发类的 Agent Skill,安装方式未标注,权限级别未标注,许可证不明确,有可直接复制的安装命令。技能本质是给模型读的说明书,效果取决于模型与客户端;装完先用一个小任务验证,再放进正式流程。

分类开发 安装方式未标注 权限级别未标注权限 许可证许可证不明确
累计安装 未标注 本周 未标注
GitHub 星标 未标注 仓库 未标注
下载量 未标注 技能市场下载数
权限级别 未标注权限 安装前请确认风险范围
许可证 许可证不明确 未说明

安装

未标注
在支持 Skills 的客户端里执行,装完问一句「你有哪些技能」验证
skillhub install user_63ad2463/roblox-platform-dev
  1. 1
    确认客户端支持

    确认你的客户端支持 Skills(Claude、Codex、Cursor 等),并升级到较新的版本。

  2. 2
    拿到技能文件

    执行上面的命令安装;也可以把仓库里的 SKILL.md 手动放进客户端的 skills 目录。

  3. 3
    刷新技能列表

    重新打开客户端,或刷新技能列表,让新放进来的技能被加载。

  4. 4
    验证是否生效

    问一句「你有哪些技能」,确认列表里出现它,再拿一个小任务试跑。

技能档案

开发
字段来自技能仓库与公开索引,中文说明由本站标注
作者 / 维护方user_63ad2463仓库 未标注 · 版本 未标注
宿主客户端未标注技能可被这些客户端加载
安装方式未标注安装包 community
权限级别未标注权限安装前请确认风险范围
许可证未说明许可证不明确,商用前请自行确认条款
仓库可用性available技能仓库当前是否可访问
最近核验未标注上游最后核验时间 · 数据更新 1791672210
正文体量41.0 KBSKILL.md 原文大小,越大说明说明书写得越细

典型使用场景

3 类
按分类整理的常见用法,具体以 SKILL.md 为准
写代码与改 bug

按需求补代码、定位并修掉报错。

读仓库与生成改动

让模型读懂项目结构,再给出可落地的改动。

跑测试与排查故障

按现象排查问题,补测试用例并复跑。

选择建议

装之前先看这几条
按条目字段给出的判断,不替你决定用不用

值得选的地方

  • 有可直接复制的安装命令,不用自己翻文档找入口。

先想清楚的地方

  • 没有标注权限级别,实际能做什么要装好后确认。
  • 许可证不明确,商用或二次分发前先到仓库确认条款。
  • 没有做站内核验,内容以作者仓库为准。
  • 技能只是说明书,实际效果取决于模型与客户端,装完先用小任务试一遍。

更适合

  • 需要在开发场景里给模型补一套做法的人。
  • 愿意先读一遍 SKILL.md、确认它会让模型做什么的人。

不太适合

  • 对许可证要求很严、必须明确可商用的人。
  • 只想装完就自动变强、不打算看说明书的人。

同类对比

6 个同类
同分类里挑最接近的几条,字段以各自详情页为准
技能权限级别安装方式累计安装宿主客户端安装命令
Roblox 平台开发当前 未标注权限 未标注 未标注 未标注 有
技能审查员 浏览器控制 ClawHub 市场 877.9 万 OpenClaw 有
Vercel React 最佳实践 浏览器控制 GitHub 仓库 849.1 万 Codex、Claude、Cursor 有
GitHub 代码协作 联网访问 ClawHub 市场 763.3 万 OpenClaw 有
网页设计指南 联网访问 GitHub 仓库 668.6 万 Codex、Claude、Cursor 有
本体论 只读 ClawHub 市场 663.7 万 OpenClaw 有

SKILL.md 全文

41.0 KB
模型实际读到的说明书原文,来自技能仓库

Roblox 平台开发(Luau · 信任模型 · UGC · 商业化)

何时使用

  1. 从零搭 Roblox 体验骨架:服务器引导、模块架构、Remote 分层
  2. 出现「客户端能改服务器状态」的风险:走 §一 信任边界与安全审计
  3. 玩家进度会丢、会重复、会串档:走 §二 DataStore 规范
  4. 设计付费:Game Pass / Developer Product / UGC 三类付费物的选型、门控与定价
  5. 做留存:每日奖励、体验引导漏斗、Roblox 算法信号(并发/收藏/SEO)
  6. 做虚拟形象与 UGC:配件网格规格、分层服装 Cage、Creator Marketplace 提交流程

判定(分流相邻技能):Roblox 平台机制 = 本技能;通用玩法与关卡设计(内容与规则层)= game-content-design;通用网络同步与延迟补偿原理 = game-multiplayer-netcode;通用美术管线与着色器 = game-tech-art;引擎世界分区与工具链 = game-engine-engineering;XR 沉浸与空间界面 = xr-spatial-computing;工作室级流程编排 = game-studio-orchestration。

触发语(语言信号)

  • 中文:Roblox、Roblox Studio、Luau、罗布乐思、Robux、游戏通行证、开发者产品、虚拟形象、头像、分层服装、创作者市场、配件、绑定、贴图规格、数据存储、存档、客户端服务器安全、每日奖励、留存、体验设计、UGC
  • English: Roblox, Luau, Robux, DevEx, Game Pass, Developer Product, UGC, avatar, HumanoidDescription, Layered Clothing, Creator Marketplace, accessory, rigging, _InnerCage, RemoteEvent, RemoteFunction, DataStore, ServerStorage, ReplicatedStorage, ModuleScript, client-server security, daily reward, retention

总纲:Roblox 平台四条底座

Roblox 不是「又一个引擎」,而是带自有经济学、自有审核、自有信任模型的宿主平台。本技能的主干是平台特有的约束与流程,通用玩法设计与网络原理不在此重述。

  1. 服务器是真相,客户端只是显示器——伤害、货币、背包、位置权威一律在服务器;客户端发请求,服务器决定是否兑现。这决定了 §一 与 §二 的全部写法。
  2. 平台经济学走 Robux(创作者侧另有 DevEx 结算机制),不是通用游戏货币——Game Pass(永久权益)、Developer Product(可重复消耗)、UGC 物品(目录资产)三条路径各有各的 API 与门控方式,定价须落在 Roblox 允许的价格档位。
  3. 合规与审核是管线的一等公民——网格三角面、贴图内容、物品命名、缩略图任一项越界即自动拒审;免费体验必须完整,付费不得使其变得挫败或不可玩。
  4. 平台算法奖励「重叠会话」——并发玩家数、收藏、访问量是发现性信号(见 §四),设计要利于组队与分享,而非孤立的单机式体验。

一、客户端-服务器信任模型与 Luau 架构

1.1 信任边界五条铁律

  • 服务器是真相——客户端显示状态,不拥有状态
  • 绝不信任经 RemoteEvent/RemoteFunction 送来的客户端数据,未经服务器校验即拒
  • 一切影响玩法的状态变更(伤害、货币、背包)只在服务器执行
  • 客户端可以请求动作;服务器决定是否兑现
  • LocalScript 跑客户端,Script 跑服务器——绝不把服务器逻辑混进 LocalScript

1.2 Remote 家族规则

调用 方向 纪律
RemoteEvent:FireServer() 客户端 → 服务器 永远校验发送者是否有权发此请求
RemoteEvent:FireClient() 服务器 → 客户端 安全——服务器决定客户端看到什么
RemoteFunction:InvokeServer() 客户端 → 服务器 谨慎用;客户端中途断线会让服务器线程无限 yield,必须加超时处理
RemoteFunction:InvokeClient() 服务器 → 客户端 绝不从服务器调用——恶意客户端可永久挂住服务器线程

1.3 ModuleScript 架构四则

  • 所有游戏系统都是 ModuleScript,由服务器 Script 或客户端 LocalScript require——独立 Script/LocalScript 里除引导外不放逻辑
  • 模块返回 table 或 class——绝不返回 nil,require 时不留副作用
  • 双方可用的常量放 ReplicatedStorage 模块或 shared 表——绝不在多个文件硬编码同一常量
  • 每系统一个模块、暴露 init()、启动时统一调用;所有 Remote 处理器在模块 init() 内接线,Script 里不散落事件连接

1.4 服务器引导 + 安全 Remote 模式(模板)

-- Server/GameServer.server.lua —— 只做引导,逻辑全在 ModuleScript
local Players = game:GetService("Players")
local ServerStorage = game:GetService("ServerStorage")
local PlayerManager = require(ServerStorage.Modules.PlayerManager)
local CombatSystem = require(ServerStorage.Modules.CombatSystem)
local DataManager = require(ServerStorage.Modules.DataManager)
DataManager.init()
CombatSystem.init()
Players.PlayerAdded:Connect(function(p) DataManager.loadPlayerData(p)
    PlayerManager.onPlayerJoined(p) end)
Players.PlayerRemoving:Connect(function(p) DataManager.savePlayerData(p)
    PlayerManager.onPlayerLeft(p) end)
game:BindToClose(function()          -- 关机保存:只挂 PlayerRemoving 会漏掉关机窗口
    for _, player in Players:GetPlayers() do DataManager.savePlayerData(player) end
end)

-- ServerStorage/Modules/CombatSystem.lua —— 三层校验通过后才改状态
local Remotes = game:GetService("ReplicatedStorage").Remotes
local CombatSystem, LAST = {}, {}                   -- LAST = 冷却表
local ATTACK_RANGE, COOLDOWN = 10, 0.5              -- studs / 秒
local function rootOf(p: Player): BasePart?
    return p.Character and p.Character:FindFirstChild("HumanoidRootPart") :: BasePart?
end
local function onAttack(player: Player, targetUserId: number): ()
    if type(targetUserId) ~= "number" then return end                 -- ① 结构校验
    local last = LAST[player.UserId]
    if last and os.clock() - last < COOLDOWN then return end          -- ② 冷却(服务器侧)
    local attacker, targetPlayer = rootOf(player), Players:GetPlayerByUserId(targetUserId)
    local target = targetPlayer and rootOf(targetPlayer)
    if not (attacker and target) then return end
    if (attacker.Position - target.Position).Magnitude > ATTACK_RANGE then return end  -- ③ 距离
    LAST[player.UserId] = os.clock()                                  -- 三层全过 → 服务器改状态
    local hum = targetPlayer.Character:FindFirstChildOfClass("Humanoid")
    if hum then hum.Health -= 20                                      -- 仅把结果确认给客户端
        Remotes.AttackConfirmed:FireAllClients(player.UserId, targetUserId) end
end
function CombatSystem.init(): () Remotes.RequestAttack.OnServerEvent:Connect(onAttack) end
return CombatSystem

1.5 模块目录结构(模板)

ServerStorage/Modules/         DataManager(玩家数据)· CombatSystem(战斗校验)· PlayerManager(生命周期)
                               InventorySystem(物品归属)· EconomySystem(货币源汇)
ReplicatedStorage/Modules/     Constants(共享常量)· NetworkEvents(Remote 引用,单一真相源)
ReplicatedStorage/Remotes/     RequestAttack · RequestPurchase · SyncPlayerState(服务器 → 客户端)
StarterPlayerScripts/LocalScripts/  GameClient.client.lua —— 只做客户端引导
StarterPlayerScripts/Modules/  UIManager(HUD/菜单)· InputHandler(输入 → Remote)· EffectsManager(反馈)

1.6 安全审计流程

逐个审 OnServerEvent 处理器(客户端发垃圾数据会发生什么?)→ 用 RemoteEvent 触发工具发不可能的值,确认服务器拒绝 → 确认血量、货币、位置权威全归服务器 → 客户端只做两件事:以 FireServer() 发动作请求、以 OnClientEvent 收确认 → 客户端视觉状态由服务器确认驱动(简单场景用纯确认,要跟手性时用经校验的预测)。


二、DataStore 持久化规范

2.1 四项铁律

  • 所有 DataStore 调用必须包 pcall——DataStore 会失败,未保护的失败会永久损坏玩家数据
  • 所有读写实现指数退避重试
  • 在 Players.PlayerRemoving 和 game:BindToClose() 都保存——只挂前者会漏掉关机窗口
  • 每键保存频率不得高于每 6 秒一次——Roblox 有速率限制,超限静默失败

2.2 进度安全三则

  • 玩家进度(等级、物品、货币)必须进 DataStore 且带重试——进度丢失是玩家永久流失的第一原因
  • 绝不静默重置玩家进度——数据 schema 要版本化并迁移,绝不覆写
  • 免费与付费玩家共用同一 DataStore 结构——按玩家类型拆库会造成维护噩梦

2.3 DataStore 重试模块(模板)

-- ServerStorage/Modules/DataManager.lua
local DataManager = {}
local store = game:GetService("DataStoreService"):GetDataStore("PlayerData_v1")
local loaded: {[number]: any} = {}
local DEFAULT = {coins = 0, level = 1, inventory = {}}
local function deepCopy(t)
    local c = {}
    for k, v in t do c[k] = if type(v) == "table" then deepCopy(v) else v end
    return c
end
local function retryAsync(fn, maxAttempts)                   -- 指数退避:2s / 4s / 8s
    local attempts, success, result = 0
    repeat
        attempts += 1
        success, result = pcall(fn)
        if not success then task.wait(2 ^ attempts) end
    until success or attempts >= maxAttempts
    return success, result
end
function DataManager.loadPlayerData(player: Player): ()
    local ok, data = retryAsync(function() return store:GetAsync("player_" .. player.UserId) end, 3)
    if not ok then warn("[DataManager] load failed:", player.Name) end
    loaded[player.UserId] = (ok and data) or deepCopy(DEFAULT)
end
function DataManager.savePlayerData(player: Player): ()
    local data = loaded[player.UserId]
    if not data then return end
    local ok, err = retryAsync(function() store:SetAsync("player_" .. player.UserId, data) end, 3)
    if not ok then warn("[DataManager] save failed:", err) end
    loaded[player.UserId] = nil
end
function DataManager.getData(player: Player): any return loaded[player.UserId] end
function DataManager.init(): () end
return DataManager

2.4 高级持久化与压测

玩家数据写入用 UpdateAsync 替代 SetAsync(原子地处理并发写冲突);建数据版本系统 data._version,每次 schema 变更递增并配每版本迁移处理器;用带 session locking 的包装器防同一玩家在两台服务器同时加载导致损坏;排行榜用 ordered DataStore 的 GetSortedAsync() 并控制页大小做 top-N。压测:模拟玩家快速进出(含活跃会话中关机)→ 验证 BindToClose 在关机窗口保存全量 → 临时停用再于会话中途恢复 DataStore,验证重试生效。


三、Roblox 商业化设计

3.1 三类付费物(平台特有)

类型 性质 门控 / 购买 API
Game Pass 永久权益或功能 MarketplaceService:UserOwnsGamePassAsync() 门控
Developer Product 可消耗(可重复购买)——货币包、物品包等 购买完成后授予对应消耗品
UGC 物品 目录资产(帽子、配件、服装等) MarketplaceService:PromptPurchase()

三者的区别不是价格高低,而是所有权语义:永久 / 消耗 / 目录资产。选型错了,门控与退款处理都会错。

3.2 Game Pass 门控(模板)

-- ServerStorage/Modules/PassManager.lua
local MarketplaceService = game:GetService("MarketplaceService")
local PASS_IDS = {VIP = 123456789, DoubleXP = 987654321}   -- 集中注册表,只改这里
local cache: {[number]: {[string]: boolean}} = {}          -- 缓存归属,少打 API
function PassManager.playerOwnsPass(player: Player, passName: string): boolean
    local userId, passId = player.UserId, PASS_IDS[passName]
    cache[userId] = cache[userId] or {}
    if cache[userId][passName] == nil then
        local ok, owns = pcall(MarketplaceService.UserOwnsGamePassAsync,
            MarketplaceService, userId, passId)
        cache[userId][passName] = ok and owns or false
    end
    return cache[userId][passName]
end
function PassManager.promptPass(player: Player, passName: string): ()   -- 客户端发起的购买提示
    if PASS_IDS[passName] then
        MarketplaceService:PromptGamePassPurchase(player, PASS_IDS[passName]) end
end
function PassManager.init(): ()                    -- 购买完成 → 更新缓存 + 立即施加权益
    MarketplaceService.PromptGamePassPurchaseFinished:Connect(
        function(player: Player, passId: number, wasPurchased: boolean)
            if not wasPurchased then return end
            for name, id in PASS_IDS do
                if id == passId then cache[player.UserId][name] = true end end
            applyPassBenefit(player, passId)
        end)
end
return PassManager

3.3 每日奖励系统(模板:投入最低、留存最高,上线前必须先有)

-- ServerStorage/Modules/DailyRewardSystem.lua
local rewardStore = game:GetService("DataStoreService"):GetDataStore("DailyRewards_v1")
local LADDER = {                                   -- 索引 = 连续天数(第 7 天给整周奖励)
    {coins = 50}, {coins = 75}, {coins = 100}, {coins = 150},
    {coins = 200}, {coins = 300}, {coins = 500, item = "badge_7day"} }
local DAY = 86400
function DailyRewardSystem.claimReward(player: Player): (boolean, any)
    local key = "daily_" .. player.UserId
    local ok, data = pcall(rewardStore.GetAsync, rewardStore, key)
    if not ok then return false, "datastore_error" end
    data = data or {lastClaim = 0, streak = 0}
    local elapsed = os.time() - data.lastClaim
    if elapsed < DAY then return false, "already_claimed" end
    if elapsed > DAY * 2 then data.streak = 0 end          -- 超 48 小时断档
    data.streak = (data.streak % #LADDER) + 1
    data.lastClaim = os.time()
    if not pcall(rewardStore.SetAsync, rewardStore, key, data) then return false, "save_error" end
    return true, LADDER[data.streak]
end
return DailyRewardSystem

3.4 商业化伦理判据(Roblox 受众主体为 9–17 岁)

  • 体验必须完整——不得有让免费玩法变得挫败或不可能的 pay-to-win
  • 绝不用倒计时制造人为稀缺来逼即时购买
  • 奖励式广告(若实现):玩家同意必须明确,跳过必须容易
  • 首发包与限时优惠合法——但要用诚实框架,不用暗黑模式
  • 所有付费物品必须在 UI 上与可赚取物品清楚区分

3.5 定价与 Live Ops 纪律

Robux 定价必须落在 Roblox 允许的价格档位——实现前须核当期认可档位(档位会变,实访官方)。用分析分桶做价格点 A/B(测转化率、ARPU、LTV);价格锚定(高端选项摆标准选项旁);软货币首购漏斗(给新玩家足够货币完成一次小购买);购买弃单挽回(打开商店未购买,下次会话给提醒)。

限时活动:用 ReplicatedStorage 配置对象在服务器重启时切换限时/赛季内容;倒计时系统由单一服务器时间源驱动 UI、世界装饰与解锁内容;灰度发布用 math.random() 种子对配置开关做百分比判定;活动奖励要制造期待但不掠夺——限定时装要有清晰赚取路径,不是付费墙。


四、留存、引导与平台算法

4.1 体验引导流程(模板)

## Roblox 体验引导流程
### 阶段 1 · 前 60 秒(留存关键)—— 目标:执行核心动词并成功一次
1. 出生在视觉上明确区分的「起始区」,不是主世界
2. 立刻给可控时刻:无过场、无长教程对话
3. 首次必定成功——本阶段不可失败
4. 首次成功给视觉奖励(闪光/彩带)+ 音频反馈
5. 箭头或高亮引导至「首个任务」NPC 或目标
### 阶段 2 · 前 5 分钟(核心循环引入)—— 目标:完成一整轮循环并拿到首个奖励
1. 简单任务:目标清楚、位置明显、只需一个机制
2. 奖励:足够的起始货币,让玩家感到有意义
3. 解锁一个额外功能或区域——制造前进动量
4. 柔性社交提示:「邀请好友得双倍奖励」(不阻塞)
### 阶段 3 · 前 15 分钟(投入钩)—— 目标:退出开始像一种损失
1. 首次升级或段位晋升
2. 个性化时刻:选一件时装或给角色命名
3. 预告锁定功能:「达到 5 级解锁 [X]」
4. 自然收藏提示:「玩得开心?把它加入收藏吧!」
### 流失恢复点
- 2 分钟内离开:引导太慢 → 砍掉前 30 秒
- 5–7 分钟离开:首个奖励不够诱人 → 加码
- 15 分钟后离开:好玩但没有回访钩子 → 加每日奖励引导

4.2 留存埋点(模板:Roblox 内置 AnalyticsService,无需第三方)

-- Creator Dashboard 可见;无需第三方
local AnalyticsService = game:GetService("AnalyticsService")
AnalyticsService:LogCustomEvent(player, "OnboardingCompleted", {time_seconds = elapsedTime})
AnalyticsService:LogCustomEvent(player, "FirstPurchase", {pass_name = passName, price_robux = price})
Players.PlayerRemoving:Connect(function(player)                       -- 会话时长
    AnalyticsService:LogCustomEvent(player, "SessionEnd",
        {duration_seconds = os.time() - sessionStartTimes[player.UserId]})
end)

补充:用 AnalyticsService:LogCustomEvent() 建漏斗,覆盖引导每一步、购买流、留存触发点;首入时间戳/总游玩时长/上次登录存入 DataStore 做同期群分析;A/B 分桶用 UserId 播种 math.random() 并记档;需超出内置看板的 BI 时用 HttpService:PostAsync() 导出事件。

4.3 Roblox 算法信号与社交系统

  • 并发玩家数越高排名越高——设计鼓励组队与分享,而非孤立单机体验
  • 收藏与访问量是算法信号——在自然正向节点(升级、首胜、解锁物品)放分享提示与收藏提醒
  • Roblox SEO:标题、描述、缩略图是发现性影响最大的三项——当成产品决策,不是占位符
  • 上线首周盯 D1/D7,D1 低于 20% 须重做引导;用内置 A/B 工具测缩略图与标题;盯首会话流失漏斗
  • 用 Players:GetFriendsAsync() 校验好友后发邀请奖励;用 Players:GetRankInGroup() 做 Group 门控内容;大厅展示实时在线人数与排行榜(社会认同);合适场景用 VoiceChatService 空间语音
  • 构建顺序不可颠倒:先建 DataStore 进度 → 上线前实现每日奖励 → 购买流最后建(依赖可用的进度系统)

五、UGC 与虚拟形象管线

5.1 网格规格(硬约束)

  • UGC 配件网格必须低于 4,000 三角面(帽/配件)——超限自动拒审;打包部件上限 10,000
  • 必须是单一对象、单一 UV 图,UV 落在 [0,1] 空间——不得有超出该范围的 UV 重叠
  • 导出前应用全部变换(scale = 1、rotation = 0、position 依配件类型置于原点/挂点)
  • 导出格式:带绑定的配件用 .fbx;不形变的简单配件用 .obj

5.2 贴图与绑定规则

分辨率最小 256×256、最大 1024×1024;格式 .png 支持透明(带透明的配件用 RGBA);不得含版权 logo、真实品牌或不雅影像——立即被审核移除;UV 岛边缘至少留 2px 内边距,防止压缩 mip 级下贴图渗色。配件经 Attachment 对象挂载——挂点名必须匹配 Roblox 标准(HatAttachment、FaceFrontAttachment、LeftShoulderAttachment 等);R15/Rthro 兼容须在多种体型测试(Classic、R15 Normal、R15 Rthro);分层服装需要外层网格 + 内层笼网格(_InnerCage)才能形变——缺内笼会穿透身体。

5.3 配件导出检查表(模板:DCC → Roblox Studio)

### 网格
- [ ] 三角面 ___(配件上限 4,000,打包部件 10,000)
- [ ] 单一网格对象 / 单一 UV 通道且落在 [0,1] / [0,1] 外无 UV 重叠:Y/N
- [ ] 全部变换已应用(scale=1、rot=0)/ 轴心点位于挂点 / 无零面积面与非流形几何:Y/N
### 贴图
- [ ] 分辨率 ___×___(上限 1024×1024)/ 格式 PNG / UV 岛留 ≥2px 内边距:Y/N
- [ ] 无版权内容 / 透明度在 alpha 通道处理:Y/N
### 绑定
- [ ] Attachment 对象存在且命名正确:___;已测体型 [ ] Classic [ ] R15 Normal [ ] R15 Rthro
- [ ] 任何测试体型下均不穿透默认形象网格:Y/N
### 文件
- [ ] 格式 FBX(带绑定)/ OBJ(静态);命名 [CreatorName]_[ItemName]_[Type]

5.4 分层服装 Cage 要求(模板:Blender)

- **外层网格(Outer Mesh)**:游戏内可见的服装本体;按规格 UV 与贴图;绑定到 R15 骨骼(与 Roblox 公开 R15 rig 完全一致);导出名 [ItemName]
- **内层笼网格(_InnerCage)**:与外层同拓扑但向内收缩约 0.01 单位;定义服装如何包裹身体;不上贴图,游戏内不可见;导出名 [ItemName]_InnerCage
- **外层笼网格(_OuterCage)**:让其他分层物品能叠在其上;由外层网格略微向外扩张;导出名 [ItemName]_OuterCage
- **骨骼权重**:所有顶点加权到正确的 R15 骨骼;无未加权顶点(否则接缝处撕裂);权重迁移使用 Roblox 提供的参考 rig 以取得正确骨骼名
- **测试要求**:提交前在 Studio 应用到全部测试体型(Young、Classic、Normal、Rthro Narrow、Rthro Broad);在 idle/run/jump/sit 极限姿势下确认无穿模

5.5 Creator Marketplace 提交包(模板)

### 元数据
- **物品名**:[准确、可搜索、不误导] **描述**:[清楚描述物品 + 挂在哪个身体部位]
- **分类**:[帽子 / 面部配件 / 肩部配件 / 衬衫 / 裤子 / 等]
- **价格**:[以 Robux 计——对标同类物品做市场定位] **Limited**:[ ] 是(需具备资格)  [ ] 否
### 资产文件
- [ ] 网格 [filename].fbx / .obj;贴图 [filename].png(上限 1024×1024)
- [ ] 图标缩略图 420×420 PNG——中性背景上清楚展示物品
### 提交前校验
- [ ] Studio 内:全形象体型渲染正确 / idle、walk、run、jump、sit 无穿模
- [ ] 贴图无版权、无品牌 logo、无不雅内容;网格三角面在限内;全部变换已应用
### 审核风险预检
- [ ] 物品上有文字?(可能需过文字审核) [ ] 引用真实品牌?→ 移除
- [ ] 遮蔽面部的部件?(审核关注度更高) [ ] 武器形状配件?→ 先查 Roblox 武器政策

提交与审核纪律:物品名必须准确描述物品(误导性命名导致扣留);所有物品须过 Roblox 自动审核,精选物品还需人工复审,典型审核时长 24–72 小时;图标必须清楚展示物品;Limited 物品种类需创作者账号有既定成绩记录(须核当期资格要求);做造型前先查当期该物品类型的 Roblox UGC 要求(规格会周期性更新);若被拒,仔细读拒审理由——最常见三类为贴图内容、网格规格违规、误导性命名。

5.6 体验内 Avatar 自定义与 UGC 购买(模板)

-- ServerStorage/Modules/AvatarManager.lua
local AvatarManager = {}
function AvatarManager.applyOutfit(player: Player, outfit: table): ()
    local character = player.Character
    local humanoid = character and character:FindFirstChildOfClass("Humanoid")
    if not humanoid then return end
    local d = humanoid:GetAppliedDescription()
    if outfit.hat then d.HatAccessory = tostring(outfit.hat) end
    if outfit.face then d.FaceAccessory = tostring(outfit.face) end
    if outfit.shirt then d.Shirt = outfit.shirt end
    if outfit.pants then d.Pants = outfit.pants end
    if outfit.bodyColors then d.HeadColor = outfit.bodyColors.head or d.HeadColor
        d.TorsoColor = outfit.bodyColors.torso or d.TorsoColor end
    humanoid:ApplyDescription(d)                   -- 该方法自行处理角色刷新
end
function AvatarManager.applyPlayerSavedOutfit(player: Player): ()   -- 从 DataStore 载入并施加
    local data = require(script.Parent.DataManager).getData(player)
    if data and data.outfit then AvatarManager.applyOutfit(player, data.outfit) end
end
return AvatarManager

-- 客户端:按 asset ID 购买 UGC,再回传服务器持久化
local MarketplaceService = game:GetService("MarketplaceService")
function AvatarShopUI.promptPurchaseItem(assetId: number): ()
    MarketplaceService:PromptPurchase(Players.LocalPlayer, assetId)   -- UGC 目录物品可用
end
MarketplaceService.PromptPurchaseFinished:Connect(function(_, assetId, isPurchased)
    if isPurchased then game.ReplicatedStorage.Remotes.ItemPurchased:FireServer(assetId) end
end)

用 DataStore 存多套装束槽位并支持体验内切换;把形象自定义做成核心玩法循环(游玩赚时装、在社交空间展示)。


六、端到端平台工作流

  1. 架构规划——定服务器/客户端职责切分(服务器拥有什么、客户端显示什么);映射全部 RemoteEvent(请求 vs 确认与状态更新);数据落盘前先设计 DataStore key schema(迁移很痛)
  2. 服务端模块——先建 DataManager(其他系统都依赖已载入的玩家数据);每系统一个 ModuleScript 并在启动时调用 init();Remote 处理器在 init() 内接线
  3. 客户端模块——只以 FireServer() 发动作、以 OnClientEvent 收确认;LocalScript 引导器 require 并 init() 全部客户端模块
  4. 安全审计——逐个审 OnServerEvent;用触发工具发不可能的值并确认被拒;确认血量、货币、位置权威全归服务器
  5. DataStore 压测——模拟快速进出与关机;验证 BindToClose 保存全量;临时停用再恢复 DataStore 验证重试
  6. UGC 建模与绑定——定类型 → 查当期要求 → 调研同类价格 → 按三角面上限建模 → UV 留 2px → 导入官方参考 rig 权重到 R15 骨骼 → 建 _InnerCage / _OuterCage
  7. Studio 内测试——经 Studio → Avatar → Import Accessory 导入;五个体型预设全测;走 idle/walk/run/jump/sit 查穿模
  8. 提交——备元数据、缩略图、资产文件;经 Creator Dashboard 提交;盯审核队列(典型 24–72 小时)
  9. 上线与优化——首周盯 D1/D7 与首会话流失漏斗;内置 A/B 工具测标题与缩略图;按漏斗数据迭代购买流与引导

七、量化验收指标(三份专家 Success Metrics 合并)

维度 指标 阈值
安全 可被利用的 RemoteEvent 处理器(无类型/范围校验)/ 从服务器调用 RemoteFunction:InvokeClient() 0 / 0 次
安全 服务器逻辑置于 ServerStorage 模块、客户端不可达 100%
数据 未包 pcall+无重试的 DataStore 访问 / PlayerRemoving 与 BindToClose 双路径保存成功 0 / 100%(关机零丢档)
商业化 免费 → 任意付费的转化率 > 3%
合规 商业化审核中的 Roblox 政策违规 0
留存 D1 / D7 留存(上线首月内) > 30% / > 15%
留存 引导完成率(到达第 5 分钟)占新访客 > 70%
增长 MAU 月环比增长(前 3 个月) > 10%
UGC 因技术原因被审核拒绝 0 次
UGC 配件在 5 种体型 × 标准动画集下穿模 0
UGC Marketplace 定价与同类物品的偏离 ≤ 15%
形象 体验内 HumanoidDescription 自定义出现瑕疵或角色刷新循环 / 分层服装与 2+ 件其他分层物品叠加不穿模 0 / 必过
性能 用 Stats.GetTotalMemoryUsageMb() 分类审计内存 在预算内

八、反例(七条)

# 反例 为什么错
1 把伤害/货币/背包的权威逻辑放客户端,服务器只「收通知」 违信任边界:利用者可任意篡改玩法状态。服务器是真相,客户端只是显示器
2 从服务器调用 RemoteFunction:InvokeClient() 恶意客户端可永久挂起服务器线程——单点即可拖垮全场
3 DataStore 不用 pcall、直接 SetAsync 覆写 一次平台抖动即永久损坏玩家进度;覆写绕过迁移,等于静默重置
4 只挂 PlayerRemoving 保存,不挂 BindToClose() 关机窗口内全场存档丢失——进度丢失是玩家永久流失的第一原因
5 配件超 4,000 三角面/UV 岛不留 2px 内边距/分层服装缺 _InnerCage 自动拒审;或缺内笼导致游戏内穿透身体
6 用默认头像管线规格、跳过 Studio 五体型与动画测试就提交 上线穿模或审核退回;规格会变,提交前必须查当期要求
7 用倒计时制造人为稀缺逼即时购买,或让免费玩法变得挫败 违 Roblox 政策(免费体验必须完整)+ 违伦理(受众主体为未成年人)

九、来源与边界

  • 核验范围:本次核验的是源材料本体的完整性(三份原文可取、逐节比对、模板可复制)。未核当期官方条款——Roblox 平台政策与费率会变:Robux 价格档位、UGC 审核标准与资格要求(如 Limited 物品的创作者资格)、三角面与贴图规格上限、DataStore 速率限制细则、创作者侧 DevEx 结算规则,均须实访 Roblox 官方文档与 Creator Dashboard 复核后再执行。本技能中的 API 名称与代码模板直接取自原文,未做独立运行验证。
  • 本技能不做:通用玩法/关卡/经济设计方法论(机制、叙事、节奏、源与汇)→ game-content-design(本技能只写 Roblox 平台特有的落地方式);通用网络架构与同步原理(权威模型、复制、延迟补偿)→ game-multiplayer-netcode(本技能只写 Roblox 的客户端-服务器信任模型);通用美术管线与着色器/材质 → game-tech-art(本技能只写 Roblox 的 Avatar/UGC 管线规格);引擎架构、世界分区与工具链 → game-engine-engineering;Unity / Unreal / Godot 引擎工作流 → 各自引擎技能;XR 沉浸与空间界面 → xr-spatial-computing;工作室级流程编排 → game-studio-orchestration。
  • 相关技能:game-content-design(通用内容设计,与本技能的「Roblox 落地方式」互补)、game-multiplayer-netcode(通用网络原理,本技能为其 Roblox 特例)、steam-local-game-data(Steam 侧本地游戏数据,同属平台数据类但平台不同)。

异常处理与降级(Error Handling)

输入校验:什么算「不合格输入」

判定项 合格 不合格 不合格时的动作
目标平台 明确是 Roblox 平台工作(Luau/Remote/DataStore/UGC) 说的是 Unity/Unreal/Godot 或通用网络原理 分别转各自引擎技能或 game-multiplayer-netcode;通用玩法设计转 game-content-design
权威归属 伤害、货币、背包、位置权威都在服务器 由客户端算出结果再「通知」服务器 停机重构:把该状态变更移回服务器,客户端只留请求与显示
Remote 方向 客户端 FireServer() 请求,服务器决定是否兑现 从服务器调用 RemoteFunction:InvokeClient() 立即改为单向 RemoteEvent 通知,绝不保留
持久化访问 全部 DataStore 调用包 pcall + 指数退避重试 裸 SetAsync 覆写、无重试 补 pcall + 重试,并先定 key schema 再落盘
UGC 资产 配件网格在三角面上限内、UV 落在 [0,1]、贴图不超过 1024×1024 超限/UV 出界/缺内笼 回 DCC 减面、重展 UV、补 _InnerCage,不得带病提交
定价与规格 实现前已核对当期官方档位与政策 凭印象定价或套旧规格 实访官方后重核,本技能不代替当期条款核验

错误分类与处置

码 触发条件 表现 处置 降级去向
E1 OnServerEvent 收到非法数据 服务器未校验即改状态,可被利用 补「结构/冷却/距离」三层校验后再改状态 回 §1.4 三层校验模板
E2 从服务器调用 RemoteFunction:InvokeClient() 恶意客户端可永久挂起服务器线程 改为 RemoteEvent 单向通知 回 §1.2 Remote 家族规则
E3 DataStore 调用未包 pcall 一次平台抖动即永久损坏玩家进度 包 pcall + 指数退避重试 回 §2.3 重试模块模板
E4 关机窗口丢档 只挂 PlayerRemoving,漏掉关机 补 game:BindToClose() 全量保存 回 §2.1 数据四项铁律
E5 同一玩家被两台服务器同时加载 并发写导致数据损坏 上 session locking 包装器,写用 UpdateAsync 回 §2.4 高级持久化
E6 UGC 超 4,000 三角面/缺 _InnerCage 自动拒审,或游戏内穿透身体 减面、补内笼、Studio 五体型复测 回 §5.1 网格规格与 §5.4 Cage 要求

明确不做与去向

> 本技能只写 Roblox 平台特有的落地方式,不重述通用内容设计与通用网络原理。
> 通用玩法/关卡/经济设计 → game-content-design;通用网络架构与同步原理(权威模型、复制、延迟补偿)→ game-multiplayer-netcode;
> 通用美术管线与着色器 → game-tech-art;引擎架构与世界分区 → game-engine-engineering。
> 另:Roblox 政策与费率会变(价格档位、UGC 审核标准、三角面与贴图上限),本技能不代替当期官方条款核验,执行前须实访官方文档与 Creator Dashboard。

输出一致性保障(Stability)

  • 固定输出骨架:涉及平台落地时,输出必含「信任边界判定/DataStore 策略/合规与审核风险/落地步骤」四段,顺序固定;某段不涉及也写出并标「无」。
  • 每条断言携带证据:凡安全与数据结论,必须回挂具体 API(如 RemoteEvent:FireServer、game:BindToClose)与具体校验条件(类型、范围、冷却),不得只说「已加固」。
  • 幂等性:同一段脚本重复审计,漏洞清单应一致。若两次结论不同,说明存在未标出的平台不确定性(如速率限制边界)⇒ 须补标注,不得静默择一。
  • 关机零丢档:任何持久化方案须同时覆盖 PlayerRemoving 与 BindToClose() 两条路径;只写一条即为不合格输出。
  • 时效敏感项:价格档位、审核标准、网格与贴图上限、DataStore 速率限制、DevEx 规则均会变;引用了非当场实测的数值一律标「未核」并注明须实访官方。
  • 代码为模板非实跑:文中的 API 名与代码取自原文、未做独立运行验证,输出时须标明「须在 Studio 实跑复核」。

常见问题 FAQ(含正反对比)

Q1 服务器能不能调用 RemoteFunction:InvokeClient() 拿客户端数据?
- ❌ 能,方便服务器主动问客户端。
- ✅ 绝不能 —— 服务器向客户端发请求一律用 RemoteEvent 单向通知。
- 为什么:恶意客户端可让对方永久挂住服务器线程,一处即拖垮全场;服务器要的是客户端「上报」,不是「被询问」。

Q2 DataStore 存一次而已,需要包 pcall 和重试吗?
- ❌ 不需要,一次调用写成 SetAsync 就行。
- ✅ 必须包 pcall 并配指数退避重试(如 2 秒/4 秒/8 秒三档)。
- 为什么:DataStore 会失败,未保护的失败会永久损坏玩家数据;进度丢失是玩家永久流失的第一原因。

Q3 只在 Players.PlayerRemoving 里保存,够不够?
- ❌ 够,玩家离开就会触发。
- ✅ 不够 —— 必须同时挂 game:BindToClose()。
- 为什么:服务器关机不会逐个触发 PlayerRemoving,只挂前者会漏掉整个关机窗口的存档。

Q4 客户端先算出伤害再同步给服务器,不行吗?
- ❌ 行,客户端算得快,服务器收通知即可。
- ✅ 不行 —— 客户端只能「请求」动作,服务器「决定」是否兑现;伤害、货币、背包、位置权威全在服务器。
- 为什么:客户端是显示器不是真相源;把权威放客户端,利用者可直接篡改玩法状态。

Q5 配件网格做到 5,000 三角面,能过审吗?
- ❌ 差不多就行,审核不会卡那么细。
- ✅ 不行 —— 配件上限 4,000 三角面、打包部件 10,000,超限自动拒审。
- 为什么:审核是管线的一等公民,超限不会「视情况放行」,会直接被挡在门外;且规格会变,提交前须查当期要求。

Q6 分层服装只做外层网格,行不行?
- ❌ 行,外层就是玩家看得到的部分。
- ✅ 不行 —— 必须外层网格 + 内层笼网格(_InnerCage)双件齐备。
- 为什么:缺内笼,服装无法正确包裹身体,游戏内会穿透角色;这是技术性拒审与穿模的高频来源。

Q7 每日奖励能不能先不做,等体验成型再说?
- ❌ 能,先把核心玩法做完再谈留存。
- ✅ 不能颠倒顺序 —— 先建 DataStore 进度 → 上线前实现每日奖励 → 购买流最后建。
- 为什么:每日奖励依赖可用的进度系统、购买流依赖进度与货币;顺序颠倒会导致奖励与门控都无处落盘。

Q8 用倒计时制造稀缺、催玩家马上买,可以吗?
- ❌ 可以,这是常见促销手法。
- ✅ 不可以 —— 体验必须完整,不得用倒计时逼即时购买,也不得让免费玩法变得挫败。
- 为什么:Roblox 受众主体为未成年人,付费不得以暗黑模式制造人为稀缺;免费体验必须完整是平台政策底线。

完整示例(输入 → 判定 → 输出)

输入:「我做一个近战格斗体验,玩家点一下就扣对手的血 —— 客户端算好伤害再发给服务器,这样安全吗?」

判定:走 §一 信任边界与 §1.6 安全审计流程 —— 先审「客户端能否改服务器状态」→ 用三层校验重构 OnServerEvent → 确认血量权威归服务器。

输出(成品,无任何占位符):

-- ❌ 原写法(不安全,已否决):客户端算伤害,服务器只收通知
-- Remotes.RequestAttack.OnServerEvent:Connect(function(player, targetUserId, damage)
--     local t = Players:GetPlayerByUserId(targetUserId)
--     t.Character.Humanoid.Health -= damage    -- 伤害由客户端给,可被任意篡改
-- end)

-- ✅ 重构后:ServerStorage/Modules/CombatSystem.lua —— 三层校验通过后才改状态
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Remotes = ReplicatedStorage.Remotes          -- ReplicatedStorage/Remotes/RequestAttack
local CombatSystem, LAST_HIT = {}, {}

local WEAPON_RANGE, COOLDOWN, BASE_DAMAGE = 9, 0.45, 18   -- studs / 秒 / 单次伤害

local function rootOf(player: Player): BasePart?
    return player.Character and player.Character:FindFirstChild("HumanoidRootPart") :: BasePart?
end

local function onAttack(player: Player, targetUserId: number): ()
    -- ① 结构校验:只接受数字 userId,其余一律丢弃
    if type(targetUserId) ~= "number" then return end
    -- ② 冷却校验:服务器侧计时,不信任客户端声明的「刚冷却好」
    local last = LAST_HIT[player.UserId]
    if last and os.clock() - last < COOLDOWN then return end
    -- ③ 距离校验:目标必须在武器射程内
    local attacker = rootOf(player)
    local targetPlayer = Players:GetPlayerByUserId(targetUserId)
    local target = targetPlayer and rootOf(targetPlayer)
    if not (attacker and target) then return end
    if (attacker.Position - target.Position).Magnitude > WEAPON_RANGE then return end

    LAST_HIT[player.UserId] = os.clock()               -- 三层全过 → 服务器改状态
    local humanoid = targetPlayer.Character:FindFirstChildOfClass("Humanoid")
    if humanoid then
        humanoid.Health -= BASE_DAMAGE                 -- 伤害计算与扣除都在服务器
        Remotes.CombatConfirmed:FireAllClients(player.UserId, targetUserId)
    end
end

function CombatSystem.init(): ()
    Remotes.RequestAttack.OnServerEvent:Connect(onAttack)
end
return CombatSystem

审计结论:
- 信任边界:修复完成 —— 伤害值 BASE_DAMAGE 在服务器常量中,客户端改不了。
- 可被利用的 OnServerEvent:原写法 1 处 → 现 0 处(三层校验齐备)。
- 从服务器调用 RemoteFunction:InvokeClient():0 次。
- 待办(同类风险自查):货币与背包的变更须同样移回 EconomySystem/InventorySystem 的服务器模块;位置权威后续按同一模板复核。

常见问题

5 问
答案由本站依据条目字段整理
Roblox 平台开发怎么安装?

在支持 Skills 的客户端里执行:skillhub install user_63ad2463/roblox-platform-dev。安装方式为未标注。装完刷新技能列表或重开客户端。

Roblox 平台开发支持哪些客户端?

资料没有标注宿主客户端,但只要客户端支持 Skills(Claude、Codex、Cursor 等),一般都能加载。

Roblox 平台开发权限高吗,安全吗?

权限级别为未标注权限。安装前先看它会读取或写入哪些内容。

Roblox 平台开发收费吗?

本站不代收费用,也没有标注具体价格。是否收费取决于技能本身和所用的模型或客户端,正式使用前按作者说明确认。

Roblox 平台开发用什么许可证?

许可证标注为 未说明(许可证不明确)。商用或二次分发前请到仓库确认条款原文。

热门专题

按场景挑技能
全部专题 →

技能内容以作者仓库为准;分类、权限级别与许可证状态的中文说明为中文整理,最近核验 未标注。