Roblox Guidebook知识库
简体中文 ⌄

开发 / ROBLOX

Luau中的false设置:为什么默认值又把音乐打开了

通过原创的音乐偏好练习,保留玩家明确选择的false,只在数据缺失时使用默认值。先区分缺失数据、错误类型和有效的关闭状态,再连接菜单或存储。

更新日期:

先规定各个值的意义 #

想象一款虚构的岛屿漫步游戏,其中有独立的背景音乐设置。玩家主动关闭音乐,因此练习数据是false。新玩家尚未选择,输入则是nil。设计者希望只有第二种情况默认开启音乐。先写清这项约定,才能避免一个简短表达式把明确选择与信息缺失混为一谈。

本练习并不表示我们的现有游戏已经实现这个设置。我们从普通Luau函数和简单数值开始,没有连接Sound、DataStore、按钮或网络事件。之后这些部分仍需分别实现并在Studio中检查。先记录:true代表开启,false代表关闭,nil代表没有提供值。这是一项设计约定,不是对任意输入的自动解释。

重现or默认值的问题 #

表达式savedMusic or true看起来像一种方便的默认设置。然而,or并不是只检查数据是否缺失。官方参考说明:如果第一个操作数被视为真,返回它;否则返回第二个操作数。当savedMusic为false时,结果是true。玩家明确关闭的状态因此在读取后的解释阶段又被打开了。

先用false运行一个小例子并输出结果,再分别尝试true和nil。true保留,false和nil都会选择备用值。这是语言的行为,不能据此认定存储读取失败。在重新写入记录之前,检查解释输入的表达式:原本正确读取的数据,也可能在读取完成之后才被错误的备用值改变。

关闭选择被替换打开大图 ↗
备用值选择错误;原创教学示意图。
local savedMusic = false
print(savedMusic or true)
print(0 or 9)
print(true and false or true)

不要把零和空字符串当作关闭 #

在Luau的这种判断中,false和nil被视为假,数字0和空字符串则被视为真。因此0 or 9返回0;空字符串与备用文本通过or组合,也会保留空字符串。界面上的空标签不会必然得到你期望的提示文字。先检查收到的具体值,再判断显示问题发生在哪一层。

但对本练习而言,0仍然不是有效的关闭设置。我们的约定只允许布尔值,而不是任何具有某种真假表现的输入。字符串"false"同样不等于布尔值false。把这些情况加入错误输入列表。一个值能够通过if判断,不代表它类型正确,也不代表它是玩家确认过的合法选择。

用明确检查只替换nil #

booleanPreference函数首先检查raw==nil。只有这一分支返回约定的defaultValue。如果输入存在,函数另外检查type(raw)=="boolean"。真正的true和false原样传递;数字或字符串被拒绝,而不是悄悄替换。这样便能区分没有信息、明确关闭和格式错误三种情况。

本练习要求defaultValue本身也是布尔值。assert用于指出调用函数时的编程错误,并不是成品界面处理所有输入的完整策略。接入时还要确定合法默认值来自哪里、拒绝输入后应用采取什么行动。未经检查的玩家文本不应意外成为整个设置的默认选项。

local function booleanPreference(raw, defaultValue)
    assert(type(defaultValue) == "boolean")
    if raw == nil then
        return defaultValue, true
    end
    if type(raw) ~= "boolean" then
        return nil, false
    end
    return raw, true
end
local value, valid = booleanPreference(false, true)
print(value, valid)
value, valid = booleanPreference(nil, false)
print(value, valid)
value, valid = booleanPreference("false", true)
print(value, valid)

分开保存值和验证结果 #

函数返回两个结果:偏好值与valid。有效的关闭选择是false,true;拒绝输入则是nil,false。如果调用者只检查第一个结果,有效的关闭状态可能进入与错误相同的分支。先检查valid,再应用value。操作是否成功与成功获得的偏好是什么,是两个不同的问题。

未来的按钮处理器可以接收false,true并显示关闭状态。接收nil,false时,应进入事先设计的错误处理路径,而不是自动开启声音。本文章不替你决定完整产品策略;保留上一个确认状态并提示问题,可能适合你的项目。关键是不把输入遭到拒绝描述成玩家作出了新的选择。

三种不同结果打开大图 ↗
区分缺失、关闭和拒绝;原创示意图。

检查and/or缩写 #

有时会用condition and selectedValue or fallback简写选择逻辑。但它不能保留所有允许的selectedValue。如果condition为true,而selectedValue为false,中间结果就是false,之后or会选择fallback。因此true and false or true再次产生true。条件为真,并不能保证这个缩写保留一个为假的结果。

如果被选择的结果允许是false或nil,请使用明确分支。表达式短,并不证明正确。保留“条件为真、选中值为false”的测试:只有true的例子无法发现这个问题。已有的阈值教程讨论选择第一个匹配的数字分支;这里的独立任务,则是保留语言视为假的有效结果。

运行输入矩阵 #

分别检查正确情况:false配合默认true,必须返回false,true;true配合默认false,必须返回true,true;nil配合默认true,返回true,true。再加入nil配合默认false这一反向缺失情况。运行前写下预期,否则意外开启的结果可能被误当作新的正确行为。

之后传入0、空字符串、字符串"false"和数字1。按照本练习约定,它们都应返回nil,false。检查两个返回值,不要只看执行是否崩溃。原创assertions已经在独立Luau解释器中实际执行;这验证了列出的数据操作,但没有验证Roblox里的音乐声音、按钮交互或偏好保存过程。

输入结果
falsefalse, true
truetrue, true
nildefaultValue, true
0 / "false"nil, false

把菜单接入作为另一个阶段 #

函数正确后,说明输入来源、读取何时完成,以及菜单接受哪一个已确认状态。重新打开面板,应保留关闭的偏好。缺失数据应在约定场景下使用默认值。再次绘制同一面板,不应该只因为界面重复显示,就把false重新解释为没有数据。

不要把通过纯数据测试扩展成DataStore或服务器已经正常的结论。加载失败、记录不存在和类型被拒绝,可能需要不同处理。服务器检查与可靠错误路径仍是独立任务。不要仅因面板在读取完成前出现,就用备用值覆盖记录。实施持久化之前,先规定这些时序情况。

留下可以复现的交接记录 #

记录允许类型、nil的意义、两个返回值和拒绝情况。附上源文件及实际测试结果。这比“音乐修好了”更有用:另一位开发者无需进入你的游戏会话,也能重复数据测试。使用虚构输入,避免在教学文件中放入真实玩家标识或访问凭证。

如果约定后来改变,应同时更新函数、预期和说明。例如支持一个字符串表示的新模式,需要明确转换和新的测试,而不是直接删除类型检查。把产品决定与语言行为分开:官方参考解释操作符如何运作,你的项目规定哪些偏好值有意义并被允许。

交接前检查最终结果 #

练习成功的标准是:保存的false仍是false,nil只得到约定的默认值,不支持的类型产生独立拒绝。测试两个可能的defaultValue以及重复调用。确认调用代码通过valid判断结果能否应用。检查允许false作为有效结果的地方,有没有使用危险的and/or缩写。

实际接入后,再在Studio的真实面板中重复检查,并另外测试保存和重新读取。这些是未来验证步骤,不是已经完成的游戏观察。原创例子与官方来源解释错误机制,并不意味着现有游戏已经修改。把已确认的函数结果与后来游戏中的实际结果分开记录。

检查行动
类型boolean
缺失值单独的nil分支
结果分开value与valid
集成在Studio中检查

原始资料

Roblox Creator Hub — Operators