luau-roblox-optimizer
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseLuau Roblox Optimizer
Luau Roblox 优化器
Review checklist for scripts that live inside Roblox Studio. Every item names
the symptom, the cause, and the one-line fix. Studio-only means: no external
tooling, no file layout advice, no lectures. Script Analysis,
the Output window, the Developer Console (F9), and MicroProfiler (Ctrl+F6)
are the whole toolkit.
--!strict审查驻留在 Roblox Studio 内的脚本的检查清单。每项都会列出症状、原因和一行修复方案。仅限 Studio:不需要外部工具,不提供文件布局建议,也不进行 说教。Script Analysis、Output 窗口、Developer Console(F9)和 MicroProfiler(Ctrl+F6)就是全部工具。
--!strictReview output
审查输出
A review IS, in this order:
- Exploits and data loss - anything a client can abuse or that drops saved data.
- Crashes - nil indexes, races, errors that stop the script.
- Leaks - connections, threads, and tables that outlive their owner.
- Performance - work done more often than needed.
- Animation and DataStore hygiene - the two areas below.
Each finding is one line: . Items that need the
whole file to change (adopt a framework, restructure folders) are out of
scope for a Studio review.
line N - what breaks - fix审查应按以下顺序进行:
- 可被利用的问题与数据丢失——客户端能够滥用,或导致已保存数据丢失的所有问题。
- 崩溃——nil 索引、竞态,以及会停止脚本的错误。
- 泄漏——生命周期超过其所有者的连接、线程和表。
- 性能——执行次数超过实际需要的任务。
- 动画与 DataStore 规范——下面两个领域。
每条发现占一行:。需要修改整个文件的项(采用框架、重构文件夹)不在 Studio 审查范围内。
line N - what breaks - fixScan triggers
扫描触发条件
Walk the file once. Each token below opens a fixed set of checks; report
every check that fails, even when the same line already has a worse finding.
| Seeing | Check |
|---|---|
| debounce, |
| arg types and ranges, cooldown, player data may not be loaded yet |
| load inside |
| every connection, loop, and track has a |
| called on an Animator, loaded once per character, has a matching |
| |
| |
| |
通读文件一遍。下面的每个 token 都会触发一组固定检查;每项失败的检查都要报告,即使同一行已经有更严重的问题。
| 看到 | 检查 |
|---|---|
| 防抖; |
| 参数类型和范围、冷却机制、玩家数据可能尚未加载 |
| 在 |
| 每个连接、循环和轨道都要在 |
| 在 Animator 上调用;每个角色只加载一次;具有对应的 |
| |
| 改用 |
| 在顶部缓存 |
1. Client/server mistakes
1. 客户端/服务器错误
| Symptom | Cause | Fix |
|---|---|---|
| Exploiters give themselves items or coins | Server reads an amount, id, or position from | Server computes the value itself; client sends intent only ( |
| Remote handler errors on odd input | No type or range check on args | |
| Remote spam lags the server | No cooldown | Track |
| Script runs nowhere | LocalScript in ServerScriptService, or Script in StarterPlayerScripts | LocalScripts: StarterPlayerScripts, StarterCharacterScripts, StarterGui, StarterPack. Scripts: ServerScriptService, Workspace. ModuleScripts: ReplicatedStorage (shared) or ServerStorage (server only) |
| Client change doesn't show for others | Client edits Workspace directly | Client fires a RemoteEvent; server makes the change |
| Remote is nil on the client | Created by a Script after the LocalScript looked for it | Put RemoteEvents in ReplicatedStorage in the Explorer, not |
| 症状 | 原因 | 修复 |
|---|---|---|
| 作弊者给自己发放物品或金币 | 服务器从 | 由服务器自行计算数值;客户端只发送意图( |
| Remote 处理程序在遇到异常输入时出错 | 参数没有类型或范围检查 | |
| Remote 洪泛导致服务器卡顿 | 没有冷却机制 | 跟踪 |
| 脚本完全不运行 | LocalScript 位于 ServerScriptService,或 Script 位于 StarterPlayerScripts | LocalScript:StarterPlayerScripts、StarterCharacterScripts、StarterGui、StarterPack。Script:ServerScriptService、Workspace。ModuleScript:ReplicatedStorage(共享)或 ServerStorage(仅服务器) |
| 客户端的更改对其他人不可见 | 客户端直接修改 Workspace | 客户端触发 RemoteEvent;服务器执行更改 |
| 客户端上的 Remote 为 nil | Script 在 LocalScript 查找之后才创建它 | 在 Explorer 中将 RemoteEvent 放入 ReplicatedStorage,而不是在运行时使用 |
2. Bugs that crash on respawn or leave
2. 在角色重生或玩家离开时崩溃的错误
| Symptom | Cause | Fix |
|---|---|---|
| Remote or Touched fires before the async load in PlayerAdded finishes | Guard: |
| | Same guard; never save when the load failed |
| Works in Play Solo, breaks in Team Test or live | Script assumes the character exists at start | |
| Touched gives 2 to 5 pickups per coin | | Debounce: |
| Pickup ignores hats and tools | | |
| Dot chain runs before the part streams or loads | |
| Script errors once then goes silent | Error thrown inside a connection handler kills only that call, but an error at top level stops the whole script | Move setup into functions; wrap risky calls in |
| 症状 | 原因 | 修复 |
|---|---|---|
在 | Remote 或 Touched 在 PlayerAdded 中的异步加载完成前触发 | 添加保护: |
玩家离开后出现 | | 使用同样的保护;加载失败时绝不保存 |
| 在 Play Solo 中正常,在 Team Test 或正式环境中失效 | 脚本假设角色一开始就存在 | |
| 每个金币触发 2 到 5 次拾取 | | 防抖:在发放奖励前执行 |
| 拾取时忽略帽子和工具 | | |
| 点号链在部件流入或加载之前执行 | 客户端使用 |
| 脚本报错一次后便不再执行 | 连接处理程序内部抛出的错误只会终止该次调用,但顶层错误会停止整个脚本 | 将初始化逻辑移入函数;用 |
3. Memory leaks
3. 内存泄漏
| Symptom | Cause | Fix |
|---|---|---|
| Server memory climbs every respawn | | Store the connection; disconnect in |
| Memory climbs per player who joined | Table keyed by | |
| Parts pile up invisibly | | |
| Tweens or tracks keep running on destroyed objects | Track or tween created per spawn, never stopped | Stop and destroy in |
| Sounds and particles stack | | Reuse one instance, or |
Rule of thumb: every , , , , and
inside a or handler needs a
matching cleanup in or .
Connecttask.spawnwhileInstance.newLoadAnimationPlayerAddedCharacterAddedPlayerRemovingCharacterRemoving| 症状 | 原因 | 修复 |
|---|---|---|
| 服务器内存在每次角色重生时持续增长 | | 存储连接;在 |
| 内存随着每位加入的玩家不断增长 | 以 Player 为键的表从未清除 | 在 |
| 部件在不可见的情况下不断堆积 | 使用了 | |
| 每次生成都会创建 Track 或 Tween,却从未停止 | 在 |
| 声音和粒子不断叠加 | 每次事件都使用 | 复用一个实例,或使用 |
经验法则:每个位于 或 处理程序中的 、、、 和 ,都需要在 或 中有对应的清理。
PlayerAddedCharacterAddedConnecttask.spawnwhileInstance.newLoadAnimationPlayerRemovingCharacterRemoving4. Performance
4. 性能
| Symptom | Cause | Fix |
|---|---|---|
| Everything slows under load | | |
| Script Performance window shows one script at the top | | Cache references once above the loop |
| Polling loop per player | | Use the event: |
| Heartbeat handler does work every frame | No throttle | Accumulate |
| String building lags | | Collect into a table, |
| Physics lag with static builds | Unanchored decorative parts | |
| Low FPS on big maps | StreamingEnabled off | Turn it on in Workspace properties; guard client code for parts being nil |
| Unknown cause | Guessing | Ctrl+F6 MicroProfiler, Ctrl+P to pause a frame, find the wide bar. Wrap suspects in |
| 症状 | 原因 | 修复 |
|---|---|---|
| 负载较高时整体变慢 | 使用 | 改用 |
| Script Performance 窗口显示某个脚本耗时最高 | 在 Heartbeat 或紧凑循环中调用 | 在循环上方缓存引用一次 |
| 每位玩家都有一个轮询循环 | | 使用事件: |
| Heartbeat 处理程序每帧都执行工作 | 没有节流 | 累积 |
| 构建字符串时出现卡顿 | 在循环中执行 | 收集到表中,再使用 |
| 静态建筑产生物理卡顿 | 装饰部件未锚定 | 对所有永不移动的部件设置 |
| 大型地图的 FPS 较低 | 关闭了 StreamingEnabled | 在 Workspace 属性中开启;客户端代码要防护部件为 nil |
| 原因不明 | 依靠猜测 | 使用 Ctrl+F6 MicroProfiler,Ctrl+P 暂停一帧,并找到较宽的条形。将可疑代码包裹在 |
5. Studio-specific anti-patterns
5. Studio 特有的反模式
- ,
game.Playersas dot access. Works, butgame.ReplicatedStorageis the documented path and survives renames. Cache it once at the top of the script.game:GetService("Players") - . The parent argument replicates every later property change one at a time. Set properties first,
Instance.new("Part", workspace)last.Parent - A script inside a Workspace part that assumes is ready. It is, but duplicated parts run duplicated scripts. Prefer one script in ServerScriptService that loops over a folder or a CollectionService tag.
script.Parent - Logic in a ScreenGui with . The LocalScript restarts on every respawn and reconnects everything. Set
ResetOnSpawn = trueunless the UI must reset.ResetOnSpawn = false - . Yields the whole script; use an event or
while wait() do.task.wait - in Heartbeat. The Output window itself becomes the bottleneck.
print - Testing DataStores in Play mode without Game Settings > Security > Enable Studio Access to API Services. Calls error with 403 and nothing saves.
- 将 、
game.Players作为点号访问。这样虽然可行,但game.ReplicatedStorage才是文档推荐的路径,并且重命名后仍然有效。应在脚本顶部缓存一次。game:GetService("Players") - 。将 parent 作为参数传入,会导致之后的每次属性变更逐个复制。先设置属性,最后设置
Instance.new("Part", workspace)。Parent - 放在 Workspace 部件内部并假设 已就绪的脚本。它确实已就绪,但复制的部件会运行重复的脚本。更好的做法是在 ServerScriptService 中放置一个脚本,遍历文件夹或 CollectionService 标签。
script.Parent - ScreenGui 中使用 的逻辑。LocalScript 会在每次角色重生时重启,并重新连接所有内容。除非 UI 必须重置,否则将
ResetOnSpawn = true设为ResetOnSpawn。false - 。它会让整个脚本产生 yield;应使用事件或
while wait() do。task.wait - 在 Heartbeat 中使用 。Output 窗口本身会成为瓶颈。
print - 在未启用 Game Settings > Security > Enable Studio Access to API Services 的情况下于 Play 模式测试 DataStore。调用会报 403 错误,并且不会保存任何内容。
6. Animation scripts
6. 动画脚本
| Symptom | Cause | Fix |
|---|---|---|
| Deprecation warning, animation may not replicate | | |
| Animation stacks or stutters | | Load once per character, store the track, reuse it |
| Animation never stops | Only | |
| Walk overrides the attack | Wrong | |
| Animation plays once and freezes | | |
| Works for you, invisible for others | Animation asset not owned by the game owner or group | Re-upload under the account or group that owns the place |
| Lag before the animation shows | Player animations loaded on the server | Load and play player-character animations in a LocalScript; the engine replicates them |
| Tracks pile up | Never destroyed | |
| 症状 | 原因 | 修复 |
|---|---|---|
| 出现弃用警告,动画可能无法复制 | | |
| 动画叠加或卡顿 | 每次动作触发时都调用 | 每个角色只加载一次,存储轨道并重复使用 |
| 动画永不停止 | 只调用了 | 在相反事件发生时调用 |
| 行走动画覆盖攻击动画 | | |
| 动画播放一次后冻结 | 闲置动画未设置 | 闲置动画设置 |
| 自己能看到,其他人看不到 | 动画资产不属于游戏所有者或群组 | 在拥有该 place 的账户或群组下重新上传 |
| 动画显示前出现卡顿 | 玩家动画在服务器上加载 | 在 LocalScript 中加载并播放玩家角色动画;引擎会负责复制 |
| 轨道不断堆积 | 从未销毁 | 在 |
7. DataStore review
7. DataStore 审查
| Symptom | Cause | Fix |
|---|---|---|
| Script errors with "Request was throttled" or HTTP 5xx | Bare | Wrap every call in |
| Player data resets to default | Load failed, script fell back to defaults, then saved them | If the load pcall fails, mark the player as not loaded and skip the save |
| Coins lost on server shutdown | Only saving in | Add |
| Two servers overwrite each other | | |
| "DataStore request was added to queue" spam | Saving on every change | Save on |
| Old data unreadable after a schema change | Raw | String key with a version: |
| Nothing saves in Studio | API access off | Game Settings > Security > Enable Studio Access to API Services |
Table saved as | Value contains an Instance, a function, or a mixed-key table | Save plain numbers, strings, booleans, and array or string-key tables only |
| 症状 | 原因 | 修复 |
|---|---|---|
| 脚本出现 "Request was throttled" 或 HTTP 5xx 错误 | 直接调用 | 将每次调用包裹在 |
| 玩家数据重置为默认值 | 加载失败,脚本回退到默认值,随后又将这些默认值保存 | 如果加载 |
| 服务器关闭时丢失金币 | 只在 | 添加 |
| 两台服务器相互覆盖数据 | 先执行 | 任何需要合并的操作都使用 |
| 反复出现 "DataStore request was added to queue" | 每次数据变化都保存 | 在 |
| 更改数据结构后旧数据无法读取 | 直接使用 | 使用带版本号的字符串键: |
| 在 Studio 中没有保存任何内容 | 未启用 API 访问 | Game Settings > Security > Enable Studio Access to API Services |
表被保存为 | 值包含 Instance、函数或混合键表 | 只能保存普通数字、字符串、布尔值,以及数组或字符串键表 |
Common mistakes in the review itself
审查本身的常见错误
- Flagging , type annotations, or file structure. Studio devs cannot act on these without changing their workflow.
--!strict - Suggesting a framework (Knit, ProfileService) as the first fix. Name the direct fix; mention a library only if the dev asks.
- Listing twenty items with no order. Severity first, one fix each.
- 将 、类型注解或文件结构列为问题。Studio 开发者如果不改变工作流,就无法处理这些问题。
--!strict - 将框架(Knit、ProfileService)作为首要修复方案。应指出直接修复方法;只有开发者提出要求时才提及库。
- 列出二十个问题却不排序。应先列严重问题,每项只给一个修复方案。