Loading...
Loading...
Compare original and translation side by side
Every entry here represents a real production footgun that has caused data loss, exploits, crashes, or hours of debugging in Roblox games.Severity Levels:
- Critical - Data loss, security breach, or revenue loss. Fix before shipping.
- High - Server instability, degraded experience, or exploit surface. Fix in current sprint.
- Medium - Correctness bugs, performance issues, or dev confusion. Fix before scale.
- Low - Code quality, maintainability, or minor timing issues. Fix when convenient.
这里的每一条记录都代表Roblox游戏中真实发生过的生产级陷阱问题,曾导致数据丢失、漏洞利用、崩溃或数小时的调试工作。严重程度等级:
- 严重 - 数据丢失、安全 breach 或收入损失。上线前必须修复。
- 高 - 服务器不稳定、体验下降或存在漏洞风险。当前迭代必须修复。
- 中 - 正确性bug、性能问题或开发者困惑。规模化前必须修复。
- 低 - 代码质量、可维护性或轻微时序问题。方便时修复。
MarketplaceService.ProcessReceiptPurchaseGrantedPurchaseGrantedMarketplaceService.ProcessReceiptPurchaseGranted:Connect()RBXScriptConnection:Disconnect():Connect()RBXScriptConnection:Disconnect()PlayerRemovinglocal Players = game:GetService("Players")
local Trove = require(game.ReplicatedStorage.Packages.Trove)
local playerTroves: { [Player]: typeof(Trove.new()) } = {}
local function onPlayerAdded(player: Player)
local trove = Trove.new()
playerTroves[player] = trove
trove:Connect(player.CharacterAdded, function(character)
local humanoid = character:WaitForChild("Humanoid")
trove:Connect(humanoid.Died, function()
task.wait(3)
player:LoadCharacter()
end)
end)
end
local function onPlayerRemoving(player: Player)
local trove = playerTroves[player]
if trove then
trove:Clean()
playerTroves[player] = nil
end
end
Players.PlayerAdded:Connect(onPlayerAdded)
Players.PlayerRemoving:Connect(onPlayerRemoving)PlayerRemovinglocal Players = game:GetService("Players")
local Trove = require(game.ReplicatedStorage.Packages.Trove)
local playerTroves: { [Player]: typeof(Trove.new()) } = {}
local function onPlayerAdded(player: Player)
local trove = Trove.new()
playerTroves[player] = trove
trove:Connect(player.CharacterAdded, function(character)
local humanoid = character:WaitForChild("Humanoid")
trove:Connect(humanoid.Died, function()
task.wait(3)
player:LoadCharacter()
end)
end)
end
local function onPlayerRemoving(player: Player)
local trove = playerTroves[player]
if trove then
trove:Clean()
playerTroves[player] = nil
end
end
Players.PlayerAdded:Connect(onPlayerAdded)
Players.PlayerRemoving:Connect(onPlayerRemoving)local lastFire: { [Player]: number } = {}
local COOLDOWN = 0.1
AttackRemote.OnServerEvent:Connect(function(player: Player, targetId: number)
local now = os.clock()
if lastFire[player] and now - lastFire[player] < COOLDOWN then return end
lastFire[player] = now
-- process attack
end)local lastFire: { [Player]: number } = {}
local COOLDOWN = 0.1
AttackRemote.OnServerEvent:Connect(function(player: Player, targetId: number)
local now = os.clock()
if lastFire[player] and now - lastFire[player] < COOLDOWN then return end
lastFire[player] = now
-- 处理攻击逻辑
end)game:BindToClose()task.spawngame:BindToClose()task.spawnStreamingMinRadiusStreamingTargetRadiusModelStreamingModeStreamingMinRadiusStreamingTargetRadiusModelStreamingModerequire()WaitForChildtask.waitrequire()WaitForChildtask.waitlocal CombatSystem = {}
function CombatSystem:Init()
-- WaitForChild is safe here (called by bootstrap, not during require)
self._remotes = game.ReplicatedStorage:WaitForChild("Remotes", 10)
end
function CombatSystem:Start()
-- Connect events after all modules are Init'd
end
return CombatSystem:Init():Start()local CombatSystem = {}
function CombatSystem:Init()
-- WaitForChild在此处是安全的(由启动脚本调用,而非require阶段)
self._remotes = game.ReplicatedStorage:WaitForChild("Remotes", 10)
end
function CombatSystem:Start()
-- 所有模块初始化完成后再连接事件
end
return CombatSystem:Init():Start()#tbl[3] = nil#tbl#tbl[3] = nil#tblniltable.remove()for _, v in tbl dofor i = 1, #tbltable.remove()for _, v in tbl dofor i = 1, #tblwait()task.wait()spawn()task.spawn()delay()task.delay()wait()task.wait()spawn()task.spawn()delay()task.delay()WaitForChild(name)WaitForChild(name)nillocal folder = ReplicatedStorage:WaitForChild("Weapons", 10)
if not folder then
warn("[Init] Weapons folder not found after 10s")
return
endlocal folder = ReplicatedStorage:WaitForChild("Weapons", 10)
if not folder then
warn("[初始化] 10秒后仍未找到Weapons文件夹")
return
end\d%d%\|*?-\d%d%\|*?-%d\d%w\w%s\s%.\..-.*?%%%%d\d%w\w%s\s%.\..-.*?%%%local functionlocal functionfunctionA()helperB()helperB-- BAD: helperB is nil when functionA runs
local function functionA()
helperB() -- ERROR: attempt to call a nil value
end
local function helperB()
print("I'm a helper")
end
-- GOOD: helper declared first
local function helperB()
print("I'm a helper")
end
local function functionA()
helperB() -- works
endfunctionA()helperB()helperB-- 错误:functionA运行时helperB为Nil
local function functionA()
helperB() -- 错误:尝试调用Nil值
end
local function helperB()
print("我是辅助函数")
end
-- 正确:辅助函数先声明
local function helperB()
print("我是辅助函数")
end
local function functionA()
helperB() -- 正常运行
endlocal functionB -- forward declare
local function functionA()
functionB()
end
function functionB() -- note: no 'local' (already declared above)
functionA()
endlocal functionB -- 前置声明
local function functionA()
functionB()
end
function functionB() -- 注意:此处无需加'local'(已在上方声明)
functionA()
endCRITICAL (fix before shipping):
SE-1 DataStore session locking → Use ProfileStore
SE-2 Client-side currency → Server-authoritative only
SE-3 ProcessReceipt order → Grant THEN PurchaseGranted
HIGH (fix in current sprint):
SE-4 Undisconnected events → Trove pattern (RbxUtil)
SE-5 RemoteEvent flooding → Per-player rate limiter
SE-6 BindToClose 30s timeout → Parallel saves with task.spawn
MEDIUM (fix before scale):
SE-7 Mobile part count → StreamingEnabled + <10K parts
SE-8 Yielding in module require → Init/Start lifecycle pattern
SE-9 Table # with nil gaps → table.remove or explicit length
SE-11 Infinite yield WaitForChild → Always pass timeout parameter
SE-13 Local function order → Callees above callers (no hoisting)
LOW (fix when convenient):
SE-10 Deprecated wait/spawn/delay → task.wait/spawn/delay
SE-12 String patterns vs regex → %d not \d, % not \严重(上线前必须修复):
SE-1 DataStore会话锁定 → 使用ProfileStore
SE-2 客户端货币处理 → 仅由服务器权威控制
SE-3 ProcessReceipt执行顺序 → 先发放道具再返回PurchaseGranted
高(当前迭代必须修复):
SE-4 未断开事件连接 → 使用Trove模式(RbxUtil)
SE-5 RemoteEvent洪水攻击 → 实现按玩家速率限制
SE-6 BindToClose 30秒超时 → 用task.spawn并行保存数据
中(规模化前必须修复):
SE-7 移动端零件数量 → 启用StreamingEnabled + 控制在10000个以内
SE-8 模块Require时阻塞 → 使用Init/Start生命周期模式
SE-9 含Nil间隙的表格#运算 → 使用table.remove或显式长度计算
SE-11 WaitForChild无限阻塞 → 始终传入超时参数
SE-13 局部函数声明顺序 → 被调用函数在前(无变量提升)
低(方便时修复):
SE-10 已废弃的wait/spawn/delay → 替换为task.wait/spawn/delay
SE-12 字符串模式与正则的区别 → 使用%d而非\d,%而非\