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:
  • wait()
    or
    spawn()
    in tight loops
  • Multiple
    RunService.Heartbeat:Connect()
    in same script
  • 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:
  1. File and line (or function name)
  2. What's wrong
  3. The specific fix (code)

对整体质量评级:
  • A - 可投入生产环境。代码整洁、架构清晰、安全合规、性能优异
  • B - 整体可靠,仅存在少量问题。只需轻微清理即可发布
  • C - 功能可用但需优化。发布时需附带说明
  • D - 存在重大问题。发布前需重构
  • F - 存在严重问题。当前状态禁止发布
按严重程度列出问题:
  • Critical(严重) - 安全漏洞、数据丢失风险、崩溃问题
  • High(高) - 内存泄漏、性能瓶颈、功能故障
  • Medium(中) - 代码异味、已废弃API、架构组织混乱
  • Low(低) - 风格不一致、缺少文档
每个问题需包含:
  1. 文件与行号(或函数名)
  2. 问题描述
  3. 具体修复方案(代码示例)

Step 8: Refactoring Suggestions

步骤8:重构建议

If significant issues found, suggest refactoring priorities:
  1. Immediate - Must fix before next publish
  2. Short-term - Fix in the next development cycle
  3. Long-term - Plan for when the project grows
For each suggestion:
  • What to change
  • Why it matters
  • Estimated effort (small/medium/large)

若发现重大问题,提出重构优先级:
  1. Immediate(紧急) - 下次发布前必须修复
  2. Short-term(短期) - 在下一个开发周期内修复
  3. 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
RemoteEvent
and
RemoteFunction
instances. Search for
:FireServer
,
:FireClient
,
:InvokeServer
,
:InvokeClient
to map the full remote surface.
Record every remote found with:
  • Name
  • Location (ReplicatedStorage path)
  • Direction (Client→Server, Server→Client, Client↔Server)
  • What it appears to do

查找所有
RemoteEvent
RemoteFunction
实例,搜索
:FireServer
:FireClient
:InvokeServer
:InvokeClient
以梳理完整的远程调用面。
记录每个远程调用的信息:
  • 名称
  • 位置(ReplicatedStorage路径)
  • 方向(客户端→服务器、服务器→客户端、客户端↔服务器)
  • 功能描述

Security Step 2: Validation Check

安全步骤2:验证检查

For each remote, verify:
  • Argument type checking - Server validates
    typeof(arg)
    for every parameter
  • 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
    ReplicatedStorage
    (secrets, configs with admin keys)
  • No server-only logic in
    StarterPlayerScripts
    (game state, anti-cheat)
  • No player data exposed to other players via remotes (unless intentional)
  • RemoteEvent payloads don't include excess data (send only what's needed)
  • No
    require()
    paths to server-only modules from client scripts

验证内容:
  • 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:
  1. Remote/method affected
  2. Exploit scenario (how an attacker would abuse it)
  3. Impact (what they gain)
  4. Fix (specific hardened code)

对问题分类:
  • Critical(严重) - 可被直接利用获取优势(免费货币、物品复制、账号接管)
  • High(高) - 可能导致数据暴露或损坏
  • Medium(中) - 中等成本即可滥用
  • Low(低) - 违反最佳实践,但难以被利用
每个漏洞需包含:
  1. 受影响的远程调用/方法
  2. 攻击场景(攻击者如何滥用)
  3. 影响范围(攻击者可获得的收益)
  4. 修复方案(具体加固代码)

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:
  • wait()
    and
    spawn()
    (yield-based, blocks thread)
  • RunService
    loops (Heartbeat, Stepped, RenderStepped frequency)
  • GetDescendants()
    and
    GetChildren()
    in loops (expensive at scale)

查找已知反模式:
  • wait()
    spawn()
    (基于yield,会阻塞线程)
  • RunService
    循环(Heartbeat、Stepped、RenderStepped的调用频率)
  • 循环中使用
    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
    Heartbeat:Connect()
    in the same script (consolidate into one)
  • Excessive RemoteEvent usage (batch updates, reduce frequency)
  • Tight loops without
    task.wait()
    (thread starvation)
  • Unindexed table operations (linear search vs hash lookup)
  • String concatenation in loops (use table.concat instead)
  • Instance.new()
    in hot paths (cache and reuse)
  • Deep
    WaitForChild()
    chains (cache references)

检查内容:
  • 同一脚本中存在多个
    Heartbeat:Connect()
    (应合并为一个)
  • RemoteEvent过度使用(批量更新,降低调用频率)
  • task.wait()
    的密集循环(线程饥饿)
  • 未索引的表格操作(线性搜索vs哈希查找)
  • 循环中拼接字符串(应使用table.concat)
  • 热点路径中使用
    Instance.new()
    (缓存并复用实例)
  • 深层
    WaitForChild()
    链(缓存引用)

Performance Step 4: Memory Audit

性能步骤4:内存审计

Check for:
  • Undisconnected events (every
    :Connect()
    must have a matching
    :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?
  • FireAllClients
    vs
    FireClient
    - Target specific players when possible
  • Debouncing - Are rapid-fire remotes properly debounced server-side?

检查内容:
  • RemoteEvent调用频率:是否每帧都发送更新,而实际上1次/秒就足够?
  • 每个事件的数据大小:载荷是否过大?
  • 不必要的复制:是否向所有玩家发送数据,而实际上仅部分玩家需要?
  • FireAllClients
    vs
    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:
  1. What's slow
  2. Why it's slow (technical explanation)
  3. The fix (specific code change)
  4. Expected improvement

生成优先级列表:
  • Critical(严重) - 导致崩溃或完全无法游玩
  • High(高) - 明显卡顿、掉帧或瞬移
  • Medium(中) - 性能不佳但可用,资源浪费
  • Low(低) - 微小的优化机会
每个项需包含:
  1. 性能瓶颈点
  2. 技术层面的卡顿原因
  3. 修复方案(具体代码变更)
  4. 预期优化效果

Performance Step 7: Apply Fixes

性能步骤7:应用修复

Provide optimized code for each finding. Include before/after with expected impact.
Common fixes:
  • Replace
    wait()
    with
    task.wait()
  • Consolidate Heartbeat connections
  • Add
    task.wait()
    to prevent thread starvation
  • Cache
    GetService()
    calls
  • 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:
  1. Metric - What was measured (frame time, memory, network traffic)
  2. Before - Original value
  3. After - Improved value
  4. Change - Percentage improvement
  5. Remaining - What's left to optimize

记录优化效果:
  1. 指标 - 测量内容(帧时间、内存、网络流量)
  2. 优化前 - 原始数值
  3. 优化后 - 提升后的数值
  4. 变化率 - 优化百分比
  5. 剩余空间 - 仍需优化的内容

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
MarketplaceService
usage. Find all GamePass and DevProduct references. List all existing monetization.
Record:
  • 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

查找
MarketplaceService
的使用情况,找出所有GamePass和DevProduct引用,列出所有现有变现方式。
记录内容:
  • 所有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:
  1. What to implement
  2. Why it will increase revenue
  3. Implementation effort (small/medium/large)
  4. Where in the game to present it
  5. Pricing suggestion

按优先级列出变现优化建议:
  • Must-have(必备) - 直接提升营收的项
  • Should-have(应做) - 提升转化率或留存的项
  • Nice-to-have(锦上添花) - 优化现有营收的项
每个建议需包含:
  1. 实现内容
  2. 提升营收的原因
  3. 实现工作量(小/中/大)
  4. 在游戏内的展示位置
  5. 定价建议

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
RemoteEvent
,
RemoteFunction
, and
UnreliableRemoteEvent
instances. Search for
:FireServer
,
:FireClient
,
:FireAllClients
,
:InvokeServer
,
:InvokeClient
, and
:Invoke
to map the full remote surface.
Record 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

查找所有
RemoteEvent
RemoteFunction
UnreliableRemoteEvent
实例,搜索
: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:
TypeBest ForNotes
RemoteEvent
Fire-and-forget messagesMost common. No return value.
RemoteFunction
Request-response patternsBlocking. Avoid in hot paths. Prefer RemoteEvent + callback pattern.
UnreliableRemoteEvent
Loss-tolerant data (effects, cosmetics, position updates)Can drop packets under load. NEVER for currency, inventory, damage, game state.
BindableEvent
Intra-client or intra-server pub/subLocalScript→LocalScript or Script→Script only. Never cross Server↔Client boundary.
BindableFunction
Intra-client or intra-server request-responseSame boundary rule as BindableEvent.
Flag any remote using the wrong type:
  • RemoteFunction
    where
    RemoteEvent
    + response pattern would suffice
  • RemoteEvent
    used as BindableEvent (firing a remote only to reach other scripts on the same client)
  • RemoteEvent
    carrying critical data that should use reliable delivery
  • UnreliableRemoteEvent
    carrying game-critical state

验证每个远程调用是否使用正确类型:
类型适用场景说明
RemoteEvent
即发即弃消息最常用,无返回值。
RemoteFunction
请求-响应模式阻塞调用,避免在热点路径使用。优先使用RemoteEvent + 回调模式。
UnreliableRemoteEvent
可容忍丢包的数据(特效、外观、位置更新)高负载下可能丢包。绝不能用于货币、库存、伤害、游戏状态同步。
BindableEvent
客户端内部或服务器内部发布/订阅仅适用于LocalScript→LocalScript或Script→Script,绝不能跨服务器↔客户端边界。
BindableFunction
客户端内部或服务器内部请求-响应边界规则与BindableEvent相同。
标记使用错误类型的远程调用:
  • 可用RemoteEvent + 响应模式替代的RemoteFunction
  • 用作BindableEvent的RemoteEvent(仅向同一客户端的其他脚本发送消息)
  • 传输关键数据但未使用可靠传输的RemoteEvent
  • 传输游戏关键状态的UnreliableRemoteEvent

Networking Step 3: RemoteFunction Check

网络步骤3:RemoteFunction检查

RemoteFunction
is a blocking pattern - the caller yields until the receiver returns. This can cause lag if overused.
Verify:
  • :InvokeServer
    is used sparingly (not per-frame or in tight loops)
  • :InvokeClient
    is only used when the server genuinely needs an answer from a specific client (rare)
  • Consider replacing with
    RemoteEvent
    + response event pattern for non-critical request-response flows
  • :InvokeClient
    has a timeout safeguard (client may not respond)

RemoteFunction
是阻塞模式——调用方会等待接收方返回结果。过度使用会导致卡顿。
验证内容:
  • :InvokeServer
    使用频率低(不用于每帧或密集循环)
  • :InvokeClient
    仅在服务器确实需要特定客户端返回结果时使用(罕见场景)
  • 考虑用RemoteEvent + 响应事件模式替代非关键的请求-响应流程
  • :InvokeClient
    设置了超时保护(客户端可能无响应)

Networking Step 4: Bindable Audit

网络步骤4:Bindable审计

BindableEvent
and
BindableFunction
are strictly intra-boundary (Server→Server or Client→Client).
Check:
  • No
    BindableEvent
    /
    BindableFunction
    in ReplicatedStorage that is fired by server and listened to by client (use
    RemoteEvent
    instead - Bindables don't replicate)
  • Client-side
    BindableEvent
    s are used for decoupling LocalScripts (cleaner than direct module references)
  • Server-side
    BindableEvent
    s are used for service-to-service pub/sub within the same script context
  • No orphaned or unused Bindable instances left in the hierarchy

BindableEvent
BindableFunction
严格限定在同一边界内(服务器→服务器或客户端→客户端)。
检查内容:
  • ReplicatedStorage中不存在由服务器触发、客户端监听的BindableEvent/BindableFunction(应使用RemoteEvent——Bindable不会复制到客户端)
  • 客户端BindableEvent用于解耦LocalScript(比直接引用模块更清晰)
  • 服务器BindableEvent用于同一脚本上下文内的服务间发布/订阅
  • 层级中无孤立或未使用的Bindable实例

Networking Step 5: UnreliableRemoteEvent Audit

网络步骤5:UnreliableRemoteEvent审计

UnreliableRemoteEvent
trades reliability for speed. Data may arrive out of order, arrive duplicates, or not arrive at all.
Verify:
  • 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     -- UnreliableRemoteEvent

UnreliableRemoteEvent
以可靠性换取速度,数据可能乱序到达、重复到达或完全丢失。
验证内容:
  • 仅用于可容忍丢包的数据:外观特效、非关键位置插值、粒子触发、声音事件
  • 绝不用于:货币交易、库存变更、伤害计算、游戏状态转换、解锁/升级操作
  • 客户端有 fallback 逻辑(若外观事件丢失,游戏仍可正常运行)
  • 服务器不依赖不可靠传输来维护权威状态
推荐模式——分离关键与外观远程调用:
luau
-- 关键数据:可靠的RemoteEvent
local PurchaseRequest = ReplicatedStorage.Remotes.PurchaseRequest  -- RemoteEvent
-- 外观数据:不可靠
local HitEffectSync = ReplicatedStorage.Remotes.HitEffectSync     -- UnreliableRemoteEvent

Networking Step 6: Organization & Naming

网络步骤6:组织与命名

Check:
  • All remotes organized under a consistent folder structure (e.g.,
    ReplicatedStorage > Remotes > {Category}
    )
  • Naming convention is consistent:
    PascalCase
    for remote names,
    VerbNoun
    pattern (
    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.,
    Sync_
    prefix)

检查内容:
  • 所有远程调用组织在统一的文件夹结构下(如
    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
    ,
    HandleRequest
    ,
    r1
    mixed in the same project.
  • Remotes scattered across ReplicatedStorage - all remotes should live under a single
    Remotes
    folder.
  • 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:
    roblox-data
    §4.
  • 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协调。建议迁移。参考:
    roblox-data
    §4。
  • 无数据持久化:若游戏需要则标记为问题。
验证ProfileStore安装:
  • Wally依赖:
    ProfileStore = "madstudioroblox/profileservice@1.4.0"
  • 或手动在ServerScriptService / ReplicatedStorage中添加ModuleScript
  • ProfileStore从正确路径
    require

Data Step 2: Profile Structure Review

数据步骤2:Profile结构审查

Verify the
PROFILE_TEMPLATE
(or equivalent schema):
  • Exists and is a table
  • Contains a
    DataVersion
    field (number, incremented on schema changes)
  • Uses nested structure for non-trivial games (separate
    Currency
    ,
    Progression
    ,
    Inventory
    ,
    Settings
    sections)
  • Every field has a sensible default value (ProfileStore's
    :Reconcile()
    fills missing fields from the template)
  • No Instance references in the template (only JSON-compatible types: number, string, boolean, table)
  • Cross-reference:
    roblox-data
    §6

验证
PROFILE_TEMPLATE
(或等效Schema):
  • 存在且为表格类型
  • 包含
    DataVersion
    字段(数字类型,Schema变更时递增)
  • 复杂游戏使用嵌套结构(拆分
    Currency
    Progression
    Inventory
    Settings
    模块)
  • 每个字段有合理默认值(ProfileStore的
    :Reconcile()
    会从模板填充缺失字段)
  • 模板中无Instance引用(仅使用JSON兼容类型:数字、字符串、布尔值、表格)
  • 参考:
    roblox-data
    §6

Data Step 3: Session Locking

数据步骤3:会话锁定

Confirm session locking is properly configured:
  • profile:AddUserId(player.UserId)
    is called after loading (GDPR compliance)
  • profile:ListenToRelease()
    is connected, kicks the player if lock is stolen
  • "ForceLoad"
    strategy is used (waits for lock, does not fail silently)
  • profile:Reconcile()
    is called after loading to fill missing fields from template
  • Cross-reference:
    roblox-data
    §5

确认会话锁定配置正确:
  • 加载后调用
    profile:AddUserId(player.UserId)
    (符合GDPR合规)
  • 连接
    profile:ListenToRelease()
    ,锁定被抢占时踢出玩家
  • 使用
    "ForceLoad"
    策略(等待锁定,不静默失败)
  • 加载后调用
    profile:Reconcile()
    从模板填充缺失字段
  • 参考:
    roblox-data
    §5

Data Step 4: Lifecycle Review

数据步骤4:生命周期审查

Verify the full player data lifecycle:
EventMust DoCross-Ref
PlayerAdded
Load profile via
LoadProfileAsync
, reconcile, store in cache
roblox-data
§4
Mid-gameMutate
profile.Data.*
directly, leaderstats sync back
roblox-data
§4
PlayerRemoving
Sync leaderstats to profile, call
profile:Release()
roblox-data
§4
BindToClose
If using raw DataStore: parallel saves with 30s timeout
roblox-data
§10.3
Auto-saveProfileStore handles internally. If raw: 5-min interval, exponential retry
roblox-data
§10.1
Flag missing lifecycle handlers, especially
PlayerRemoving
release and
BindToClose
.

验证完整的玩家数据生命周期:
事件必须操作参考
PlayerAdded
通过
LoadProfileAsync
加载Profile,协调数据,存入缓存
roblox-data
§4
游戏中直接修改
profile.Data.*
,leaderstats同步回数据
roblox-data
§4
PlayerRemoving
将leaderstats同步到Profile,调用
profile:Release()
roblox-data
§4
BindToClose
若使用Raw DataStore:并行保存,设置30秒超时
roblox-data
§10.3
自动保存ProfileStore自动处理。若使用Raw DataStore:5分钟间隔,指数退避重试
roblox-data
§10.1
标记缺失的生命周期处理器,尤其是
PlayerRemoving
释放与
BindToClose
处理。

Data Step 5: Data Access Patterns

数据步骤5:数据访问模式

Check how data is read and written:
  • Data is mutated via
    profile.Data.fieldName
    , not by calling DataStore methods directly
  • Leaderstats
    IntValue
    /
    StringValue
    are synced back to
    profile.Data
    before
    :Release()
  • Other scripts access player data via a getter module (
    getProfile(player)
    ), not by directly importing ProfileStore
  • Data writes happen immediately in memory; saves are handled by ProfileStore's auto-save interval
  • Cross-reference:
    roblox-data
    §4

检查数据读写方式:
  • 通过
    profile.Data.fieldName
    修改数据,而非直接调用DataStore方法
  • 释放前将leaderstats的
    IntValue
    /
    StringValue
    同步回
    profile.Data
  • 其他脚本通过 getter 模块(
    getProfile(player)
    )访问玩家数据,而非直接导入ProfileStore
  • 数据在内存中立即修改;保存由ProfileStore的自动保存间隔处理
  • 参考:
    roblox-data
    §4

Data Step 6: Migration Strategy

数据步骤6:迁移策略

If the game has evolved its data schema:
  • DataVersion
    field exists in the template
  • Migration functions exist for each version bump (v1→v2, v2→v3, etc.)
  • DataMigrations.migrate(data)
    is called after
    LoadProfileAsync
    and before
    :Reconcile()
  • Migrations are sequential, pure functions (no yields, no side effects)
  • Migration for old data that lacks
    DataVersion
    defaults to version 1
  • Cross-reference:
    roblox-data
    §7

若游戏已演进数据Schema:
  • 模板中存在
    DataVersion
    字段
  • 每个版本升级都有迁移函数(v1→v2、v2→v3等)
  • LoadProfileAsync
    后、
    :Reconcile()
    前调用
    DataMigrations.migrate(data)
  • 迁移为顺序执行的纯函数(无yield、无副作用)
  • 缺少
    DataVersion
    的旧数据默认迁移到版本1
  • 参考:
    roblox-data
    §7

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:
    roblox-data
    §4.
  • Saving too frequently - every coin pickup triggers a DataStore write. Rate limits will be hit. Cross-ref:
    roblox-data
    §11.
  • No
    pcall
    around DataStore calls
    - unhandled errors crash the script. Cross-ref:
    roblox-data
    §11.
  • Storing Instance references in DataStore - Instances are not serializable. Store IDs instead. Cross-ref:
    roblox-data
    §11.
  • No data validation before save - NaN values or corrupt data can silently break the save. Cross-ref:
    roblox-data
    §10.5.
  • Missing
    DataVersion
    - no way to detect or migrate old schema formats. Cross-ref:
    roblox-data
    §6.
  • Session locking bypassed - using raw DataStore without manual lock implementation risks data loss. Cross-ref:
    roblox-data
    §5.
  • No
    BindToClose
    handler
    - server shutdown loses unsaved player data. Cross-ref:
    roblox-data
    §10.3.
  • Sequential saves in
    BindToClose
    - with many players, 30s timeout may be exceeded. Must use
    task.spawn
    for parallel saves. Cross-ref:
    roblox-data
    §12.
标记常见的数据持久化错误:
  • 用Raw DataStore存储玩家状态而非ProfileStore - 缺少会话锁定、自动保存、重试、BindToClose处理。参考:
    roblox-data
    §4。
  • 保存过于频繁 - 每次拾取金币都触发DataStore写入,会触发速率限制。参考:
    roblox-data
    §11。
  • DataStore调用未包裹pcall - 未处理的错误会导致脚本崩溃。参考:
    roblox-data
    §11。
  • 在DataStore中存储Instance引用 - Instance不可序列化,应存储ID。参考:
    roblox-data
    §11。
  • 保存前未验证数据 - NaN值或损坏数据会静默破坏保存。参考:
    roblox-data
    §10.5。
  • 缺少
    DataVersion
    - 无法检测或迁移旧Schema格式。参考:
    roblox-data
    §6。
  • 绕过会话锁定 - 使用Raw DataStore但未手动实现锁定,存在数据丢失风险。参考:
    roblox-data
    §5。
  • 缺少
    BindToClose
    处理器
    - 服务器关闭时会丢失未保存的玩家数据。参考:
    roblox-data
    §10.3。
  • BindToClose
    中顺序保存
    - 玩家较多时,30秒超时可能不够,必须使用
    task.spawn
    并行保存。参考:
    roblox-data
    §12.