【问题标题】:How to remove specific children from an array depending on name如何根据名称从数组中删除特定的孩子
【发布时间】:2021-01-07 18:35:59
【问题描述】:

我正在创建一个 obby,对于我的一个关卡,我计划制作一个平台,当踩到该平台时,我会根据我为平台传送到的这些“检查点”设置的位置来改变位置。我在资源管理器中有一个名为“Levels”的文件夹,文件夹内是关卡,我添加了构建附加到父部件的关卡所需的所有部件。我已经使用 :GetChildren() 函数将所有子级添加到父级部分的数组中,现在我正在尝试排序并删除任何不是检查点的部分。所有检查点都称为 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

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

【问题讨论】:

    标签: arrays sorting lua roblox


    【解决方案1】:

    首先,作为旁注,我建议不要将级别文件夹存储在game.Workspace 中,而是在ServerScriptStorage 中。我下面的例子就是以此为基础的。

    您可以更轻松地遍历该表并获取您认为是检查点的所有部分,而不是从调用 GetChildren() 生成的表中删除部分,例如:

    -- 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()生成的原始表要简单得多。

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

    编辑澄清:

    变量(我将其视为常量)称为CHECKPOINT_PATTERN 是一个字符串模式;我使用它的角色与您的string.match(v.Name, "Tele") 相同,尽管我的版本略有不同。解释一下:^$这两个字符被称为anchors——前者意味着模式匹配应该从字符串的前面开始,后者也一样但表示结束; "Tele" 与您的原始代码相同; "%d+" 匹配一个数字一次或多次。有关 Lua 中字符串模式的更多信息,请参阅 this 页面。

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

    【讨论】:

    • 我在编程方面还不是很先进,但我很确定我明白这里发生了什么,但是如果可以的话,我只是有几个问题。首先,^Tele%d+$ 到底在做什么?我不知道 ^, %, d+$ 在这种情况下是什么意思,最后当我将 Levels 文件夹放在服务器存储中时,整个 obby 就从地图上消失了。我该如何解决?也感谢您的帮助!
    • 我刚刚发布了一些编辑。我希望他们能把事情弄清楚!
    • 好的,所以我创建了一个新脚本并将其放入 ServerScriptService 中,如下所示。我创建了一个脚本来复制我的地图并将其从 ServerStorage 放入 Workspace。我在关卡文件夹中创建了文件夹,以将所有片段放入我的关卡,而不是将所有这些片段作为父级锚定到游戏中的某个部分。我实现了你的代码,我收到一个错误,上面写着“12:52:00.155 - Workspace.Levels.Level3.Platform.Script:12: 尝试调用 nil 值”,我认为它与 @987654340 有关@ 部分。我似乎无法解决这个问题
    • Match 不应大写。试试part.Name:match(CHECKPOINT_PATTERN) ~= nil——注意小写的match
    • 这么小的东西竟然能破坏一切,真是太有趣了。这确实解决了手头的问题,但我希望你不介意我再问一个问题!我感谢您已经给我的所有帮助,这些只是为了更好地澄清。我最初将脚本附加到我想使用的平台部分,但我决定将脚本放入 ServerScriptService。这是脚本更好的地方吗?可以将脚本附加到零件吗?在地图上工作时,我是否应该将地图放在工作区中,但在不处理地图时将其放在 ServerStorage 中?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-27
    • 1970-01-01
    • 2019-12-15
    • 2011-09-01
    • 1970-01-01
    • 2020-01-17
    相关资源
    最近更新 更多