如何根据名称从数组中删除特定的 children

How to remove specific children from an array depending on name

我正在创建一个 obby,对于我的其中一个关卡,我计划制作一个平台,当踏上该平台​​时,该平台会根据我为平台设置的这些“检查点”设置为传送到的位置而改变位置。我在资源管理器中有一个名为“级别”的文件夹,文件夹内是级别,我已经添加了构建级别所需的所有部分,并附加到 parent 部分。我已经使用 :GetChildren() 函数将所有 children 到级别 parent 部分添加到一个数组中,现在我正在尝试排序并删除任何不是检查点的部分。所有检查点都称为 Tele1、Tele2、Tele3 等...目前我正在使用 Table.remove,但我听说它很糟糕,永远不应该使用,但我也是一个新手,所以我不知道不知道还有什么办法可以解决这个问题。这是我的代码:

local checkpoints = game.Workspace.Levels.Level3:GetChildren()

for i, v in pairs(checkpoints) do
    if string.match(v.Name, "Tele") then
        
    else
        table.remove(checkpoints, i)
    end

    print(i, v)
end

正在打印以查看表格是否已正确排序。

首先,作为side-note,我建议将关卡文件夹存储在game.Workspace而不是ServerScriptStorage中。我下面的例子就是基于此。

与其从调用 GetChildren() 生成的 table 中删除部分,不如更轻松地遍历 table 并获取所有你认为是检查点的部分——例如:

-- The pattern that will be provided to string.match: it contains anchors
-- to the start and end of a string, and searches for 'Tele' followed by
-- one or more digits. This should be treated as a constant, hence the
-- capital letters.
local CHECKPOINT_PATTERN = "^Tele%d+$"

local serverStorage = game:GetService("ServerStorage")
local levels = serverStorage:FindFirstChild("Levels")
local level3 = levels:FindFirstChild("Level3")

-- Helper function to check if a particular part is a checkpoint.
-- Requires: part is a BasePart.
-- Effects : returns true if part.Name matches CHECKPOINT_PATTERN,
--           false otherwise.
local function is_checkpoint(part)
    return part.Name:match(CHECKPOINT_PATTERN) ~= nil
end

-- Get children of Level3, which should contain x number of checkpoints.
local children = level3:GetChildren()

-- Create a new table into which you will insert all parts you consider to
-- be checkpoints.
local checkpoints = {}

-- Iterate through the table children to find checkpoints.
for _, child in ipairs(children) do
    if (is_checkpoint(child)) then
        table.insert(checkpoints, child)
    end
end

-- To further abstract this process, the above for-loop could be placed
-- inside a function that returns a table of checkpoints; but, this is
-- entirely up to you and how you want to set up your code.

-- Continue with code, now that all checkpoints within Level3 have been
-- located and inserted into the table checkpoints.

这比修改 game.Workspace.Levels.Level3:GetChildren() 生成的原始 table 简单得多。

作为另一种更高级的解决方案,您可以使用 CollectionService 标记您认为是检查点的所有部分;这取决于您设置位置的精确程度;您可以通过调用 CollectionService:GetTagged(<tag>) 来检索包含这些检查点的 table。请参阅 Roblox Wiki 上的 this 页面以供参考。

编辑澄清:

我将其视为常量的变量称为 CHECKPOINT_PATTERN 是一个字符串模式;我使用它的作用与您的 string.match(v.Name, "Tele") 相同,尽管我的版本略有不同。解释一下:字符^$被称为锚点——前者表示模式匹配应该从字符串的开头开始,后者表示结束; "Tele" 与您的原始代码相同; "%d+" 匹配一个数字一次或多次。有关 Lua.

中字符串模式的更多信息,请参阅 this 页面

至于将 Levels 文件夹放在 ServerStorage 中的问题,这是一个好主意,因为它可以更好地在一个位置组织资源;而且,它比存储东西更安全,例如 game.Lighting。我建议这是一个很好的做法,但这当然取决于你的位置是如何设置的——如果这样做会删除你的整个 obby,那么需要对你的位置和代码进行一些重组才能使其工作。