本文へ移動
cccskills
無料GitHub で公開

scenario-roblox-architecture

Use when structuring Roblox game code: where scripts go (ServerScriptService, ReplicatedStorage, StarterPlayerScripts), Script vs LocalScript and RunContext, a module loader or framework (Knit or none), services and controllers, how systems talk (signals, BindableEvents, attributes), CollectionService tags, cleanup with Trove or Janitor, Rojo project layout, or a round-based game core. Also when code is spaghetti, a script runs twice, require errors with 'required recursively', a module is nil on the client, a tool stops working after respawn, or memory climbs from leaked connections.

日本語の概要は準備中です。原文の説明を表示しています。

インストール方法を見る

含まれるファイル(53)

  • SKILL.md20.4 KB
  • references/critique.md4.9 KB
  • references/expert-notes.md22.3 KB
  • references/gui-paths.md11.5 KB
  • references/procedures.md73.8 KB
  • references/project-setup.md18.5 KB
  • references/sources.md15.7 KB
  • scripts/agentkit/architecture/ArchAudit.luau19.9 KB
  • scripts/agentkit/architecture/Binder.luau4.5 KB
  • scripts/agentkit/architecture/Loader.luau5.7 KB
  • scripts/agentkit/architecture/lune_arch_audit.luau1.1 KB
  • scripts/agentkit/architecture/lune_place_facts.luau2.1 KB
  • scripts/rbx_architecture.py13.7 KB
  • scripts/templates/arena/fixtures/first/FixtureLoadingModule.luau361 B
  • scripts/templates/arena/fixtures/FixtureDoor1/DoorScript.model.json332 B
  • scripts/templates/arena/fixtures/FixtureDoor1/init.meta.json25 B
  • scripts/templates/arena/fixtures/FixtureDoor1/Panel.model.json128 B
  • scripts/templates/arena/fixtures/FixtureDoor2/DoorScript.model.json332 B
  • scripts/templates/arena/fixtures/FixtureDoor2/init.meta.json25 B
  • scripts/templates/arena/fixtures/FixtureDoor2/Panel.model.json128 B
  • scripts/templates/arena/fixtures/FixtureSecondEntry.server.luau91 B
  • scripts/templates/arena/fixtures/FixtureTwiceProbe.client.luau445 B
  • scripts/templates/arena/fixtures/gui/FixturePerLife.model.json65 B
  • scripts/templates/arena/fixtures/gui/FixtureScreens/FixtureNested.model.json66 B
  • scripts/templates/arena/fixtures/replicated/CharacterCache.luau316 B
  • scripts/templates/arena/fixtures/replicated/CycleA.luau156 B
  • scripts/templates/arena/fixtures/replicated/CycleB.luau115 B
  • scripts/templates/arena/fixtures/replicated/FixtureRemote.model.json31 B
  • scripts/templates/arena/fixtures/replicated/GlobalRegistry.luau118 B
  • scripts/templates/arena/fixtures/replicated/LeakyClass.luau570 B
  • scripts/templates/arena/fixtures/replicated/LeakyServerModule.luau374 B
  • scripts/templates/arena/fixtures/replicated/Maps/FixtureMap.model.json245 B
  • scripts/templates/arena/fixtures/replicated/ReachesServer.luau286 B
  • scripts/templates/arena/fixtures/replicated/RemovalLogger.luau343 B
  • scripts/templates/arena/fixtures/replicated/ScoreGui.luau145 B
  • scripts/templates/arena/fixtures/replicated/ScoreService.luau428 B
  • scripts/templates/arena/src/assets/Maps/Crossroads.model.json2.5 KB
  • scripts/templates/arena/src/assets/Maps/Pillars.model.json3.2 KB
  • scripts/templates/arena/src/assets/Tools/Sword.model.json328 B
  • scripts/templates/arena/src/client/Controllers/RoundController.luau2.1 KB
  • scripts/templates/arena/src/client/Controllers/ShopController.luau1.3 KB
  • scripts/templates/arena/src/client/Main.client.luau778 B
  • scripts/templates/arena/src/first/Boot.client.luau342 B
  • scripts/templates/arena/src/gui/Shop.model.json632 B
  • scripts/templates/arena/src/server/Main.server.luau399 B
  • scripts/templates/arena/src/server/Services/MapService.luau5.3 KB
  • scripts/templates/arena/src/server/Services/PlayerService.luau1.9 KB
  • scripts/templates/arena/src/server/Services/RoundService.luau2.8 KB
  • scripts/templates/arena/src/server/Services/TeamService.luau1.7 KB
  • scripts/templates/arena/src/server/Services/WeaponService.luau3.3 KB
  • scripts/templates/arena/src/shared/Config.luau313 B
  • scripts/templates/arena/src/shared/RoundMachine.luau1.7 KB
  • scripts/templates/arena/src/shared/Signal.luau1.8 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

Roblox architecture (gameplay programmer and architect)

Target: Roblox Studio (October 2026 build) on macOS, driven through the scenario-roblox-expert toolkit.

Expert architecture on Roblox means placement and RunContext decide what runs where, one entry script per side boots every module in two phases, server modules own the truth that attributes mirror, and tags bind behavior to instances with an owner for every connection. This skill carries those rules from the sources, corrected by live tests in Studio 0.743, plus a tested arena core (round loop, teams, maps, HUD, shop, sword) and the tools that build and audit it. If a sibling skill named here is missing from your available skills, ask the user to install it (npx skills add scenario-labs/skills --skill <name>); unattended, proceed from tool schemas and flag the gap.

REQUIRED BACKGROUND: scenario-roblox-expert (channels, review loop, toolkit, current-Roblox traps).

Status (2026-10-19): 14 live tests pass in Studio 0.743; 8 offline checks pass (18 Lune unit tests, luau-lsp on both type solvers over code, fixtures and snippets, StyLua, selene).

Stance (the expert delta)

  1. Pin placement and RunContext: one entry Script per side. Use one Script with RunContext Server in ServerScriptService and one with RunContext Client in ReplicatedStorage (Roblox docs, Script locations; Ludius, n8IDTRW1EfM [00:01:34]; Leif, F3ASTJuO82A [00:03:18]). Everything else is a ModuleScript.

    • A Client Script in StarterPlayerScripts ran twice (live), with a "non-legacy RunContext" warning in Output.
    • Rojo 7.7.1 turns .client.luau into a LocalScript unless the project sets "emitLegacyScripts": false (verified). A LocalScript in ReplicatedStorage never runs.
  2. Boot in two phases through one loader. GetDescendants order is undefined, so no module may call another while loading (Suphi Kaner, YsXijBUUmmM [00:04:22]). Init sets up its own state and never yields; Start may yield and call others (Leif [00:02:25]; docs, start() on every module). Loader.luau adds what the sources skip [added]:

    • an explicit order, then the rest sorted by path; duplicate names fail (Suphi [00:01:50]);
    • one pcall per module, so one broken service does not stop the others;
    • an Init that yields is reported as an error;
    • a frozen registry and a boot report written as attributes.
  3. Server modules own the truth; attributes mirror it; UI owns nothing. A state service never requires its GUI; the GUI calls the service and listens (MrAsync [00:25:46 to 00:31:11]). Publish shared state as attributes on a Configuration that clients observe (Crusherfire, 6Q_p2ObUXSo [00:07:06]). Mirror absolute server times (EndsAt) so clients count down without a timer remote [added]. A property or attribute change and a remote are not ordered relative to each other (docs, Attributes; Server Authority): put the state in the remote payload, or publish it only as attributes and re-render on each change.

  4. Bind behavior by tag, filtered by ancestor. One module drives every tagged instance instead of a script per instance (B Ricey, Vi2FckNJv9w [00:02:44]; GnomeCode, UsPYgIW3rv8 [00:01:38]; docs). Two traps the sources miss [added]:

    • A tagged template in ServerStorage is in GetTagged too: bind only under chosen ancestors.
    • Moving a tagged part from ServerStorage back to Workspace fired no InstanceAdded (live): watch AncestryChanged.

    Binder.luau does both, connects the signals before GetTagged, and runs the cleanup that setup returns.

  5. Every connection has an owner with a lifetime. Wire cleanup to the owner that dies with it, for example a per-tycoon Trove instead of the player's (Crusherfire, 0moy04A9vFg [00:16:38]). Add to the cleanup object at creation (B Ricey, 2Msrw5w5cTs [00:09:27]). Set Workspace.PlayerCharacterDestroyBehavior to Enabled (Crusherfire, YWyJHwynM1M [00:12:34]). Under Deferred signals a Destroying handler runs after the destroy (Crusherfire, xz_G2n1Q8-U [00:12:45]). Live, the handler had not run before the yield and then read Parent nil: capture state before removal; removal handlers only clear tables. A listener connected inside another handler misses the fire already queued, and nested fires run breadth-first (Crusherfire [00:03:19 to 00:08:52]; live): connect every listener in Init.

    • Screens have a lifetime too: each spawn recopies StarterGui into PlayerGui, except direct children with ResetOnSpawn false; a Folder cancels false (docs, On-screen UI containers). Players die every round, so the HUD and shop use false (GnomeCode, oEWoyT-GBZY [00:14:38]) and their run-once controllers keep valid references (live).
  6. Server code and round content never sit in a replicated container. Exploiters can read ReplicatedStorage (Leif [00:01:00]; Crusherfire, 6Q_p2ObUXSo [00:09:13]). Maps stay in ServerStorage until needed, which cuts join traffic (docs, Data model). Clone one into Workspace per round and destroy it after (GnomeCode [00:11:03 to 00:13:51], who keeps them in ReplicatedStorage). Crusherfire relocates server modules from a system folder to ServerScriptService at start (6Q_p2ObUXSo [00:09:47]). Require siblings by relative path so a system can move (Crusherfire [00:23:46]).

  7. The client asks; remotes are made in code. Never create remotes by hand in Explorer (Leif, F3ASTJuO82A [00:04:28]). The client asks "can I build here?" and the server decides (Leif [00:05:39]). Check on the client to save bandwidth and again on the server (MrAsync [00:16:37]).

  8. Pick the framework by team, not taste. Knit-style frameworks decide for you, and everything depends on one service (B Ricey, MyK4o2pIpQw [00:17:58]); the 2025 sources build small loaders (Ludius, Leif, Crusherfire). Solo or small team: this loader, Signal and a cleanup module; an existing Knit codebase: keep it and add the audit [added]. A class only for several stateful instances (B Ricey [00:07:10]); a service is a singleton table (Leif [00:02:00]).

Establish first

  • Session shape: round-based, persistent world or hub; player count; teams.
  • New place or existing code: Rojo or Script Sync repository, Studio-only, or an existing framework to keep.
  • Team size and whether systems are shared across places (Roblox Packages for your own systems, Wally for third-party code).
  • Server Authority (AuthorityMode = Server): it forces Deferred signals and replicates only the first 64 attributes per instance.
  • StreamingEnabled, on in new places (these tests ran with it off): clients wait for streamed parts.

Defaults: Rojo project with emitLegacyScripts false, the arena skeleton below, Deferred signals, PlayerCharacterDestroyBehavior Enabled, --!strict.

Procedure

Setup: import rbx_architecture as A (it puts the lead's scripts on sys.path). Full code and recorded results are in references/procedures.md.

  1. Scaffold. A.scaffold(dest, name, fixtures=False) copies the arena skeleton plus Loader and Binder, writes the Rojo project and builds the place through rbx_env.new_place. GATE: A.place_facts(place) shows Server and Client RunContexts, SignalBehavior Deferred and PlayerCharacterDestroyBehavior Enabled; A.check(dest) returns 0 errors on both type solvers.

  2. Map the modules. Write the module map before code. Dependencies point from services to shared modules, never from a service to UI or from replicated code to the server.

    ModuleSideOwns
    PlayerServiceserverper-player and per-character tables, cleared on leave
    TeamServiceserverteam assignment and alive teams
    RoundServiceserverthe RoundMachine state, StateChanged, the GameState mirror
    WeaponServiceserverswords by tag: give, take, re-give on respawn
    MapServiceserverone map clone per round, rotation, pads, hazards by tag
    DamageService, ShopServiceserverhanded to scenario-roblox-gameplay and scenario-roblox-data
    RoundMachine, Config, Signalsharedpure logic, constants, signals (run in Lune)
    RoundController, ShopControllerclientHUD and shop, wired once, ResetOnSpawn false

    GATE: A.audit_file(place) reports 0 errors and 0 warnings, no require cycle and 0 unresolved requires.

  3. Boot. Each entry script calls Loader.boot(Loader.ordered(folder, order), {publish = script}). GATE: in a playtest, A.boot_report(pt) shows BootOk true, BootErrors 0 and BootCount 1 on both sides, with every init: before every start:. The console has no "required recursively" and no [Loader] line.

  4. State and mirrors. RoundService writes EndsAt, Winner, then RoundState; controllers re-render on every attribute change. Test_* attributes on GameState shorten the loop in Studio only. GATE: server state, client mirror and HUD text agree; capture the HUD, run image_checks and open the image.

  5. Tags and lifetimes. Bind tagged instances with Binder.bind(tag, setup, {ancestors = ...}). Clear player tables on PlayerRemoving and character tables on CharacterRemoving. Re-give round items on CharacterAdded, because a respawn empties the Backpack. MapService clones the map at Intermission and destroys it on the way to Lobby. GATE: five respawns mid-round leave one tracked character and one bound sword on the map. After a respawn, the HUD and shop are the same instances. In Lobby, Workspace holds 0 maps and 0 bound hazards, the instance count is back within 10, and frames meet the gate across a map load.

  6. Observe and iterate live. Open the place once with rbx_env.open_place inside rbx_env.place_slot(). After each edit, push sources with A.sync_sources(studio, dest) instead of reopening. GATE: A.run(s, "return ArchAudit.all(game)", kit=["ArchAudit"]) matches the offline tally, and tests/code/scenario-roblox-architecture/run_live.py exits 0.

Numbers

ValueNumberRelative to
Player latency100 to 300 msdocs, Client-server runtime
Studio playtest latency0 ms; simulate 50 to 150 ms each waydocs; Studio Settings, Network, or settings().Network
Module size smell500+ linesMrAsync [00:20:54]; ArchAudit module-size
Replicated attributes under Server Authorityfirst 64 per instance; names and strings up to 50 charactersdocs, Server Authority
Boot, measuredserver 5 services 1.56 to 2.52 ms; client 2 controllers 0.40 to 1.08 mslive, Studio 0.743
Client order, measuredReplicatedFirst ran 35 to 36 ms before client Main; IsLoaded false, then true; no character yetlive
Five respawns mid-roundinstances +3 or -3 (about 46,150); 1 character, 1 bound swordlive, 6 runs
Arena defaults2 players, 15 s intermission, 120 s round, 5 s ending, 0.25 s tick[added]
Frame gatep95 at most 20 ms, worst at most 33.3 ms at 60 fps (1.2 x and 2 x the budget)scenario-roblox-expert
Map cycle, measuredServer p95 17.3 ms, worst 17.5 to 20.0 ms across a clone; Lobby instance delta 0live, 3 runs

Quality gates

  • Measurable:
    • ArchAudit: 0 errors and 0 warnings outside fixtures; AgentKit Audit.all(game) has 0 errors.
    • Boot report on both sides: BootOk, BootErrors 0, BootCount 1.
    • Console: no "required recursively", "not a valid member", [Loader] or "non-legacy RunContext" lines.
    • Lifetimes: Characters equals the player count after respawns; in Lobby, 0 maps and 0 bound hazards, and the instance count is back within 10; Server and Client frames meet the gate.
    • run_live.py exits 0; the Lune unit tests pass; luau-lsp has 0 errors on both solvers (A.check); StyLua and selene are clean.
  • Visual: a capture during a round shows the HUD with the mirrored state; image_checks raises no flag and you open the image. A human reviewer gets an Explorer capture.

Common mistakes

MistakeSymptomFix
Client Script in StarterPlayerScriptsruns twice; Studio warns in Outputmove the entry Script to ReplicatedStorage, or use a LocalScript in StarterPlayerScripts
Rojo default emitLegacyScriptsclient entry in ReplicatedStorage never runsset "emitLegacyScripts": false
require of a live service from execute_luaufresh copy: fields nil, state emptyread the module's Studio-only attributes
Tagged template in ServerStoragetemplate gets behaviorancestors filter
Reparent within the DataModelbehavior missing after moving backAncestryChanged watch (Binder)
Round items given oncesword gone after respawnre-give on CharacterAdded during the round
Reading Parent in Destroying or CharacterRemovingnil under Deferredcapture state before destroy
Listener connected inside a handlermisses the fire already queuedconnect in Init, before anything fires
SetAttribute, then FireAllClients; the handler reads the attributecan read the old value on live serverssend the state in the payload
Maps in ReplicatedStorage or Workspaceevery client downloads every map at joinServerStorage, one clone per round (maps-replicated)
Run-once controller holding a ScreenGui with ResetOnSpawn trueHUD gone after the first deathResetOnSpawn false
ResetOnSpawn false on a ScreenGui inside a Folderrebuilt at every respawn anywaydirect child of StarterGui (reset-ignored-nested)
_G registry, duplicate module namessilent overwriteLoader registry; ordered errors on duplicates
Package with AutoUpdate offcopies never updateAutoUpdate on (Roblox Learn, AzKZy2BqIh8 [00:09:55])

Handoffs

  • Receives from: scenario-roblox-expert (brief, toolkit, place slot); scenario-3d and scenario-game-assets (models that arrive as tagged templates in ServerStorage).
  • Delivers to: scenario-roblox-networking (service layout, remote module slot), scenario-roblox-data (DataService boot slot, PlayerRemoving hooks), scenario-roblox-gameplay (hits and damage inside Binder setups), scenario-roblox-ui (controllers on GameState, the shop screen), scenario-roblox-luau (types, Signal, deferred events), scenario-roblox-tooling (Rojo project, CI), scenario-roblox-performance (leaks, streaming), scenario-roblox-animation (character scripts).
  • Form: the Rojo src/ tree, the module map, the ArchAudit report and results.json.

Current Roblox notes

  • Rojo 7.7.1 drops "Position" on a Part with exit 0 and leaves it at the origin: write a 12-number "CFrame" (verified).
  • Rojo 7.7.1 builds Script Sync's .local.luau and .legacy.luau as ModuleScripts named X.local and X.legacy (verified): do not mix the two suffix schemes.
  • require-by-string: ./, ../, @self and @game; special handling of Init modules is gone (version deltas row 23).
  • SignalBehavior: new templates and Server Authority use Deferred; Default still maps to Immediate in older places. workspace.SignalBehavior failed with "not a valid member" from execute_luau (live): read it in Properties or from the file with Lune.
  • PlayerCharacterDestroyBehavior is NotScriptable: set it in Properties or in the Rojo project.
  • CollectionService:CreateCollection is documented, but in Studio 0.743 it errored "Collections are not enabled" (live). Use tags and Binder.
  • Next Gen Studio UI is the default: menu paths in references/gui-paths.md.
  • Creator Store assets cannot require(assetId): vendor the code.

References

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

コメント

ログインなしで書き込めます。使ってみた感想、質問、動かなかった環境などを気軽にどうぞ。

まだコメントはありません。最初のコメントを書いてみませんか。

送信するとすぐに公開されます。メールアドレスや電話番号などの個人情報は書かないでください。URL は 2 つまでです。

0 / 1000 文字

このフォームは reCAPTCHA で保護されており、Google のプライバシーポリシーと利用規約が適用されます。

同じリポジトリのスキル

Handle review comments received on GitHub for the current branch's PR or a given PR number or URL, by triaging each unresolved thread, fixing what is warranted, pushing, and replying in each thread, when asked to address, fix or answer PR comments. Works in any Scenario repository.

日本語の概要は準備中です。原文の説明を表示しています。

scenario-labs/skills1,0882026年10月23日 更新

Generate one short Conventional Commits squash message describing only the net diff between the PR's base and head, set its header as the PR title, validate it with the repository's commitlint and both copy its description to the clipboard and display it, when asked for a squash message. Works in any Scenario repository, whatever its default branch.

日本語の概要は準備中です。原文の説明を表示しています。

scenario-labs/skills1,0882026年10月23日 更新

Refresh the current pull request description from its net changes, following the repository's PR template, when asked to update or write the PR summary. Works in any Scenario repository, whatever its default branch.

日本語の概要は準備中です。原文の説明を表示しています。

scenario-labs/skills1,0882026年10月23日 更新

scenario

無料

Use when connecting an AI agent to Scenario (scenario.com) through MCP, or when a task involves generating images, video, 3D, audio, sprites, textures, or game assets. Also when picking a Scenario model, running a LoRA, refining a generation prompt, uploading reference images, waiting on generation jobs, checking credits or quota, hitting Scenario auth, scope, or Forbidden errors, or setting up mcp.scenario.com in Claude Code, Cursor, VSCode, or another agent.

日本語の概要は準備中です。原文の説明を表示しています。

scenario-labs/skills1,0882026年10月23日 更新

Use when generating or handling 3D assets through the Scenario MCP server, including text-to-3D or image-to-3D meshes, GPT-6 Astra 3D or Claude Opus 5.5 3D, GLB, FBX, OBJ, STL, or VOX files, PBR-textured or game-ready models, voxel models, multi-view reconstruction, editing a mesh by prompt, retexture, remesh, UV unwrap, auto-rigging a biped or quadruped, or retargeting an animation, previewing a mesh in the 3D viewer, or downloading a model for import into Unity, Unreal, Godot, or Blender.

日本語の概要は準備中です。原文の説明を表示しています。

scenario-labs/skills1,0882026年10月23日 更新

Use when generating navigable 3D worlds or Gaussian splat scenes on Scenario via MCP: text-to-world, image-to-world, a 360 panorama or skybox turned into a walkable splat, multi-view photos or a video walkthrough reconstructed as a splat, or one object photo to splat. Keywords: World Labs Marble 1.1, 1.1 Plus, 1.0 Draft, Hunyuan World, HY World, image-to-skybox, skybox-to-splat, multiview-to-splat, TripoSplat, gaussian splatting, 3DGS, spz, world generation, explorable scene, VR.

日本語の概要は準備中です。原文の説明を表示しています。

scenario-labs/skills1,0882026年10月23日 更新

scenario-labs のスキルをすべて見る

このスキルの問題を報告する