制作互动游戏通常意味着操作对象的属性和属性值:
属性是对象类的一部分。例如,BasePart.Anchored 属性控制零件的物理行为。在田径比赛中,您可能希望在盘或标枪落地的瞬间将其固定,以便玩家能够直观地了解它的飞行距离。
属性值实质上是您定义的自定义属性。例如,Plant 参考项目使用属性值设置种子的购买价格和一个花盆能够容纳的最大植物尺寸。
复制顺序
在开始检索和操作对象之前,必须理解复制顺序。
Roblox 引擎不保证从服务器到客户端的对象(及其更改)的复制顺序,这使得 Instance:WaitForChild() 方法在客户端脚本中访问对象,尤其是 Workspace 中的对象,变得至关重要。
例如,如果服务器脚本更改了工作区中某个实例的属性,然后调用 RemoteEvent:FireAllClients(),则属性更改可能会在 RemoteEvent.OnClientEvent 触发之前或之后复制到客户端。请使用可用的方法和事件来 检测变化,而不要假设某个更改已复制。同类型的更改,例如两个属性值更改,通常 确实 按顺序到达。
当客户端首次启动游戏时,某些复制和脚本执行的方面是可预测的:
客户端加载 ReplicatedFirst 的内容,例如加载屏幕、资产和脚本。
LocalScripts(以及 Scripts,其 RunContext 为 Client)在 ReplicatedFirst 中运行。这些脚本可以安全地从 ReplicatedFirst 中获取对象,而无需使用 Instance:WaitForChild():
-- 安全local ReplicatedFirst = game:GetService("ReplicatedFirst")local LoadingScreen = require(ReplicatedFirst.LoadingScreen)这些脚本 不能 安全地从其他 服务 中获取对象,因为它们可能还没有加载:
-- 不安全local ReplicatedStorage = game:GetService("ReplicatedStorage")local PickupManager = require(ReplicatedStorage.PickupManager)您 可以 在这些脚本中使用 WaitForChild() 来从其他服务中获取对象,但这样做会消减使用 ReplicatedFirst 的好处。
客户端继续加载游戏的其余部分。
当它完成时,Loaded 事件触发,IsLoaded() 返回 true。
Players.[Player].PlayerScripts 中的 LocalScripts(从 StarterPlayerScripts 复制)运行,此外在 ReplicatedStorage 中的客户端 Scripts 也运行。这些脚本可以安全地从 ReplicatedStorage 中获取对象,而无需使用 WaitForChild()。
玩家的人物模型 Character 在游戏中生成。
Workspace.[Character] 中的 LocalScripts(从 StarterCharacterScripts 复制)运行。
如果您的游戏使用 实例流式加载(Workspace.StreamingEnabled),某些或大多数对象可能尚未加载到工作区,因此使用 WaitForChild() 访问工作区对象变得更加重要的安全措施。有关加载和调整流式行为的更多信息,请参见 流入 和 每模型流式控件。
获取对象
修改对象属性和属性值的第一步是获取对该对象的引用。最简单的解决方案是将脚本作为对象的子项放入 资源管理器 中,并使用 script.Parent 来引用对象。

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

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 用户界面中创建它们并设置默认值。然后,您可以使用脚本根据玩家的操作修改它们的值。

有关如何在 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) --> Name
print(cabbage[property]) --> Cabbage1
end
end
local function onAnyAttributeChange(attribute)
print(attribute) --> Grow, GrowthRate
print(cabbage:GetAttribute(attribute)) --> false, 3
end
-- 监听变化并连接到本地函数
cabbage.Changed:Connect(onAnyPropertyChange)
cabbage.AttributeChanged:Connect(onAnyAttributeChange)
-- 监听变化并连接到匿名函数
cabbage:GetPropertyChangedSignal("Name"):Connect(function()
print(cabbage.Name) --> Cabbage1
end)
cabbage:GetAttributeChangedSignal("GrowthRate"):Connect(function()
print(cabbage:GetAttribute("GrowthRate")) --> 3
end)
-- 触发 Changed 和 GetPropertyChangedSignal()
cabbage.Name = "Cabbage1"
-- 触发 Changed 和 AttributeChanged
cabbage:SetAttribute("Grow", false)
-- 触发 Changed、AttributeChanged 和 GetAttributeChangedSignal()
cabbage:SetAttribute("GrowthRate", 3)