使体验互动往往意味着操纵对象属性和特性:
属性是对象类的一部分。例如,BasePart.Anchored 属性控制零件的物理。在轨道和田径体验中,你可能想在它落地的那一刻锚定一枚铅球或标枪,以便玩家知道它飞行了多远。
属性实际上是您定义的自定义属性。例如,植物参考项目使用属性来设置种子的购买价格和一个盆子可以容纳的最大植物尺寸。
复制顺序
在开始检索和操作对象之前,您必须了解复制顺序。
Roblox 引擎不保证对象从服务器复制到客户端的顺序,这使得 Instance:WaitForChild() 方法对在客户端脚本中访问对象特别是 Workspace 对象至关重要。然而,过程的某些方面是可预测的:
客户端加载 ReplicatedFirst 的内容,例如加载屏幕、资产和脚本。
LocalScripts (和 Scripts 使用 RunContext 的 Client)在 ReplicatedFirst 奔跑中。这些脚本可以安全地从 ReplicatedFirst 中获取对象,而不使用 WaitForChild() :
-- 安全local ReplicatedFirst = game:GetService("ReplicatedFirst")local LoadingScreen = require(ReplicatedFirst.LoadingScreen)这些脚本 无法 安全地从其他 服务 获取对象,因为它们可能还没有加载:
-- 不安全local ReplicatedStorage = game:GetService("ReplicatedStorage")local PickupManager = require(ReplicatedStorage.PickupManager)你 可以 在这些脚本中使用 WaitForChild() 从其他服务获取对象,但这样做会抵消使用 ReplicatedFirst 的好处。
客户端继续加载体验的剩余部分。
当它完成时,事件 发生,并返回真值。
LocalScripts 在 Players.Player.PlayerScripts (从 StarterPlayerScripts 复制)奔跑,以及客户端 Scripts 在 ReplicatedStorage 。这些脚本可以安全地从 ReplicatedStorage 中获取对象,而不使用 WaitForChild() 。
玩家的Character在体验中生成。
LocalScripts 在 Workspace.Character (从 StarterCharacterScripts 复制)奔跑。
如果您的体验使用 实例流媒体 ( Workspace.StreamingEnabled ),一些或大多数对象可能未加载到工作区,因此使用 WaitForChild() 访问工作区对象成为更重要的安全措施。特别是,请参阅在中的流和每个模型的流控制以获取有关加载和调优流行为的额外信息。
获取对象
修改对象属性和特性的第一步是获取对象的引用。最简单的解决方案是将脚本作为 Explorer 中对象的子对象,并使用 script.Parent 来引用对象。

local sign = script.Parent
更通用的解决方案是使用方法如 或 Instance:WaitForChild() 从 Instance:FindFirstChild() 获取对象。

local ReplicatedStorage = game:GetService("ReplicatedStorage")local signsFolder = ReplicatedStorage:WaitForChild("Signs")local sign = signsFolder:WaitForChild("InteractiveSign")
修改属性
属性很容易访问 — 只需使用对象引用后的 . — 但如果你正在使用模型,你可能需要选择模型而不是模型本身。

local ReplicatedStorage = game:GetService("ReplicatedStorage")local chair = ReplicatedStorage:WaitForChild("Chair")chair.LeftArmRest.Size = Vector3.new(10, 1, 10)
创建属性
虽然您可以通过编程创建属性,但更常见的解决方案是在 Studio 用户界面中创建它们以默认值。然后,您可以使用脚本来在回应玩家操作时修改其值。

有关在工作室创建属性的信息,请参阅实例属性。
设置属性
要修改特性的值,请使用名称和值调用 Instance:SetAttribute() 。
创建或修改属性
local cabbage = script.Parentcabbage:SetAttribute("Harvestable", true)
如果特性尚未存在,该方法将创建它。
获取属性值
要获取现有属性的值,请在实例上调用 Instance:GetAttribute() 。
获取属性值
local cabbage = script.Parentcabbage:SetAttribute("Harvestable", true)local isHarvestable = cabbage:GetAttribute("Harvestable")print(isHarvestable) --> true
同样,您可以通过调用 Instance:GetAttributes() 获得所有属性。该方法返回一个键值对象典词。
获取所有属性
local cabbage = script.Parentlocal cabbageAttributes = cabbage:GetAttributes()print(cabbageAttributes.GrowthRate) --> 2for k, v in cabbageAttributes doprint(k, v)end
删除属性
要删除特性,将其值设置为 nil .
删除属性
local cabbage = script.Parentcabbage:SetAttribute("GrowthRate", nil)
检测更改
有几种方法可以监听属性和特性的更改:
- Instance.AttributeChanged 事件听到任何属性的更改,并将更改的属性名称作为参数传递。
- Instance:GetPropertyChangedSignal() 方法可让您监听一个属性的更改并传递无参数。
- Instance:GetAttributeChangedSignal() 方法可让您监听一个属性的更改并传递无参数。
由于这些事件和方法作为参数传递的最少信息,所有都适合用于匿名函数,特别是 Instance:GetPropertyChangedSignal() 和 Instance:GetAttributeChangedSignal() 。了解有关匿名函数和与事件工作的更多信息,请参阅事件。
收听更改
local cabbage = script.Parent
-- 本地函数
local function onAnyPropertyChange(property)
-- 忽略对属性的更改
if property ~= "Attributes" then
print(property) --> 名称
print(cabbage[property]) --> 柿子1
end
end
local function onAnyAttributeChange(attribute)
print(attribute) --> 增长,增长率
print(cabbage:GetAttribute(attribute)) --> 错误,3
end
-- 监听更改并连接到本地函数
cabbage.Changed:Connect(onAnyPropertyChange)
cabbage.AttributeChanged:Connect(onAnyAttributeChange)
-- 监听更改并连接到匿名函数
cabbage:GetPropertyChangedSignal("Name"):Connect(function()
print(cabbage.Name) --> 柿子1
end)
cabbage:GetAttributeChangedSignal("GrowthRate"):Connect(function()
print(cabbage:GetAttribute("GrowthRate")) --> 3
end)
-- 火焰更改和获取属性更改信号()
cabbage.Name = "Cabbage1"
-- 火焰更改和属性更改
cabbage:SetAttribute("Grow", false)
-- 火焰更改、属性更改和获取属性更改信号()
cabbage:SetAttribute("GrowthRate", 3)