roblox-code-review
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinese/code-review - Code Quality Review
/code-review - 代码质量审查
You are performing a code quality review on a Roblox project. Follow these 8 steps. Apply the relevant lens based on what changed. Don't apply all lenses every time.
你正在对一个Roblox项目进行代码质量审查。请遵循以下8个步骤。根据代码变更情况应用相应的审查维度,无需每次都应用所有维度。
Quick Reference
快速参考
Load lenses below only when code matching that domain changed. Don't apply all lenses every time.
Key rules:
- Remote types: RemoteEvent (fire-and-forget), UnreliableRemoteEvent (loss-tolerant VFX/position), RemoteFunction (request-response, use sparingly), BindableEvent/BindableFunction (intra-client/server internal, never cross-boundary).
- Data persistence: ALWAYS ProfileStore for player state. Never raw DataStore. Schema template with defaults, DataVersion, migration functions, session locking, BindToClose.
- Security: Validate every remote parameter server-side. Rate-limit all remotes per-player.
- Performance: Consolidate Heartbeat loops. Cache services. Disconnect unused events.
仅当对应领域的代码发生变更时,才加载下方的审查维度。无需每次都应用所有维度。
核心规则:
- 远程类型:RemoteEvent(即发即弃)、UnreliableRemoteEvent(可容忍丢包的特效/位置同步)、RemoteFunction(请求-响应模式,谨慎使用)、BindableEvent/BindableFunction(客户端/服务器内部通信,绝不能跨边界使用)。
- 数据持久化:玩家状态必须使用ProfileStore存储,严禁直接使用DataStore。需包含带默认值的 Schema 模板、DataVersion、迁移函数、会话锁定以及BindToClose处理。
- 安全:服务器端必须验证所有远程调用参数,对每个玩家的所有远程调用进行速率限制。
- 性能:合并Heartbeat循环,缓存服务实例,断开未使用的事件连接。
Step 1: Project Scan
步骤1:项目扫描
Read the project directory structure. Survey script count, naming patterns, and organization.
Record:
- Total script count
- Folder organization
- Module naming patterns
- Whether the project uses Rojo/Wally or in-Studio editing
读取项目目录结构,统计脚本数量、命名模式与组织方式。
记录内容:
- 脚本总数
- 文件夹组织架构
- 模块命名模式
- 项目是否使用Rojo/Wally,还是直接在Studio内编辑
Step 2: Organization Review
步骤2:架构组织审查
Check:
- Scripts in correct locations (ServerScriptService, StarterPlayerScripts, etc.)
- Proper use of services vs standalone scripts
- Clean folder structure (no orphaned scripts, no nesting > 3 levels deep)
- Module naming conventions consistent (PascalCase for ModuleScripts, camelCase for functions)
- No scripts with duplicate or overlapping responsibilities
检查项:
- 脚本是否放置在正确位置(如ServerScriptService、StarterPlayerScripts等)
- 服务与独立脚本的使用是否规范
- 文件夹结构是否清晰(无孤立脚本,嵌套层级不超过3层)
- 模块命名约定是否一致(ModuleScripts使用大驼峰命名,函数使用小驼峰命名)
- 无职责重复或重叠的脚本
Step 3: Code Quality Scan
步骤3:代码质量扫描
Search for anti-patterns:
Deprecated APIs:
- wait( → replace with task.wait()
- spawn( → replace with task.spawn()
- delay( → replace with task.delay()
Code smells:
- Global variables (should be module-scoped)
- Missing type annotations on public functions
- Instance.new() in client scripts (should be server-created)
- while true without task.wait() (unbounded loops)Check for:
- Deprecated APIs (,
wait(),spawn())delay() - Global variable usage (should be module-scoped)
- Missing type annotations on public functions
- Inconsistent naming conventions
- Dead code / unreachable code
- Duplicate code across scripts
- Overly long functions (>100 lines, should be refactored)
查找反模式:
已废弃API:
- wait( → 替换为task.wait()
- spawn( → 替换为task.spawn()
- delay( → 替换为task.delay()
代码异味:
- 全局变量(应限定在模块作用域内)
- 公共函数缺少类型注解
- 客户端脚本中使用Instance.new()(应由服务器创建实例)
- 无task.wait()的while true循环(无界循环)检查内容:
- 已废弃API(、
wait()、spawn())delay() - 全局变量使用情况(应限定在模块作用域内)
- 公共函数是否缺少类型注解
- 命名约定是否不一致
- 死代码/不可达代码
- 脚本间的重复代码
- 过长函数(超过100行,应重构)
Step 4: Architecture Review
步骤4:架构设计审查
Check:
- Module boundaries - Does each module have a single responsibility?
- Dependency direction - Do modules depend on abstractions, not concrete implementations?
- Circular requires - Any modules that depend on each other?
- Separation of concerns - Server vs Client logic properly separated
- Framework usage - If using a framework, is it used consistently?
- Configuration - Hardcoded values should be in config modules
检查项:
- 模块边界:每个模块是否单一职责?
- 依赖方向:模块是否依赖抽象而非具体实现?
- 循环依赖:是否存在互相依赖的模块?
- 关注点分离:服务器与客户端逻辑是否正确分离?
- 框架使用:若使用框架,是否保持使用一致性?
- 配置:硬编码值是否已移至配置模块?
Step 5: Security Quick-Check
步骤5:安全快速检查
Quick scan for:
- Unvalidated RemoteEvent handlers (server-side)
- Client-trusted logic (currency, inventory, damage, position)
- Sensitive data in ReplicatedStorage or StarterPlayer
- Missing rate limiting on remotes
- ProcessReceipt implementation correctness
For a deep security review, run the Security Lens below.
快速扫描内容:
- 未验证的RemoteEvent处理器(服务器端)
- 客户端信任逻辑(货币、库存、伤害、位置等)
- ReplicatedStorage或StarterPlayer中是否存在敏感数据
- 远程调用是否缺少速率限制
- ProcessReceipt实现是否正确
如需深度安全审查,请运行下方的安全审查维度。
Step 6: Performance Quick-Check
步骤6:性能快速检查
Quick scan for:
- or
wait()in tight loopsspawn() - Multiple in same script
RunService.Heartbeat:Connect() - Large tables without cleanup
- Undisconnected events (memory leaks)
- Unanchored parts without collision groups
- Excessive RemoteEvent usage
For a deep performance review, run the Performance Lens below.
快速扫描内容:
- 密集循环中使用或
wait()spawn() - 同一脚本中存在多个
RunService.Heartbeat:Connect() - 未清理的大型表格
- 未断开的事件连接(内存泄漏)
- 未设置碰撞组的非锚定部件
- RemoteEvent过度使用
如需深度性能审查,请运行下方的性能审查维度。
Step 7: Quality Report
步骤7:质量报告
Rate overall quality:
- A - Production-ready. Clean, organized, secure, performant
- B - Solid with minor issues. Safe to ship with minor cleanup
- C - Functional but needs work. Ship with caveats
- D - Significant issues. Needs refactoring before ship
- F - Critical problems. Do not ship in current state
List findings by severity:
- Critical - Security vulnerabilities, data loss risk, crashes
- High - Memory leaks, performance bottlenecks, broken features
- Medium - Code smells, deprecated APIs, poor organization
- Low - Style inconsistencies, missing documentation
For each finding, provide:
- File and line (or function name)
- What's wrong
- The specific fix (code)
对整体质量评级:
- A - 可投入生产环境。代码整洁、架构清晰、安全合规、性能优异
- B - 整体可靠,仅存在少量问题。只需轻微清理即可发布
- C - 功能可用但需优化。发布时需附带说明
- D - 存在重大问题。发布前需重构
- F - 存在严重问题。当前状态禁止发布
按严重程度列出问题:
- Critical(严重) - 安全漏洞、数据丢失风险、崩溃问题
- High(高) - 内存泄漏、性能瓶颈、功能故障
- Medium(中) - 代码异味、已废弃API、架构组织混乱
- Low(低) - 风格不一致、缺少文档
每个问题需包含:
- 文件与行号(或函数名)
- 问题描述
- 具体修复方案(代码示例)
Step 8: Refactoring Suggestions
步骤8:重构建议
If significant issues found, suggest refactoring priorities:
- Immediate - Must fix before next publish
- Short-term - Fix in the next development cycle
- Long-term - Plan for when the project grows
For each suggestion:
- What to change
- Why it matters
- Estimated effort (small/medium/large)
若发现重大问题,提出重构优先级:
- Immediate(紧急) - 下次发布前必须修复
- Short-term(短期) - 在下一个开发周期内修复
- Long-term(长期) - 项目扩张时规划修复
每个建议需包含:
- 变更内容
- 变更原因
- 预估工作量(小/中/大)
Security Lens
安全审查维度
Apply this lens when security-relevant code changed: remotes, data persistence, monetization, player input handling, or server authority.
当安全相关代码变更时应用此维度:远程调用、数据持久化、变现、玩家输入处理或服务器权限相关代码。
Security Step 1: Remote Surface Scan
安全步骤1:远程调用面扫描
Search for all and instances. Search for , , , to map the full remote surface.
RemoteEventRemoteFunction:FireServer:FireClient:InvokeServer:InvokeClientRecord every remote found with:
- Name
- Location (ReplicatedStorage path)
- Direction (Client→Server, Server→Client, Client↔Server)
- What it appears to do
查找所有和实例,搜索、、、以梳理完整的远程调用面。
RemoteEventRemoteFunction:FireServer:FireClient:InvokeServer:InvokeClient记录每个远程调用的信息:
- 名称
- 位置(ReplicatedStorage路径)
- 方向(客户端→服务器、服务器→客户端、客户端↔服务器)
- 功能描述
Security Step 2: Validation Check
安全步骤2:验证检查
For each remote, verify:
- Argument type checking - Server validates for every parameter
typeof(arg) - Range validation - Numeric inputs checked against min/max bounds
- Cooldown enforcement - Rate limiting prevents spam/exploitation
- Authorization check - Server verifies the requesting player owns the action
- Sanitization - String inputs cleaned, no injection vectors
Flag any remote that accepts input without full server-side validation.
对每个远程调用,验证以下内容:
- 参数类型检查 - 服务器端验证每个参数的
typeof(arg) - 范围验证 - 数值输入需检查最小/最大值边界
- 冷却机制 - 速率限制防止滥用/攻击
- 权限验证 - 服务器端验证请求玩家是否有权执行该操作
- 数据清理 - 字符串输入需清理,无注入风险
标记所有未经过完整服务器端验证就接收输入的远程调用。
Security Step 3: Client Trust Audit
安全步骤3:客户端信任审计
Search for client-side logic that should be server-side:
- Currency operations (giving/removing coins, cash, gems)
- Inventory changes (adding/removing items)
- Damage calculation (should be server-authoritative)
- Position setting (teleporting, movement authority)
- Leaderboard/stat modification
- Game state changes (win/lose conditions)
Rule: If it affects game state or other players, it must be server-validated.
查找应放在服务器端的客户端逻辑:
- 货币操作(发放/扣除金币、现金、宝石)
- 库存变更(添加/移除物品)
- 伤害计算(应由服务器授权)
- 位置设置(传送、移动权限)
- 排行榜/属性修改
- 游戏状态变更(胜负条件)
规则:若操作影响游戏状态或其他玩家,必须经过服务器验证。
Security Step 4: Data Exposure Check
安全步骤4:数据暴露检查
Verify:
- No sensitive data in (secrets, configs with admin keys)
ReplicatedStorage - No server-only logic in (game state, anti-cheat)
StarterPlayerScripts - No player data exposed to other players via remotes (unless intentional)
- RemoteEvent payloads don't include excess data (send only what's needed)
- No paths to server-only modules from client scripts
require()
验证内容:
- ReplicatedStorage中无敏感数据(密钥、含管理员权限的配置)
- StarterPlayerScripts中无服务器专属逻辑(游戏状态、反作弊)
- 远程调用未向其他玩家暴露玩家数据(除非是有意设计)
- RemoteEvent载荷不包含冗余数据(仅发送必要内容)
- 客户端脚本未服务器专属模块
require()
Security Step 5: Rate Limiting Check
安全步骤5:速率限制检查
Verify all remotes have per-player rate limiting:
- Track last-fire timestamps server-side
- Reject requests faster than expected human input
- Different limits for different actions (chat: 1/sec, purchase: 1/5sec, movement: 30/sec)
- Log rate limit violations for monitoring
验证所有远程调用均已针对单个玩家设置速率限制:
- 服务器端记录上次调用时间戳
- 拒绝超出人类正常输入频率的请求
- 不同操作设置不同限制(聊天:1次/秒,购买:1次/5秒,移动:30次/秒)
- 记录速率限制违规情况用于监控
Security Step 6: Vulnerability Report
安全步骤6:漏洞报告
Categorize findings:
- Critical - Exploitable for direct advantage (free currency, item duplication, account takeover)
- High - Data exposure or corruption possible
- Medium - Potential for abuse with moderate effort
- Low - Best practice violation, hard to exploit
For each vulnerability:
- Remote/method affected
- Exploit scenario (how an attacker would abuse it)
- Impact (what they gain)
- Fix (specific hardened code)
对问题分类:
- Critical(严重) - 可被直接利用获取优势(免费货币、物品复制、账号接管)
- High(高) - 可能导致数据暴露或损坏
- Medium(中) - 中等成本即可滥用
- Low(低) - 违反最佳实践,但难以被利用
每个漏洞需包含:
- 受影响的远程调用/方法
- 攻击场景(攻击者如何滥用)
- 影响范围(攻击者可获得的收益)
- 修复方案(具体加固代码)
Security Step 7: Hardening
安全步骤7:代码加固
Apply hardened code for each vulnerable remote. Include before/after for clarity.
Hardening patterns to apply:
- Server-side validation wrapper for each remote
- Rate limiting middleware
- Data sanitization functions
- Ownership verification for state changes
为每个存在漏洞的远程调用提供加固代码,包含前后对比以便清晰理解。
可应用的加固模式:
- 每个远程调用的服务器端验证包装器
- 速率限制中间件
- 数据清理函数
- 状态变更的所有权验证
Security Step 8: Re-verify
安全步骤8:重新验证
Confirm all vulnerabilities addressed:
- Each Critical/High finding has a corresponding fix applied
- Legitimate functionality still works after hardening
- No new issues introduced by the fixes
- Output a before/after comparison of the security posture
确认所有漏洞已解决:
- 所有严重/高优先级问题均已修复
- 加固后原有功能仍正常运行
- 修复未引入新问题
- 输出安全态势的前后对比
Performance Lens
性能审查维度
Apply this lens when performance-sensitive code changed: large loops, data structures, rendering, network-heavy features, or when the user reports lag.
当性能敏感代码变更时应用此维度:大型循环、数据结构、渲染、网络密集型功能,或用户反馈卡顿问题时。
Performance Step 1: Project Scan
性能步骤1:项目扫描
Search for known anti-patterns:
- and
wait()(yield-based, blocks thread)spawn() - loops (Heartbeat, Stepped, RenderStepped frequency)
RunService - and
GetDescendants()in loops (expensive at scale)GetChildren()
查找已知反模式:
- 和
wait()(基于yield,会阻塞线程)spawn() - 循环(Heartbeat、Stepped、RenderStepped的调用频率)
RunService - 循环中使用和
GetDescendants()(大规模场景下性能开销大)GetChildren()
Performance Step 2: Part Audit
性能步骤2:部件审计
Check for:
- Total part count (target: <50,000 for mobile, <200,000 for PC)
- Unanchored parts without assembly (physics chaos)
- Parts without collision groups (unnecessary collision detection)
- MeshParts vs Unions vs parts (MeshParts are most efficient)
- Transparent/reflective parts (rendering cost)
检查内容:
- 部件总数(目标:移动端<50,000,PC端<200,000)
- 未组合的非锚定部件(物理混乱)
- 未设置碰撞组的部件(不必要的碰撞检测)
- MeshParts、Unions与普通部件的使用(MeshParts效率最高)
- 透明/反光部件(渲染成本高)
Performance Step 3: Script Audit
性能步骤3:脚本审计
Check for:
- Multiple in the same script (consolidate into one)
Heartbeat:Connect() - Excessive RemoteEvent usage (batch updates, reduce frequency)
- Tight loops without (thread starvation)
task.wait() - Unindexed table operations (linear search vs hash lookup)
- String concatenation in loops (use table.concat instead)
- in hot paths (cache and reuse)
Instance.new() - Deep chains (cache references)
WaitForChild()
检查内容:
- 同一脚本中存在多个(应合并为一个)
Heartbeat:Connect() - RemoteEvent过度使用(批量更新,降低调用频率)
- 无的密集循环(线程饥饿)
task.wait() - 未索引的表格操作(线性搜索vs哈希查找)
- 循环中拼接字符串(应使用table.concat)
- 热点路径中使用(缓存并复用实例)
Instance.new() - 深层链(缓存引用)
WaitForChild()
Performance Step 4: Memory Audit
性能步骤4:内存审计
Check for:
- Undisconnected events (every must have a matching
:Connect()):Disconnect() - Unreferenced instances (created but never parented or referenced)
- Large data tables held in memory (use lazy loading)
- String/internment issues (unnecessary duplicate strings)
- Module-level state that grows without cleanup
检查内容:
- 未断开的事件连接(每个必须对应
:Connect()):Disconnect() - 未引用的实例(已创建但从未父化或引用)
- 内存中存储的大型数据表(使用懒加载)
- 字符串/驻留问题(不必要的重复字符串)
- 模块级状态无清理导致持续增长
Performance Step 5: Network Audit
性能步骤5:网络审计
Check:
- RemoteEvent frequency - Are updates sent every frame when 1/sec would suffice?
- Data size per event - Are payloads unnecessarily large?
- Unnecessary replication - Is data sent to all players when only some need it?
- vs
FireAllClients- Target specific players when possibleFireClient - Debouncing - Are rapid-fire remotes properly debounced server-side?
检查内容:
- RemoteEvent调用频率:是否每帧都发送更新,而实际上1次/秒就足够?
- 每个事件的数据大小:载荷是否过大?
- 不必要的复制:是否向所有玩家发送数据,而实际上仅部分玩家需要?
- vs
FireAllClients:尽可能针对特定玩家发送FireClient - 防抖:服务器端是否对高频远程调用进行防抖处理?
Performance Step 6: Priority Report
性能步骤6:优先级报告
Generate prioritized list:
- Critical - Causes crashes or completely unplayable experience
- High - Noticeable lag, frame drops, or rubber-banding
- Medium - Suboptimal but functional, wasted resources
- Low - Minor optimization opportunity
For each item:
- What's slow
- Why it's slow (technical explanation)
- The fix (specific code change)
- Expected improvement
生成优先级列表:
- Critical(严重) - 导致崩溃或完全无法游玩
- High(高) - 明显卡顿、掉帧或瞬移
- Medium(中) - 性能不佳但可用,资源浪费
- Low(低) - 微小的优化机会
每个项需包含:
- 性能瓶颈点
- 技术层面的卡顿原因
- 修复方案(具体代码变更)
- 预期优化效果
Performance Step 7: Apply Fixes
性能步骤7:应用修复
Provide optimized code for each finding. Include before/after with expected impact.
Common fixes:
- Replace with
wait()task.wait() - Consolidate Heartbeat connections
- Add to prevent thread starvation
task.wait() - Cache calls
GetService() - Use spatial indexing for distance checks
- Batch RemoteEvent updates
为每个问题提供优化后的代码,包含前后对比及预期影响。
常见修复方案:
- 用替换
task.wait()wait() - 合并Heartbeat连接
- 添加避免线程饥饿
task.wait() - 缓存调用
GetService() - 使用空间索引进行距离检测
- 批量发送RemoteEvent更新
Performance Step 8: Before/After
性能步骤8:前后对比
Document improvements:
- Metric - What was measured (frame time, memory, network traffic)
- Before - Original value
- After - Improved value
- Change - Percentage improvement
- Remaining - What's left to optimize
记录优化效果:
- 指标 - 测量内容(帧时间、内存、网络流量)
- 优化前 - 原始数值
- 优化后 - 提升后的数值
- 变化率 - 优化百分比
- 剩余空间 - 仍需优化的内容
Monetization Lens
变现审查维度
Apply this lens when monetization code changed: GamePasses, DevProducts, Premium integration, shop UI, or when reviewing revenue strategy.
当变现相关代码变更时应用此维度:GamePasses、DevProducts、Premium集成、商店UI,或审查营收策略时。
Monetization Step 1: Current State
变现步骤1:当前状态
Search for usage. Find all GamePass and DevProduct references. List all existing monetization.
MarketplaceServiceRecord:
- All GamePasses (ID, name, price, what it grants)
- All DevProducts (ID, name, price, what it consumes)
- Premium benefits (if any)
- Where monetization is presented in-game
查找的使用情况,找出所有GamePass和DevProduct引用,列出所有现有变现方式。
MarketplaceService记录内容:
- 所有GamePass(ID、名称、价格、权益)
- 所有DevProduct(ID、名称、价格、消耗内容)
- Premium权益(如有)
- 游戏内展示变现内容的位置
Monetization Step 2: GamePass Review
变现步骤2:GamePass审查
Evaluate each GamePass:
- Is the value clear to the player?
- Is the price appropriate for what it grants?
- Is it discoverable in-game (shown at relevant moments)?
- Does it persist correctly (works after rejoin)?
- Is it idempotent (purchasing twice doesn't break anything)?
- Does it provide lasting value vs one-time use?
评估每个GamePass:
- 玩家是否能清晰感知其价值?
- 价格与提供的权益是否匹配?
- 在游戏内是否易于发现(在合适的时机展示)?
- 是否能持久生效(重新加入游戏后仍有效)?
- 是否具有幂等性(重复购买不会导致问题)?
- 提供的是长期价值还是一次性使用价值?
Monetization Step 3: DevProduct Review
变现步骤3:DevProduct审查
Evaluate each consumable:
- Is it compelling enough for repeat purchase?
- Is it priced for impulse buy (<100 Robux) or considered purchase?
- Does ProcessReceipt handle correctly (grant then confirm)?
- Are there diminishing returns or purchase limits?
- Is the value clear before purchasing?
- Does it complement (not replace) gameplay?
评估每个消耗品:
- 是否足够吸引人以促使重复购买?
- 定价是否适合冲动消费(<100 Robux)或理性消费?
- ProcessReceipt是否处理正确(先发放权益再确认)?
- 是否存在收益递减或购买限制?
- 购买前是否能清晰感知其价值?
- 是否补充(而非替代)核心玩法?
Monetization Step 4: Missing Opportunities
变现步骤4:缺失的机会
Based on genre best practices, suggest monetization the game is missing.
Simulator: VIP GamePass (2x currency, exclusive pets), Auto-farm DevProduct, Lucky egg/spin DevProducts, Season pass.
Tycoon: VIP GamePass (faster income, exclusive materials), Extra plot slots, Cosmetic upgrades.
RPG: Inventory expansion, Experience boosts, Cosmetic gear, Character slots.
Horror: Skip/co-op passes, Cosmetic items (flashlight skins, outfits), Hint system DevProduct.
Battle Royale: Battle pass (seasonal), Cosmetic-only items, Victory animations.
基于品类最佳实践,建议游戏缺失的变现方式。
模拟器类:VIP GamePass(2倍货币、专属宠物)、自动挂机DevProduct、幸运蛋/抽奖DevProduct、赛季通行证。
大亨类:VIP GamePass(更快收益、专属材料)、额外地块、外观升级。
RPG类:背包扩容、经验加成、外观装备、角色槽位。
恐怖类:跳过/合作通行证、外观物品(手电筒皮肤、服装)、提示系统DevProduct。
大逃杀类:战斗通行证(季节性)、纯外观物品、胜利动画。
Monetization Step 5: Pricing Analysis
变现步骤5:定价分析
Compare prices against Roblox norms:
- Entry point - 25-49 Robux for impulse buys
- Mid-tier - 99-199 Robux for meaningful upgrades
- Premium - 499-999 Robux for VIP/lifetime benefits
- Consumables - 10-50 Robux for repeat purchases
Evaluate Robux-to-value ratio, price anchoring, and bundle discounts.
对比Roblox平台的定价标准:
- 入门级 - 25-49 Robux(冲动消费)
- 中端 - 99-199 Robux(有意义的升级)
- 高端 - 499-999 Robux(VIP/终身权益)
- 消耗品 - 10-50 Robux(重复购买)
评估Robux与价值的比率、价格锚定及捆绑折扣。
Monetization Step 6: Premium Integration
变现步骤6:Premium集成检查
Check:
- Premium payouts configured and optimized
- Premium-exclusive benefits (10-15% bonus, exclusive items, priority queue)
- Premium benefits clearly communicated to non-Premium players
- Premium doesn't create unfair advantages in competitive games
检查内容:
- Premium分成是否已配置并优化
- Premium专属权益(10-15%额外奖励、专属物品、优先排队)
- Premium权益是否清晰传达给非Premium玩家
- 在竞技类游戏中,Premium是否不会造成不公平优势
Monetization Step 7: Ad Integration
变现步骤7:广告集成评估
Evaluate if Rewarded Video Ads would fit:
- Natural placement points (extra life, bonus currency, skip wait timer)
- Player opt-in only (never forced)
- Doesn't interrupt core gameplay loop
- Frequency capped (1 ad per X minutes)
- Value exchange is fair (ad view = meaningful reward)
评估奖励视频广告是否适合:
- 自然植入点(额外生命、奖励货币、跳过等待时间)
- 仅允许玩家主动选择(绝不强制)
- 不打断核心玩法循环
- 频率限制(每X分钟1次广告)
- 价值交换公平(观看广告=有意义的奖励)
Monetization Step 8: Ethical Review
变现步骤8:合规性审查
Flag potentially predatory patterns:
- Loot boxes / gambling mechanics - Are odds disclosed?
- FOMO pressure - Limited-time offers that pressure quick decisions?
- Pay-to-win - Can paying players dominate free players unfairly?
- Dark patterns - Confusing UI that leads to accidental purchases?
标记潜在的掠夺性模式:
- 开箱/赌博机制:是否公开概率?
- FOMO压力:是否有促使快速决策的限时优惠?
- 付费赢:付费玩家是否能不公平地碾压免费玩家?
- 暗黑模式:是否有易导致误购的混淆UI?
Monetization Step 9: Recommendations Report
变现步骤9:建议报告
Prioritized list of monetization improvements:
- Must-have - Items that directly increase revenue
- Should-have - Items that improve conversion or retention
- Nice-to-have - Items that optimize existing revenue
For each recommendation:
- What to implement
- Why it will increase revenue
- Implementation effort (small/medium/large)
- Where in the game to present it
- Pricing suggestion
按优先级列出变现优化建议:
- Must-have(必备) - 直接提升营收的项
- Should-have(应做) - 提升转化率或留存的项
- Nice-to-have(锦上添花) - 优化现有营收的项
每个建议需包含:
- 实现内容
- 提升营收的原因
- 实现工作量(小/中/大)
- 在游戏内的展示位置
- 定价建议
Networking / Remote Architecture Lens
网络/远程调用架构审查维度
Apply this lens when networking code changed: new remotes, Bindable refactoring, effect syncing, or when auditing remote surface for scaling.
当网络代码变更时应用此维度:新增远程调用、Bindable重构、特效同步,或为扩展而审计远程调用面时。
Networking Step 1: Remote Surface Map
网络步骤1:远程调用面映射
Search for all , , and instances. Search for , , , , , and to map the full remote surface.
RemoteEventRemoteFunctionUnreliableRemoteEvent:FireServer:FireClient:FireAllClients:InvokeServer:InvokeClient:InvokeRecord every remote found with:
- Name
- Location (ReplicatedStorage path)
- Type (RemoteEvent, RemoteFunction, UnreliableRemoteEvent)
- Direction (Client→Server, Server→Client, Client↔Server)
- What it does and whether it carries critical or cosmetic data
查找所有、和实例,搜索、、、、和以梳理完整的远程调用面。
RemoteEventRemoteFunctionUnreliableRemoteEvent:FireServer:FireClient:FireAllClients:InvokeServer:InvokeClient:Invoke记录每个远程调用的信息:
- 名称
- 位置(ReplicatedStorage路径)
- 类型(RemoteEvent、RemoteFunction、UnreliableRemoteEvent)
- 方向(客户端→服务器、服务器→客户端、客户端↔服务器)
- 功能及传输的是关键数据还是 cosmetic(外观)数据
Networking Step 2: Type Selection Audit
网络步骤2:类型选择审计
Verify each remote uses the correct type:
| Type | Best For | Notes |
|---|---|---|
| Fire-and-forget messages | Most common. No return value. |
| Request-response patterns | Blocking. Avoid in hot paths. Prefer RemoteEvent + callback pattern. |
| Loss-tolerant data (effects, cosmetics, position updates) | Can drop packets under load. NEVER for currency, inventory, damage, game state. |
| Intra-client or intra-server pub/sub | LocalScript→LocalScript or Script→Script only. Never cross Server↔Client boundary. |
| Intra-client or intra-server request-response | Same boundary rule as BindableEvent. |
Flag any remote using the wrong type:
- where
RemoteFunction+ response pattern would sufficeRemoteEvent - used as BindableEvent (firing a remote only to reach other scripts on the same client)
RemoteEvent - carrying critical data that should use reliable delivery
RemoteEvent - carrying game-critical state
UnreliableRemoteEvent
验证每个远程调用是否使用正确类型:
| 类型 | 适用场景 | 说明 |
|---|---|---|
| 即发即弃消息 | 最常用,无返回值。 |
| 请求-响应模式 | 阻塞调用,避免在热点路径使用。优先使用RemoteEvent + 回调模式。 |
| 可容忍丢包的数据(特效、外观、位置更新) | 高负载下可能丢包。绝不能用于货币、库存、伤害、游戏状态同步。 |
| 客户端内部或服务器内部发布/订阅 | 仅适用于LocalScript→LocalScript或Script→Script,绝不能跨服务器↔客户端边界。 |
| 客户端内部或服务器内部请求-响应 | 边界规则与BindableEvent相同。 |
标记使用错误类型的远程调用:
- 可用RemoteEvent + 响应模式替代的RemoteFunction
- 用作BindableEvent的RemoteEvent(仅向同一客户端的其他脚本发送消息)
- 传输关键数据但未使用可靠传输的RemoteEvent
- 传输游戏关键状态的UnreliableRemoteEvent
Networking Step 3: RemoteFunction Check
网络步骤3:RemoteFunction检查
RemoteFunctionVerify:
- is used sparingly (not per-frame or in tight loops)
:InvokeServer - is only used when the server genuinely needs an answer from a specific client (rare)
:InvokeClient - Consider replacing with + response event pattern for non-critical request-response flows
RemoteEvent - has a timeout safeguard (client may not respond)
:InvokeClient
RemoteFunction验证内容:
- 使用频率低(不用于每帧或密集循环)
:InvokeServer - 仅在服务器确实需要特定客户端返回结果时使用(罕见场景)
:InvokeClient - 考虑用RemoteEvent + 响应事件模式替代非关键的请求-响应流程
- 设置了超时保护(客户端可能无响应)
:InvokeClient
Networking Step 4: Bindable Audit
网络步骤4:Bindable审计
BindableEventBindableFunctionCheck:
- No /
BindableEventin ReplicatedStorage that is fired by server and listened to by client (useBindableFunctioninstead - Bindables don't replicate)RemoteEvent - Client-side s are used for decoupling LocalScripts (cleaner than direct module references)
BindableEvent - Server-side s are used for service-to-service pub/sub within the same script context
BindableEvent - No orphaned or unused Bindable instances left in the hierarchy
BindableEventBindableFunction检查内容:
- ReplicatedStorage中不存在由服务器触发、客户端监听的BindableEvent/BindableFunction(应使用RemoteEvent——Bindable不会复制到客户端)
- 客户端BindableEvent用于解耦LocalScript(比直接引用模块更清晰)
- 服务器BindableEvent用于同一脚本上下文内的服务间发布/订阅
- 层级中无孤立或未使用的Bindable实例
Networking Step 5: UnreliableRemoteEvent Audit
网络步骤5:UnreliableRemoteEvent审计
UnreliableRemoteEventVerify:
- Used only for loss-tolerant data: cosmetic effects, non-critical position interpolation, particle triggers, sound events
- Never used for: currency transactions, inventory changes, damage application, game state transitions, unlock/upgrade actions
- Client-side has fallback logic (if a cosmetic event is dropped, the game still functions)
- Server-side does not rely on unreliable delivery for authoritative state
Recommended pattern - separate critical and cosmetic remotes:
luau
-- Critical: reliable RemoteEvent
local PurchaseRequest = ReplicatedStorage.Remotes.PurchaseRequest -- RemoteEvent
-- Cosmetic: unreliable
local HitEffectSync = ReplicatedStorage.Remotes.HitEffectSync -- UnreliableRemoteEventUnreliableRemoteEvent验证内容:
- 仅用于可容忍丢包的数据:外观特效、非关键位置插值、粒子触发、声音事件
- 绝不用于:货币交易、库存变更、伤害计算、游戏状态转换、解锁/升级操作
- 客户端有 fallback 逻辑(若外观事件丢失,游戏仍可正常运行)
- 服务器不依赖不可靠传输来维护权威状态
推荐模式——分离关键与外观远程调用:
luau
-- 关键数据:可靠的RemoteEvent
local PurchaseRequest = ReplicatedStorage.Remotes.PurchaseRequest -- RemoteEvent
-- 外观数据:不可靠
local HitEffectSync = ReplicatedStorage.Remotes.HitEffectSync -- UnreliableRemoteEventNetworking Step 6: Organization & Naming
网络步骤6:组织与命名
Check:
- All remotes organized under a consistent folder structure (e.g., )
ReplicatedStorage > Remotes > {Category} - Naming convention is consistent: for remote names,
PascalCasepattern (VerbNoun,PlayerRequestPurchase)ServerSyncInventory - No unused / orphaned remotes in ReplicatedStorage
- RemoteFunction and its response type are clearly paired by naming
- UnreliableRemoteEvents are clearly distinguishable by name or naming suffix (e.g., prefix)
Sync_
检查内容:
- 所有远程调用组织在统一的文件夹结构下(如)
ReplicatedStorage > Remotes > {分类} - 命名约定一致:远程调用使用大驼峰命名,采用"动词+名词"模式(如、
PlayerRequestPurchase)ServerSyncInventory - ReplicatedStorage中无未使用/孤立的远程调用
- RemoteFunction及其响应类型通过命名清晰配对
- UnreliableRemoteEvent通过名称或后缀清晰区分(如前缀)
Sync_
Networking Step 7: Anti-Patterns
网络步骤7:反模式
Flag these common networking mistakes:
- Using RemoteFunction in a hot path - blocks the caller. Prefer RemoteEvent.
- Using RemoteEvent when BindableEvent would suffice - a remote that only reaches scripts on the same player should be a BindableEvent, avoiding network overhead.
- Using RemoteEvent when UnreliableRemoteEvent would be better - for high-frequency cosmetic updates (position, VFX), unreliable saves bandwidth and CPU.
- Using UnreliableRemoteEvent for critical state - dropped packets will corrupt game state.
- No remote surface map - undocumented remotes make auditing and debugging harder.
- Inconsistent naming - ,
fireRemote,HandleRequestmixed in the same project.r1 - Remotes scattered across ReplicatedStorage - all remotes should live under a single folder.
Remotes - BindableEvent in ReplicatedStorage used cross-boundary - Bindables don't replicate; this will silently fail on the client.
标记常见的网络错误:
- 热点路径中使用RemoteFunction - 阻塞调用方,优先使用RemoteEvent。
- 可用BindableEvent却使用RemoteEvent - 仅向同一玩家的脚本发送消息时,应使用BindableEvent以避免网络开销。
- 可用UnreliableRemoteEvent却使用RemoteEvent - 高频外观更新(位置、特效)使用不可靠模式可节省带宽与CPU。
- 用UnreliableRemoteEvent传输关键状态 - 丢包会导致游戏状态损坏。
- 无远程调用面映射 - 未文档化的远程调用会增加审计与调试难度。
- 命名不一致 - 同一项目中混合使用、
fireRemote、HandleRequest等命名。r1 - 远程调用分散在ReplicatedStorage中 - 所有远程调用应放在单个文件夹下。
Remotes - ReplicatedStorage中的BindableEvent跨边界使用 - Bindable不会复制到客户端,此操作会静默失败。
Data Persistence Lens
数据持久化审查维度
Apply this lens when data persistence code changed: player data loading/saving, ProfileStore setup, data migration, or when auditing data integrity for production readiness.
当数据持久化代码变更时应用此维度:玩家数据加载/保存、ProfileStore配置、数据迁移,或为生产就绪性审计数据完整性时。
Data Step 1: Data Library Detection
数据步骤1:数据库检测
Search for how player data is stored:
- ProfileStore found (recommended): Continue to Step 2.
- Raw DataStoreService used directly: Flag as High priority. ProfileStore handles session locking, auto-save, BindToClose, retry logic, and schema reconciliation automatically. Recommend migration. Cross-reference: §4.
roblox-data - No data persistence found: Flag if the game needs it.
Verify ProfileStore installation:
- Wally dependency:
ProfileStore = "madstudioroblox/profileservice@1.4.0" - Or manual ModuleScript in ServerScriptService / ReplicatedStorage
- ProfileStore is required from the correct path
查找玩家数据的存储方式:
- 已使用ProfileStore(推荐):继续步骤2。
- 直接使用Raw DataStoreService:标记为高优先级问题。ProfileStore可自动处理会话锁定、自动保存、BindToClose、重试逻辑与Schema协调。建议迁移。参考:§4。
roblox-data - 无数据持久化:若游戏需要则标记为问题。
验证ProfileStore安装:
- Wally依赖:
ProfileStore = "madstudioroblox/profileservice@1.4.0" - 或手动在ServerScriptService / ReplicatedStorage中添加ModuleScript
- ProfileStore从正确路径
require
Data Step 2: Profile Structure Review
数据步骤2:Profile结构审查
Verify the (or equivalent schema):
PROFILE_TEMPLATE- Exists and is a table
- Contains a field (number, incremented on schema changes)
DataVersion - Uses nested structure for non-trivial games (separate ,
Currency,Progression,Inventorysections)Settings - Every field has a sensible default value (ProfileStore's fills missing fields from the template)
:Reconcile() - No Instance references in the template (only JSON-compatible types: number, string, boolean, table)
- Cross-reference: §6
roblox-data
验证(或等效Schema):
PROFILE_TEMPLATE- 存在且为表格类型
- 包含字段(数字类型,Schema变更时递增)
DataVersion - 复杂游戏使用嵌套结构(拆分、
Currency、Progression、Inventory模块)Settings - 每个字段有合理默认值(ProfileStore的会从模板填充缺失字段)
:Reconcile() - 模板中无Instance引用(仅使用JSON兼容类型:数字、字符串、布尔值、表格)
- 参考:§6
roblox-data
Data Step 3: Session Locking
数据步骤3:会话锁定
Confirm session locking is properly configured:
- is called after loading (GDPR compliance)
profile:AddUserId(player.UserId) - is connected, kicks the player if lock is stolen
profile:ListenToRelease() - strategy is used (waits for lock, does not fail silently)
"ForceLoad" - is called after loading to fill missing fields from template
profile:Reconcile() - Cross-reference: §5
roblox-data
确认会话锁定配置正确:
- 加载后调用(符合GDPR合规)
profile:AddUserId(player.UserId) - 连接,锁定被抢占时踢出玩家
profile:ListenToRelease() - 使用策略(等待锁定,不静默失败)
"ForceLoad" - 加载后调用从模板填充缺失字段
profile:Reconcile() - 参考:§5
roblox-data
Data Step 4: Lifecycle Review
数据步骤4:生命周期审查
Verify the full player data lifecycle:
| Event | Must Do | Cross-Ref |
|---|---|---|
| Load profile via | |
| Mid-game | Mutate | |
| Sync leaderstats to profile, call | |
| If using raw DataStore: parallel saves with 30s timeout | |
| Auto-save | ProfileStore handles internally. If raw: 5-min interval, exponential retry | |
Flag missing lifecycle handlers, especially release and .
PlayerRemovingBindToClose验证完整的玩家数据生命周期:
| 事件 | 必须操作 | 参考 |
|---|---|---|
| 通过 | |
| 游戏中 | 直接修改 | |
| 将leaderstats同步到Profile,调用 | |
| 若使用Raw DataStore:并行保存,设置30秒超时 | |
| 自动保存 | ProfileStore自动处理。若使用Raw DataStore:5分钟间隔,指数退避重试 | |
标记缺失的生命周期处理器,尤其是释放与处理。
PlayerRemovingBindToCloseData Step 5: Data Access Patterns
数据步骤5:数据访问模式
Check how data is read and written:
- Data is mutated via , not by calling DataStore methods directly
profile.Data.fieldName - Leaderstats /
IntValueare synced back toStringValuebeforeprofile.Data:Release() - Other scripts access player data via a getter module (), not by directly importing ProfileStore
getProfile(player) - Data writes happen immediately in memory; saves are handled by ProfileStore's auto-save interval
- Cross-reference: §4
roblox-data
检查数据读写方式:
- 通过修改数据,而非直接调用DataStore方法
profile.Data.fieldName - 释放前将leaderstats的/
IntValue同步回StringValueprofile.Data - 其他脚本通过 getter 模块()访问玩家数据,而非直接导入ProfileStore
getProfile(player) - 数据在内存中立即修改;保存由ProfileStore的自动保存间隔处理
- 参考:§4
roblox-data
Data Step 6: Migration Strategy
数据步骤6:迁移策略
If the game has evolved its data schema:
- field exists in the template
DataVersion - Migration functions exist for each version bump (v1→v2, v2→v3, etc.)
- is called after
DataMigrations.migrate(data)and beforeLoadProfileAsync:Reconcile() - Migrations are sequential, pure functions (no yields, no side effects)
- Migration for old data that lacks defaults to version 1
DataVersion - Cross-reference: §7
roblox-data
若游戏已演进数据Schema:
- 模板中存在字段
DataVersion - 每个版本升级都有迁移函数(v1→v2、v2→v3等)
- 后、
LoadProfileAsync前调用:Reconcile()DataMigrations.migrate(data) - 迁移为顺序执行的纯函数(无yield、无副作用)
- 缺少的旧数据默认迁移到版本1
DataVersion - 参考:§7
roblox-data
Data Step 7: Anti-Patterns
数据步骤7:反模式
Flag these common data persistence mistakes:
- Raw DataStore for player state instead of ProfileStore - missing session locking, auto-save, retry, BindToClose. Cross-ref: §4.
roblox-data - Saving too frequently - every coin pickup triggers a DataStore write. Rate limits will be hit. Cross-ref: §11.
roblox-data - No around DataStore calls - unhandled errors crash the script. Cross-ref:
pcall§11.roblox-data - Storing Instance references in DataStore - Instances are not serializable. Store IDs instead. Cross-ref: §11.
roblox-data - No data validation before save - NaN values or corrupt data can silently break the save. Cross-ref: §10.5.
roblox-data - Missing - no way to detect or migrate old schema formats. Cross-ref:
DataVersion§6.roblox-data - Session locking bypassed - using raw DataStore without manual lock implementation risks data loss. Cross-ref: §5.
roblox-data - No handler - server shutdown loses unsaved player data. Cross-ref:
BindToClose§10.3.roblox-data - Sequential saves in - with many players, 30s timeout may be exceeded. Must use
BindToClosefor parallel saves. Cross-ref:task.spawn§12.roblox-data
标记常见的数据持久化错误:
- 用Raw DataStore存储玩家状态而非ProfileStore - 缺少会话锁定、自动保存、重试、BindToClose处理。参考:§4。
roblox-data - 保存过于频繁 - 每次拾取金币都触发DataStore写入,会触发速率限制。参考:§11。
roblox-data - DataStore调用未包裹pcall - 未处理的错误会导致脚本崩溃。参考:§11。
roblox-data - 在DataStore中存储Instance引用 - Instance不可序列化,应存储ID。参考:§11。
roblox-data - 保存前未验证数据 - NaN值或损坏数据会静默破坏保存。参考:§10.5。
roblox-data - 缺少- 无法检测或迁移旧Schema格式。参考:
DataVersion§6。roblox-data - 绕过会话锁定 - 使用Raw DataStore但未手动实现锁定,存在数据丢失风险。参考:§5。
roblox-data - 缺少处理器 - 服务器关闭时会丢失未保存的玩家数据。参考:
BindToClose§10.3。roblox-data - 中顺序保存 - 玩家较多时,30秒超时可能不够,必须使用
BindToClose并行保存。参考:task.spawn§12.roblox-data