脚本功能让你控制脚本在 DataModel 子树内能够执行的操作。与默认的“全有或全无”系统相反,您可以设置脚本仅能够访问某些类别,例如音频、物理、数据存储等。
- 此系统使您能够限制从工具箱中获取的模型可以做的事情,并且更容易将用户生成的内容包含在游戏中。
- 它还可以帮助确保允许玩家运行自己代码的游戏更具安全性,这些代码通常在受限或模拟的环境中执行。
- 它还可以用于共享限制自己可能做的操作的库。例如,提供额外数学方法的库可以限制为其所需的最小功能集,以便使用该库的其他开发者不必验证整个代码库,确保没有恶意代码。
启用脚本功能
要启用此功能,请在 Explorer 和 Properties 窗口中将 SandboxedInstanceMode 属性从 Default 更改为 Experimental。
沙箱容器
脚本功能引入了一个 沙箱容器 的概念。Models、Folders、Scripts 或这些类的任何后代都有一个在 Properties 窗口中可用的 Sandboxed 属性。

启用 Sandboxed 属性将该实例指定为 DataModel 树内的沙箱容器,这限制了该容器内的脚本可以执行的操作,具体取决于 Capabilities 属性中的值集。
功能
Capabilities 属性是一组值,用于控制执行的不同方面。功能分为以下几个大类:
- 执行控制 - 指定脚本是否可以在客户端或服务器上运行
- 实例访问控制 - 指定脚本可以与哪些 DataModel 部件进行交互
- 脚本功能控制 - 指定脚本可以调用哪些 Luau 函数
- 引擎 API 访问控制 - 指定可以使用 Roblox 引擎 API 的哪些部分
当脚本尝试执行不在功能集中的操作时,Roblox 会报告错误。错误通常包括尝试的操作、操作的目标以及缺失的第一个能力:
当前线程无法修改 'Workspace'(缺少能力 AccessOutsideWrite)当前线程无法调用 'Clone'(缺少能力 CreateInstances)当前线程无法调用 'GetSecret'(缺少能力 Network)
执行控制
有两项功能处理执行控制:
如果脚本是 Enabled,但尝试启动的地方对应的能力不可用,则会在 Output 窗口中显示警告信息。如果一个脚本不应该在该上下文中运行,请禁用或删除它。
请注意,ModuleScripts 无需具备这些执行功能以被要求。
当由于缺少执行控制能力而导致脚本无法启动时,会在输出中以警告方式报告,例如:
无法启动服务器脚本 'Script'(缺少能力 RunServerScript)
实例访问控制
唯一一项功能处理实例访问控制:
- AccessOutsideWrite - 允许脚本从沙箱容器外部获取和接收实例
当此功能不可用时,脚本只能查找属于其自身沙箱容器的实例。例如,如果脚本直接放置在沙箱容器中,则 script.Parent.Parent 返回 nil。
此外,任何传入 Instance 的 Roblox API 事件在沙箱容器外部都将传入 nil。例如,若 BasePart.Touched 由沙箱容器外部的实例触发,该事件仍然会收到,但参数为 nil。
避免设置此功能;当脚本可以与游戏中的任何实例交互时,沙箱的保证会减弱。
对服务的访问
即使没有 AccessOutsideWrite,沙箱容器中的脚本仍可以访问 game、workspace 和服务。此访问是为了让脚本仍能调用这些全局变量的有用方法,例如 DataModel.GetService,但访问其子实例仍会进行验证。
内部传递的实例
如果通过不经过 Roblox API 的函数调用传递一个实例,引用将被保留。然而,如果以这种方式传递了一个 ModuleScript,则不能被要求而不具备 AccessOutsideWrite。这是因为 ModuleScript 的返回值通常是可变的,并且可能被沙箱容器中的脚本修改。
脚本功能控制
这一组功能控制一些脚本的基本方面:
- LoadString - 脚本被允许调用 loadstring
请记住,默认的函数限制仍然适用。即使 LoadString 已启用,游戏仍需在 ServerScriptService 中启用它,并且仍然仅在服务器上可用。
要创建新实例,除了 CreateInstances,还需要提供对该实例的额外引擎 API 功能。
引擎 API 访问控制
最后一组功能控制脚本对各种引擎 API 的访问:
- Animation - 访问与动画相关的实例
- AssetCreateUpdate - 访问与创建或更新资产相关的引擎 API
- AssetManagement - 访问与执行对资产的操作(非读取、创建或更新)相关的引擎 API
- AssetRead - 访问与获取资产信息相关的引擎 API
- Audio - 访问与音频 API 相关的实例
- AvatarAppearance - 访问与头像视觉元素相关的实例
- AvatarBehavior - 访问与控制或修改人形生物相关的引擎 API
- Basic - 访问提供较少风险的一般 API
- CSG - 访问与构造固体几何体(CSG)相关的实例和函数
- CapabilityControl - 访问修改实例的 Sandboxed 和 Capabilities 属性
- Capture - 访问与在用户屏幕上捕捉屏幕截图或视频相关的引擎 API
- Chat - 访问与游戏内聊天相关的实例
- Consequences - 访问用于惩罚用户的 API(踢出或封禁)
- DataStore - 访问数据存储和内存存储 API
- DynamicGeneration - 访问与动态修改资产相关的引擎 API
- Environment - 访问与环境显示控制相关的实例
- Groups - 访问与小组/社区相关的引擎 API
- Input - 访问与用户输入相关的实例
- LegacySound - 访问与将被弃用的声音相关的引擎 API
- LoadOwnedAsset - 访问与加载您拥有的、与您共享的、由 Roblox 拥有的或是良性资产类型的资产相关的引擎 API
- Logging - 访问日志 API
- Material - 访问与材料相关的引擎 API
- Monetization - 访问与游戏货币化相关的引擎 API,通常不包括大多数 PromptPurchases
- Network - 访问 HTTP 网络 API
- Physics - 访问与物理相关的实例
- PlatformAvatarEditing - 访问与创建或更新头像相关的引擎 API,或辅助此操作的 API
- PromptExternalPurchase - 允许访问与提示购买任意资产相关的引擎 API
- RemoteEvent - 访问用于内部网络操作的实例
- SensitiveInput - 访问与捕获用户敏感输入相关的引擎 API,即高隐私硬件传感器。
- ServerCommunication - 访问与跨服务器通信相关的引擎 API,例如 MessagingService
- Social - 访问与社交功能相关的引擎 API,例如好友和邀请
- Teleport - 访问与传送相关的引擎 API
- UI - 访问与用户界面相关的实例
每个类、属性、方法和事件的功能在 引擎 API 参考 中显示。例如, Player:GetFriendsOnlineAsync() 需要 Player 和 Social 权限。
许多 HttpService 方法可以在没有其他功能的情况下使用,前提是能够执行脚本:
如果在没有所需的功能的情况下访问实例的属性或方法,将报告一个错误,描述缺失的功能。
最后,功能并未涵盖今天 Roblox 引擎中的每个实例。本节或下一节中未列出的实例无法通过沙箱容器进行交互,并将抛出错误,指示当前脚本不可用的 Unassigned 功能。
另一个限制是 getfenv() 和 setfenv() 函数在沙箱容器中的脚本中不可用。从沙箱脚本调用它们会报告:
当前线程无法调用 ['getfenv'/'setfenv'] - 目标使用的 API 在当前沙箱中不可用
仅脚本访问实例受到限制。实例本身仍然可以在沙箱容器内独立存在和操作。灯光仍然照耀,用户界面仍然可见,已接线的音频设置播放声音。
容器之间的交互
嵌套容器
当一个沙箱容器嵌套在另一个容器内时,内部容器的实例对外部容器可访问。
内部容器的功能受到外部容器功能的限制。例如,如果外部容器具有 Basic、Audio 和 CSG 的功能,而内部容器具有 Basic 和 Network,则在运行时,只有 Basic 功能可用于内部容器。
如果内部容器与外部容器之间没有共同功能,则结果功能集为空。
可绑定的函数和事件
BindableEvent 和 BindableFunction 提供了与容器进行通信或允许其运行回调的最佳方式,即便该容器自身不被允许直接使用这些功能。
当触发事件或调用函数时,连接将在注册它们的函数上下文中执行。这意味着,如果事件或函数回调由沙箱容器注册,则它会在该容器的功能下被调用。如果回调是由外部代码注册的,当沙箱容器脚本调用它们时,它们将以可供您函数使用的功能执行。
值得注意的是,即使具有 AccessOutsideWrite 功能,沙箱容器中的脚本也无法调用其容器外的事件或函数,如果它们的功能集大于容器本身。
当沙箱脚本尝试触发或调用功能或事件(BindableEvent、BindableFunction 或 RemoteEvent)时,而其祖先功能超过其自身的情况下,会报告错误并指出需检查的属性。
如果目标不在任何沙箱容器内:
当前线程无法触发 '<Target>',因为 '<Target>' 的 Sandbox 属性设置为 false,但调用线程为沙箱
要解决此问题,请将目标的 Sandboxed 设置为 true。或者,您可以修改调用线程的来源,使 Sandboxed 设置为 false,但这并不推荐,因为这会消除沙箱提供的安全优势。
如果目标已被沙箱化但具有调用者缺少的功能:
当前线程无法触发 '<Target>',因为 '<Target>' 的 Capabilities 属性具有附加值:<First Missing Capability> (以及 N 个其他)
为了解决此问题,请将目标的 Capabilities 缩小为调用者能力的一个子集,或者扩展调用者的 Capabilities 以匹配目标的。
模块要求
内部的 ModuleScripts 可以如常被沙箱容器要求。然而,如果目标实例在容器外部,则只有在可以使用的功能集小于或等于容器可用的功能时,才可以对其进行要求。
此限制不适用于 RunClientScript 和 RunServerScript 功能。如果 ModuleScript 被放置在仅有 RunClientScript 的容器中,但从具有 RunServerScript 能力的脚本中被要求,则允许成功并在服务器上运行这些功能。
当 require() 在能力不匹配时失败时,错误会以与上节中描述的可绑定函数和事件类似的方式指出目标模块及需检查的属性。
直接调用的函数
如果在沙箱容器内的 ModuleScript 从容器外被要求,则某些保护机制将不可用。特别是,目标函数可以访问调用者可用的所有实例。如果调用者不在沙箱容器内,则该调用就像具有 AccessOutsideWrite 可以使用一样。
其他功能限制仍然适用。如果您具有 DataStore 访问能力,但目标模块没有,就无法调用 DataStore 方法。但是,如果您传递的是处理 DataStore 的自定义函数,则目标可以在该调用期间运行它。 如果目标使用类似于 task 中的方法调度线程,则这些线程将失去调用该函数的能力。
实例可以传递给目标模块或分配给模块字段。
如有必要,建议使用 rawset 来分配表成员,以避免执行可能在表上设置的 __index/__newindex 元方法。
总体建议是在可能的情况下使用 BindableEvent 和 BindableFunction 进行通信。
实例移动
大多数实例在容器之间移动没有限制。然而,脚本实例只能被移动到具有相同能力集或这些能力的子集的容器中。
这意味着带有 AccessOutsideWrite 的沙箱容器不能仅仅将脚本再父级到本身以外以获取更多功能。