Lua Roblox API:我如何去抖一个 player/character 碰到盒子

Lua Roblox API: How can I debounce a player/character that runs into a box

背景: 承载最小的物体。只是一个播放器和一个漂浮在空中并被锚定的部分(矩形棱柱)。

老实说,我不明白引擎盖下发生了什么,所以很难弄清楚。在没有去抖动的情况下,在事件触发时,回调函数由 connect() 或事件处理程序(不确定)调用,并且在没有去抖动的情况下,当打印语句在输出框中重复时,该函数会被多次调用。因此,使用存储去抖标志的变量(布尔类型)可以解决它。然后,当玩家的模型开箱即用时,我会尝试“去抖动”。但是,我不知道如何正确地做到这一点。

这是我的代码尝试:

local box = game.Workspace.BoxModel;
local debounce = false;

local function onTouchedDebounced()
    if (debounce == false)
    then
        debounce = true;
        print("Hello! onTouchedDebounced() has run.");
        box.Touched:Connect(onTouchedDebounced));
    end
end

local function onTouchedUndebounced()
    if (debounce == true) 
    then
        print("Hello! onTouchedUndebounced() has run.");
        debounce = false;
    end 
end

box.Touched:Connect(onTouchedDebounced);
box.TouchEnded:Connect(onTouchedUndebounced);

您正在做的事情的核心是合理的:在第一个事件之后开始阻塞,并在一段时间后解除阻塞。如果这是通过按下按钮或 mouse-clicks,您的解决方案就可以正常工作。 Touched 事件使这变得复杂,因为它会触发任何接触它的部分,并且玩家的角色可能有多个接触点。

Touched and TouchEndeded 事件为您提供了对已接触零件的实例的引用。

如果目标是只为每个玩家触发一次盒子事件或在任何人触摸它时触发一次,您可以保留当前触摸盒子的部分的字典。当一个部分接触时,你增加一个计数器。当一个部分停止时,您将其递减。只有在所有触摸点都被移除后,您才能移除 debounced 标志。

local box = game.Workspace.BoxModel
local playersTouching = {} --<string playerName, int totalParts>

local function onTouchedDebounced(otherPart)
    -- check that the thing that touched is a player
    local playerModel = otherPart.Parent
    if not playerModel:IsA("Model") then
        warn(otherPart.Name .. " isn't a child of a character. Exiting")
        return
    end

    -- check whether this player is already touching the box
    local playerName = playerModel.Name
    local total = playersTouching[playerName]
    if total and total > 0 then
        warn(playerName .. " is already touching the box")
        playersTouching[playerName] = total + 1
        return
    end

    -- handle a new player touching the box
    playersTouching[playerName] = 1

    -- Do a thing here that you only want to happen once per event...
    print(string.format("Hello! onTouchedDebounced() has ran with %s and %s", playerName, otherPart.Name))    
end

local function onTouchedUndebounced(otherPart)
    -- decrement the counter for this player
    local playerName = otherPart.Parent.Name
    if playersTouching[playerName] == nil then
        return
    end

    local newTotal = playersTouching[playerName] - 1
    playersTouching[playerName] = newTotal

    -- if the total is back down to zero, clear the debounce flag
    if newTotal == 0 then
        playersTouching[playerName] = nil
        print(string.format("Hello! onTouchedUndebounced() has ran and %s has no more touching parts", playerName))
    end
end


box.Touched:Connect(onTouchedDebounced)
box.TouchEnded:Connect(onTouchedUndebounced)