取消模式模式

*此内容使用人工智能(Beta)翻译,可能包含错误。若要查看英文页面,请点按 此处

一个 缓冲 模式是一种编程技巧,可以防止函数运行太多次或输入触发多次。以下脚本示例展示了将缓冲作为最佳实践。

检测碰撞

假设你想创建一个危险陷阱部件,触碰时造成 10 伤害。初始实现可能使用基本 BasePart.Touched 连接和一个像这样的 damagePlayer 函数:

脚本 - 伤害玩家

local part = script.Parent
local function damagePlayer(otherPart)
print(part.Name .. " collided with " .. otherPart.Name)
local humanoid = otherPart.Parent:FindFirstChildWhichIsA("Humanoid")
if humanoid then
humanoid.Health -= 10 -- 减少玩家生命值
end
end
part.Touched:Connect(damagePlayer)

虽然在第一印象中是有道理的,但在测试中会显示出 Touched 事件在快速连续的基础上多次触发细微的物理碰撞,导致多次触发。

为了避免在初始联系时造成过多伤害,您可以通过添加一个缓冲系统来强制在 实例属性 通过造成伤害的冷却期。

脚本 - 使用 Debounce 伤害玩家

local part = script.Parent
local RESET_TIME = 1
local function damagePlayer(otherPart)
print(part.Name .. " collided with " .. otherPart.Name)
local humanoid = otherPart.Parent:FindFirstChildWhichIsA("Humanoid")
if humanoid then
if not part:GetAttribute("Touched") then
part:SetAttribute("Touched", true) -- 将属性设置为真值
humanoid.Health -= 10 -- 减少玩家生命值
task.wait(RESET_TIME) -- 等待重置时间
part:SetAttribute("Touched", false) -- 重置属性
end
end
end
part.Touched:Connect(damagePlayer)

触发声音

缓冲也有用于处理声音效果,例如当两个部分碰撞时播放声音(Touched,或在用户与屏幕上的按钮互动时播放声音的Activated事件。在两种情况下,调用 Sound:Play() 将从其轨道的开始开始播放,而且没有缓冲系统,声音可能在短时间内多次快速播放。

为了防止声音重叠,您可以使用 IsPlaying 对象的 Sound 属性来减缓冲击:

脚本 - 使用 Debounce 播放碰撞声音

local projectile = script.Parent
local function playSound()
-- 在零件上找到子音效
local sound = projectile:FindFirstChild("Impact")
-- 只播放声音,如果它还没有播放
if sound and not sound.IsPlaying then
sound:Play()
end
end
projectile.Touched:Connect(playSound)
脚本 - 使用 Debounce 播放按钮单击

local button = script.Parent
local function onButtonActivated()
-- 在按钮上找到子音效
local sound = button:FindFirstChild("Click")
-- 只播放声音,如果它还没有播放
if sound and not sound.IsPlaying then
sound:Play()
end
end
button.Activated:Connect(onButtonActivated)

拾取效果

经验往往包括在 3D 世界中的收藏品拾取,例如医疗包、弹药包和更多。如果您设计这些拾取以在世界上保留,让玩家再次拾取和再次激活,那么在拾取刷新和重新激活之前应该添加一个“冷却”时间。

检测碰撞类似,您可以使用实例属性来管理缓冲状态,并通过修改零件的Transparency

脚本 - 使用 Debounce 拾取健康状况

local part = script.Parent
part.Anchored = true
part.CanCollide = false
local COOLDOWN_TIME = 5
local function healPlayer(otherPart)
local humanoid = otherPart.Parent:FindFirstChildWhichIsA("Humanoid")
if humanoid then
if not part:GetAttribute("CoolingDown") then
part:SetAttribute("CoolingDown", true) -- 将属性设置为真值
humanoid.Health += 25 -- 增加玩家生命值
part.Transparency = 0.75 -- 使零件部分透明以显示冷却状态
task.wait(COOLDOWN_TIME) -- 等待冷却时间
part.Transparency = 0 -- 将零件重置为完全不透明
part:SetAttribute("CoolingDown", false) -- 重置属性
end
end
end
part.Touched:Connect(healPlayer)