301 results · client-side index
On engine 26.07 both [GameResource] and NavMesh.GetSimplePath are marked [Obsolete] (CS0618), so a zero-warnings build gate fails on them. Replace [GameResource(...)] with [AssetType(...)] and GetSimplePath with NavMesh.CalculatePath, which returns a NavMeshPath of NavMeshPathPoint (not List<Vector3>).
The [GameResource("Name","ext","desc")] attribute on a GameResource subclass now raises CS0618 obsolete. It is a warning, so a green dotnet build hides it unless the project treats warnings as errors. Switch to [AssetType] with named properties. The type still derives from GameResource, still writes an .ext file, and is still found by ResourceLibrary.GetAll<T>(). Only the declaring attribute changes, and the old Icon argument has no replacement.
A component with [Sync] fields added in OnStart (after NetworkSpawn) never replicates: each peer creates its own local instance and the sync pair silently never matches. The law covers engine components too: a Rigidbody built post-spawn is exactly this bug (Velocity is [Sync]-backed).
@ref on a private field compiles with only a CS0649 warning: the ref stays null at runtime. Bind to a property instead.
A #if DEBUG guard inside a .razor component is always false in every configuration, so it strips nothing, and the razor source plus any sibling .scss ship into the uploaded package as readable text regardless. Build anything that must be absent from a release as a plain .cs class.
A second editor instance launched with -joinlocal is not a real Steam lobby member, yet Networking.GetData still resolves the host's Networking.SetData values -- they arrive over the ServerDataMsg the host sends on connect, not via lobby membership. The message can lag scene load by a few frames, so read GetData in a short poll loop.
A -joinlocal second instance connects to whichever process holds the loopback port 127.0.0.1:55333, so the precondition to check is socket ownership, not which editor is in play mode.
A -joinlocal second instance never runs the in-game Join UI: it connects straight to the editor's loopback dev-host socket, so it presents an empty invite code. Any host that verifies the code on the wire will correctly reject it, breaking the local two-peer test even though every other hop is healthy. It's a harness artifact, not a product bug.
A baked navmesh is a cached derived copy of the world, so a door leaf that swings clear in physics leaves the doorway solid on the navmesh until you regenerate the tile.
A pure C# Panel subclass has no settable Style.Rotate shortcut reachable from code the way razor markup can write transform:rotate(Xdeg). Rotate it by building a PanelTransform, calling AddRotation, and assigning it to Style.Transform each frame the angle changes.
A joining client can build a code-generated world twice -- once on local StartupScene load, once on the networked scene handoff. A non-idempotent world author that clears its tracking lists but never destroys prior GameObjects stacks a whole second world. Make the author idempotent, and compute any sync hash from the build recipe, not a live scene scan.
Two-stage flow: Blender headless emits Y-up OBJ, then pure Python writes vmats/vmdls and a C# model catalog.
Update order is a property of the authored scene. A component added at runtime with Components.GetOrCreate goes on the end of the update list, no matter which GameObject it sits on. Per-frame input written from it lands too late for movement code that reads it the same frame. Drive the runtime component from an authored component's tick.
Input.Pressed and Input.Down read a global input state, not a per-entity one. A component that reads them in its own OnUpdate samples that global state once per instance. With one entity on screen this is correct. With many non-networked instances of the same component, one keypress fires the action on every instance at once. Gating only on IsProxy does not help, because IsProxy answers whether the entity is replicated, not whether this instance should own the keypress. Gate the input read on genuine local ownership instead.
When the editor console (or any text field) holds keyboard focus, every Input.* read in game code returns nothing, so a feature toggled from the console looks dead while the exact same feature works from its keybind. A debug camera in that state is pixel-identical to a broken one. Game code cannot take focus back; the fix is to make the silence loud.
A project resource type that claims a file extension the engine already owns can lose a registration race, with no error. The losing type's ResourceLibrary.GetAll returns empty and files deserialize as the engine type instead. Which side wins is decided per editor launch. Audit the extension with asset_types before you commit to it.
A projected Sandbox.Decal seated on a character's analytic hit surface (e.g. a capsule hit position) with a shallow projection Depth paints the base skin mesh but ends before the clothing renderers' outer shell, so paint shows only where bare skin peeks out. Increase Depth to span the cloth shell without punching through thin limbs.
Networking.CreateLobbyAsync branches on Application.IsDedicatedServer straight into the dedicated-server path and never opens a lobby, so lobby-creation code written for peer-hosted play does nothing useful on a dedicated server.
A flex: 1 spacer takes all remaining height in a column, so every sibling after it starts at the container's bottom edge. Under overflow: hidden those trailing controls are laid out but never drawn: hover and onclick stay intact while zero pixels reach the screen. Put a spacer between two blocks that both fit, or bottom-anchor a group with margin-top: auto.
Census tris × instances before decimating; prefer BoxCollider over ModelCollider for decorative props.
s&box regenerates .csproj from the editor and gitignores them, so a fresh git worktree's Code/ and Editor/ folders have no project file and dotnet build fails MSB1009. Copy the csproj in, or, at a different depth, author one with absolute paths.
A timeout accumulator gated on a control-signal sample (throttle > threshold) resets to zero on frames where the signal legitimately reads zero, so it never fills. A gear change drives the throttle magnitude through zero on a fixed cadence, and an unstick routine that alternates gears makes that happen forever, so a stuck vehicle is never declared wrecked. Drive give-up timers from ground-truth state, such as position progress since the last known-good, never from a control signal that pulses through the reset value by design.
The editor can report a clean compile for both the game and editor compilers while the running assembly is still stale. A green status is necessary but not sufficient. Confirm the load with a symbol that is new this session.
Compiling an s&box game assembly outside the editor needs the exact csproj shape the editor generates, and even a perfectly green offline build cannot surface whitelist violations. The SB1000 analyzer runs only in the editor compile pass, so code can build with 0 errors and 0 warnings offline and still be rejected in-editor. Build the editor-generated Code/<project>.csproj directly and confirm against the editor compile_status, never the offline build alone.
An AnimFile whose name contains a hyphen never reaches the compiled model. The fbx bakes, the animation list writes, the vmdl compiles green with no errors and no warnings, and the sequence is simply absent at runtime. The SkinnedModelRenderer.Sequence.Name setter accepts the missing name and echoes it back, so the obvious guard cannot fire. Sanitise the typed name to one hyphen-free word, and check Sequence.SequenceNames before you assign.
In a .razor file, `word@Expr.Member` (e.g. `P@Score.Value`) is parsed as a literal string, not an expression. Razor's email-address heuristic sees the `foo@bar.baz` shape and treats the whole thing as text. The element renders the raw source, with no compile error and no warning. Put the literal inside the expression instead: `@($"P{Score.Value}")`.
A razor background-image referencing a loose PNG/JPG renders in-editor (loose Assets are readable off the mounted filesystem) but goes blank in the published package, because loose non-compiled images are not auto-shipped. Add the disk glob to the sbproj Resources list; the wildcard matches the loose disk path, not the normalized asset path.
At single-digit sun elevation a street canyon gets no direct ground light, so nothing on the ground casts a visible shadow while the cascade is billed in full; fix it with sun azimuth, not renderer flags.
Code under Code/ hotloads fine, but an Assets/ folder created AFTER the editor started never mounts: asset search finds nothing in it and asset_info reports no asset. It is not a dead watcher; the only fix is restarting the editor.
In s&box razor UI the declared width/height of a panel is the OUTER number: padding and borders sit inside it, not added on top. The default already behaves like box-sizing: border-box, with no such declaration anywhere. Author every width/height as the outer number the mockup shows; adding padding/border by hand under-sizes every box by exactly its own padding.
An absolutely positioned child with a percent size resolves against the nearest ancestor that is a positioning context, not against the track you can see. A track div does not become a positioning context by carrying flex, padding, a background, or a fixed size. It needs an explicit position declaration. Without one, height: 100% resolves against the panel root, so a stat-bar fill sized width N percent by height 100 percent floods the whole panel and buries the cards under it. Set position: relative on the track, then sweep every sibling with the same pattern, because small absolute children hide the same defect by landing in the wrong corner instead of flooding.
A progress fill built as a plain flex child sized by width:N% renders as a small detached pill floating partway along the track, because the engine's flex layout does not left-pin an under-width percent child the way a browser does. Fill must be position:absolute in a position:relative track.
On current builds a PointLight created with Shadows = true contributes nothing to the frame: no light, no shadow, silently. The six-face cubemap shadow path is broken while SpotLight's single-view path works. For a directional lamp, cast with a downward SpotLight instead.
Org/ident rules, every store-page field is launch-blocking, AI thumbnails demoted: verify as a player after publish.
public int X { get; init; } = SomeClass.SomeProperty; passes headless dotnet build but fails the editor compile with CS0182: the editor's code generator embeds initializers where only constants are legal. Default to a constant sentinel and resolve later.
Naming a Component method `public void Reset()` compiles clean and silently hides the engine's own `Component.Reset()`. The only signal is a CS0114 warning, which `dotnet build -v q` never prints. Green is not the same as warning-free: pick a different name (ResetState, Clear) unless you deliberately mean to hook the lifecycle method.
A primitive authored with a rotation parameter spins about its own object origin, wherever it was placed, not about the part's intended pivot. A raked hood then see-saws about its own middle and shows half the intended wedge in each direction. Rotate the placement coordinate around the pivot first, then place the box there with the same rotation baked in, and remember that a rotated box's own bounding box is trigonometric, not its declared half-length.
An image you write to FileSystem.Data at runtime (a per-save thumbnail, a screenshot) is not addressable from a CSS background-image URL -- those resolve against mounted content, not the user Data FS. Decode it into a Texture in code and assign Style.BackgroundImage instead.
Scene.Trace leaves SceneTraceResult.Hitbox null unless the trace calls .UseHitboxes(true). A target that carries model hitboxes but no body collider is invisible to a plain trace: the ray reports no hit at all. Mixing a coarse collider with hitboxes lets the collider shadow them, so a head shot resolves as a body hit.
A ScreenPanel lays out against a logical canvas that is fixed in height at 1080 and takes its width from the window aspect ratio. At a 1920x1080 window the canvas measures 2060.7 x 1080, not 1920 x 1080. Vertical and left-anchored values from a 1920-wide mockup transfer 1:1, but anything hard-centred with arithmetic against an assumed 1920 width sits off-centre. Centre with flex, never with math.
A Panel with overflow: scroll and real overflow content answers WantsDrag = true, and FindDragTarget walks up from the pointer to the first ancestor that claims the drag. That ancestor steals every press-and-drag from any slider, scrub bar, or knob inside it. Set CanDragScroll = false on the scroll container in OnTreeBuilt.
A PhysicsHullFile node compiled with import_mode HullPerElement treats a material break as an element boundary. Paint two adjoining primitives with a second material and the compiler folds them into one element and builds one convex hull across both. The convex hull of a wall with a hole in it is a solid wall, so every doorway and window built the same way seals shut at once, with no geometry change in the diff. Every offline check stays green, because none of them compile the model. The defect is only visible in the compiled collision, which the editor or an in-engine walk probe can see. Fix by giving physics its own single-material copy of the source mesh, so the render mesh's material list never reaches the physics node, and pin the physics mesh to the render mesh with a lint.
Running a second s&box process under the same Steam account (an editor or dev instance alongside the published client) correlates with P2P joins to a live remote host failing rendezvous inside the engine's fixed ~3.5s connect budget. Close every second same-account instance before drawing any conclusion from a P2P connectivity failure.
On a track that crosses itself (a figure-eight, or any lap that revisits the same ground), a per-frame nearest-waypoint lookup jumps about half a lap at the crossing, because two points that sit close together can be arclength-distant. Drive lap position from a monotone cursor that only advances along the committed branch, do lateral math in a left-of-travel frame, and keep the branch-discrimination cone tighter than the branches' angular separation.
A Standalone export changes the data path, log filename, quit behaviour, boot flow, and convar timing versus the editor/published client. Tooling and automation built on editor assumptions silently miss files or spin, verified live on engine 26.07.22.
A static Func<>/Action<> field that holds a lambda survives hotload still pointing at the replaced assembly. Invoking it throws System.NotImplementedException: 'Unable to find matching substitution for a lambda method' in the next Play session, with a green compile. Guard the read with try/catch and self-heal, and re-assign the seam at session start.
public static Config Default => new(); on a struct binds to the runtime's implicit parameterless constructor, not your declared all-optional-parameter constructor: every intended default is silently discarded and the value comes back default(T).
A text element's line box measures max(declared line-height, the font's own natural box), so a column of rows built to a browser mockup's arithmetic runs long and overflows its fixed parent. Padding, borders, margins and gaps all measure exactly as declared: only the line box inflates. Size rows off the font size, not off an assumed 1.5×, and verify on a scale-1 capture.
SUPERSEDED: the font-size-declaration theory below was owner-settled (26.07.22) to be a CAPTURE-PATH artifact, not a live-render bug, and the mechanism was later traced to the root panel's fractional scale. Never strip font-size or letter-spacing from a shipping stylesheet to 'fix' captures. See camera-screenshot-cannot-verify-fonts.
Absolute-altitude biome thresholds tuned at one reference amplitude break when the slider moves -- the climate stack squashes or vanishes. Scale every altitude threshold by realized relief.
Trailing children of a tall absolutely-positioned flex column silently vanish (no overflow, no compression) because Yoga's auto-height under-measures the content. Fix: give the column an explicit height.
Disjoint file ownership, serialize hot files, report-don't-fix foreign errors, resume after interrupts: the concurrency rules that keep agent waves shippable.
An absolutely positioned child clips to the nearest ancestor that is a positioning context, not to its visual parent. A frame with flex, a fixed size, and a border radius but no position declaration is not a positioning context, so the absolute child skips past it and renders full-bleed against the screen root. A sibling screen using the same pattern renders correctly only because its own box already was the root, which makes the pattern look safe to copy. For one rectangle, drop the absolute child and paint the texture on the frame's own background.
A per-run accumulator guard (budget, cooldown, or streak counter) that resets on a transient state flicker never actually fires, because the reset zeroes it faster than it can fill. Reset only on a signal that truly ends the episode (sustained air, real forward progress), never on a per-tick proxy the episode itself trips constantly.
A component that injects movement input for automated testing has to sit first in the scene hierarchy and write on both OnUpdate and OnFixedUpdate, or every movement phase reads zero while looking still works. Input.AnalogMove is computed once per frame from the movement actions before components run, so setting the Forward/Back/Left/Right actions afterward moves nothing that frame. Write Input.AnalogMove directly for held movement instead. Components run in scene order, so a harness under the controlled character runs after the stock mover and its writes land one frame late, then get wiped. Movement is consumed on the fixed step while looking is consumed on the per-frame update, so a harness that injects only from OnUpdate passes every look phase and reads exactly zero on every movement phase.
An ICameraModifier runs against every camera that draws, including the editor viewport camera during play-in-editor, not just the camera its component belongs to. A modifier that writes only some view fields makes the viewport obey some instructions and ignore others. A first-person modifier that set view.Rotation but not view.Position froze the editor viewport at the player aim, so a camera tool had its position honoured and its rotation discarded. A transform readback cannot see this, because the override happens later during view composition. Filter every modifier callback to the game view with a check on IsMainCamera.
Glyph-block corruption in an MCP camera_screenshot is a capture-path artifact, not a live-render bug. The same UI renders text perfectly on the real screen. You cannot screenshot your way out of it: the requested width/height does not change the UI render scale, and sub-native requests crop the top-left. Verify geometry from a capture, never text fidelity; font-face and legibility are owner-eyeball checks.
An s&box game csproj project-references the engine's Base Library csproj inside the Steam install. A first build or a rebuild writes generated intermediates into the engine tree even with an absolute OutputPath, and duplicate attribute files under the base addon then stop the engine booting. BaseIntermediateOutputPath is not the fix, it is a second trap. Clear the base addon's obj and .build folders to recover.
A custom sound-mixer slot with no baked pick and no fallback event resolves to null and plays nothing, with zero log lines anywhere. A fully wired audio call stack can be completely mute behind a clean console. When sound is missing and the console is silent, check whether the mix was actually baked for that slot before blaming the caller.
Referencing an scss variable a sheet never defines passes both dotnet build and the in-editor compile_status clean, but at runtime the style parser logs a 'malformed rule' warning and the panel using that sheet can stop rendering entirely. Variables don't cross sheets, so copying a rule between sheets silently drops its variables.
A single-line XML doc comment that shares a line with the field it documents pulls the declaration into the comment. The compiler then sees no field at all. Nothing fails at the comment site. The break shows up later as a 'does not contain a definition' error wherever the field is used, which reads like a typo or a missing using. Put every XML doc comment on its own line, directly above the member.
Angles uses .pitch/.yaw/.roll (lowercase) and Vector3 uses .x/.y/.z. Capitalized sightings in a codebase belong to unrelated component properties.
System.Array.Clone() compiles clean in dotnet build but fails SB1000 in the editor: the headless build does not enforce the whitelist.
global using Sandbox + your razor namespace in Assembly.cs: without it, panels and game types don't resolve across the assembly.
A SkinnedModelRenderer created this frame has no attachment objects yet, and reading a bone before the first pose evaluates returns the bind pose. Resolving a mount in OnStart silently gets nulls or T-pose transforms, no exception either way. Defer and retry.
MP3 + JSON .sound beside it: no wav/ffmpeg; Distance is in inches; copy schema from addons/menu box_open.sound.
A scene-authored component cannot resolve, inside its own OnStart, a component that another component creates inside that other component's OnStart. Authored beside is not authored before, so the binder looks up the target before it exists, gets null, and holds that null for the whole session behind one warning line. The whole feature does nothing while every part it depends on works. Bind lazily instead: retry the lookup on a short interval until the target resolves, and warn once if it never does.
bpy.ops.wm.obj_export can reorder face lines across runs on the same mesh: diff the manifest, not the raw OBJ bytes.
Calling .Result or .Wait() on the main thread against a Task from GameTask.RunInThreadAsync deadlocks forever, silently. The process stays alive and the window still responds, but the frame loop is dead. Only join these tasks with await, or compute synchronously on the main thread.
border-style: solid is a parse error in s&box scss. The invalid property aborts the whole stylesheet, collapsing the panel to zero size -- invisible, not just unbordered.
The inset keyword on box-shadow is effectively ignored in s&box Razor panels: an inner vignette renders as an outer halo, and a full-screen inset vignette renders nothing at all. Build inner glows and vignettes from linear-gradient bands instead.
A fresh git worktree of an s&box project cannot dotnet build, because the editor generates Code/<project>.csproj and gitignores it, and the csproj references the Steam engine DLLs by relative paths tied to the main tree's directory depth. A naive copy fails with MSB3245 when the worktree nests one level deeper. The durable fix rewrites the csproj with absolute engine paths and redirects OutputPath into an isolated folder. That second half matters everywhere: the default OutputPath is the shared .vs/output/ folder with no project segment, so any CLI build on the machine writes into the same directory. A sibling build there empties a running editor's TypeLibrary, and every game component reads as MissingComponent while compile_status still reports Success. Build headless with the editor closed and output redirected, or pass -p:OutputPath to keep the build out of the shared directory.
protected override int BuildHash() is a PanelComponent member; a logic-only Component has no such method, so the override fails headless with CS0115. Easy to hit when you split a UI feature into a logic Component beside its PanelComponent view and copy the 'keep the tree stable' BuildHash idiom onto the logic component too.
No native drag helper exists for PanelComponent sliders. Use the engine's SliderControl pattern: MousePanelEvent.LocalPosition over track width, with pointer-events routing.
One ScreenPanel host, static UIState for modals, self-closing panels, toast stack: BuildHash every flag the markup reads.
A camera that switches focus target or follow distance on a state change jerks even when position is exponentially smoothed. Smooth the target point and distance separately: the position lerp can't hide a discontinuous input.
Deriving a visual's facing from horizontal velocity causes 180-degree snaps on any momentum reversal. Lock facing to an attach-time azimuth for pendulums and oscillators.
When one character stands on another that uses a collider-less trace mover, standing can't happen physically -- you synthesise it by pinning the rider's feet to the carrier's head each fixed step. Seat at the VISUAL mesh head-top, not the physics capsule height, or the rider sinks into the carrier's head and reads as two merged characters.
A chase camera that reads a raw fixed-tick position field per render frame makes the player model sawtooth side-to-side. Read WorldPosition (context-sensitive interpolated getter) instead.
A child-combinator rule targeting the universal selector (`.parent > *`) is silently dead in s&box razor SCSS: no error, no warning, the rule simply never applies.
For a chunked runtime-mesh generator, REGEN (single-threaded generation CPU) is the binding resource, not fps or draw calls. Quartering the chunk count produces zero regen change; the lever is threading the passes.
The stock citizen animgraph ships combat params that CitizenAnimationHelper does NOT wrap -- drive them with renderer.Set() directly, and replicate them yourself because the engine only networks locomotion.
The Citizen animgraph drives body aim from SetLookDirection("aim_body", dir, weight), not from the aim_body_pitch / aim_body_yaw floats. Writing only the floats reads back perfectly and moves the pose zero degrees.
HoldType shapes arm+fingers, body aim tilts via SetLookDirection (the aim_body_pitch/yaw floats are readback-only), and an IK hand target OWNS hand position, overriding the holdtype arm pose. Move the IK target to place a held item, use holdtype only for the fist.
Published game boots with error.vmdl placeholders; engine may rewrite prefab refs, no auto-retry; restart editor + republish.
BoxCollider is cheap and follows WorldScale; Capsule/ModelCollider don't scale with WorldScale and ModelCollider is costly on clutter.
A brand-new custom .shader committed without its compiled .shader_c fails its first in-editor load with a misleading 'Invalid Dependency Information' / file-not-found error chain, even when the HLSL is correct. The engine loads shaders only from .shader_c -- commit both.
Components.Get<SkinnedModelRenderer>() only searches the same GameObject: a renderer on a child returns null, silently no-oping every Set() call.
A side-by-side follow slot must sit perpendicular to the leader's own heading, never perpendicular to the line between the two characters. The line-between-the-pair definition is circular, because it is built from where the follower already is, so each correction chases the last one and the pair collapses to single file. Measured error was 89.6 degrees from the line rule versus 0.2 degrees from the heading rule. Derive the slot axis from the leader's forward vector rotated 90 degrees.
Networking.HostStats and Connection.Stats read zero on a local loopback two-instance session, including Ping and ConnectionQuality, so a bandwidth instrument built on those fields latches zero even while traffic flows. Count bytes at the application layer instead.
Networking.CreateLobby is async: Networking.IsActive is still false on the same frame, so any branch on IsActive takes the wrong path. Gate on your own synchronous mode enum instead.
Adding a public method to the game assembly and calling it from the editor-tools assembly in the same hot-reload pass throws MissingMethodException at runtime: both compile_status and dotnet build are green.
Set Sequence.Blending = true once: per-clip fade_in/fade_out times in the vmdl shape the blend; no AnimGraph required.
CSS @keyframes plus the animation: shorthand are supported in s&box razor SCSS, so a spinner or looping effect is pure CSS -- do not drive it from a per-frame BuildHash re-render.
A custom GameResource with a file extension longer than 8 characters silently never registers as a compilable source type. Every asset fails with "no source file." Keep extensions to 8 lowercase chars or fewer.
A projected Sandbox.Decal renders its colour as lit surface albedo, not an unlit overlay: a pale/pastel tint washes out to a barely-there stain on a bright surface.
A decimated heightfield mesher renders carved cliffs as alternating sawtooth teeth; consistent diagonals and majority-vote corner snapping don't fix the crest. Sort the four corner samples, find the largest gap, and average only the cluster above it.
Census tris × instances first: silhouette fails before UVs; inject usemtl after scripted OBJ export.
A freshly SteamCMD-installed sbox-server.exe is not self-contained -- it needs the matching .NET runtime on the box, or it dies before any game logic.
A headless sbox-server running an unpublished local .sbproj boots and creates a lobby, but every joiner fails with 'Package local.<ident> wasn't found!': publish the package first (Hidden visibility is sufficient).
A stationary vertical sink at a chunk-corner seam defeats eject, mantle, and even hard-recover (the anchor itself can be buried under an overhang). The terminal escape is a top-out to the chunk surface.
Showing a loading overlay and running a synchronous main-thread job in the same handler never paints the overlay -- the blocking work runs before the render pass. Show the overlay, count down a couple of frames, then run the blocker in OnUpdate.
A voxel/heightfield world usually carries two surfaces: a fine render mesh and a coarser collision heightfield. Procedural character-facing geometry (climb grips, standoff nodes) must be sampled from the collision surface, or it floats off the real face the character actually touches.
Dev-host streaming sends assemblies and compiled assets but NOT loose data files read via FileSystem.Mounted: a joining client that loads a raw JSON manifest builds differently, silently.
Scaling DirectionalLight.LightColor does not dim the sun: from 0.001 to 5.0 it renders identically; only Color.Black turns it off. LightColor sets hue, not brightness. A day/night brightness ramp built on it is a silent no-op.
GetAllComponents<T> (and every Scene/GameObject component query) skips disabled components, so a distance cull that toggles ModelRenderer.Enabled and then re-queries each frame silently loses exactly the objects it just disabled: a census under-reports and a re-enable pass can never find its own objects. Capture renderer references once at spawn instead. ClothingContainer.Apply adds child renderers a self-only capture misses.
ModelRenderer.CastShadows doesn't exist as a settable property: use renderer.SceneObject.Flags.CastShadows instead.
Headless dotnet build is green while the in-editor compiler emits SB1000: Environment/IO/Process/reflection are banned in game code.
Jump() helpers clamp against rising velocity, eating the second impulse. Set Velocity.z directly for a reliable double jump.
GameObject.Destroy() in edit mode is deferred; a query fired right after returns the previous build's objects.
Razor HUD emoji and dashes die under Get-Content/Set-Content: edit with byte-safe UTF-8 APIs or a real editor.
Two screenshots of byte-identical geometry differ by tens of percent because editor auto-exposure adapts over wall-clock frames: settle the viewport and exposure-normalize before comparing.
The editor compiles and verifies its ProjectRoot working tree. A branch that lives only in a git worktree is invisible to it, and compile_status results silently reflect the wrong code.
Editor-embedded play mode pins at exactly 60 fps regardless of cvars. The cap is the compositor's vsync on the editor window, not the engine frame sync. Under the cap even the p50 pins to 16.67 ms: read the tail (p99, worst frame, over-budget count), not the median.
compile_status is fully green and the editor accepts edits, but Play executes the OLD code: touch, syntax-error cycling, and play restart all fail. Only a full editor process restart clears it.
Frame fps pins at 60 in the editor regardless of physics load: implement IScenePhysicsEvents.PrePhysicsStep/PostPhysicsStep with a Stopwatch to get the true, vsync-free CPU cost of the solver step.
The engine ships its built-in [McpTool]s as full C# source, not compiled DLLs: check addons/tools/Code/Mcp/*.cs for canonical patterns before inventing your own.
Every ICameraModifier in the scene runs against whichever camera is currently drawing, in ascending CameraOrder. A second camera inherits every modifier written for the primary one, even though the inspector shows its own transform as correct. Claim the view with your own modifier at a higher CameraOrder than anything else.
Failed package compile leaves the editor running the last-good hotload: multi-symptom 'regressions' are often stale code.
A front-flip rotation uses _baseRot.Forward (not .Right) when FacingYawOffset is ±90°: the offset swaps which local axis is perpendicular to travel.
An unqualified FileSystem compiles in a game assembly but CS0104s in an editor assembly: fully-qualify Sandbox.FileSystem in editor code.
Folders → sbproj → Assembly.cs → 4-object scene → green dotnet build → tagged logs on Play, then optional art tools.
RenderType.Off only kills the shadow, not the draw: use Tags.Set("viewer", true) on the visual root plus camera RenderExcludeTags for correct first-person body hiding.
On a dressed citizen, GetAllComponents<SkinnedModelRenderer>().FirstOrDefault() can return a bone-merged clothing renderer (a hat) instead of the body, silently, with no null. A sequence probe then reports every clip absent. Select the body renderer explicitly.
ERROR models or white materials persist after fixing the source: delete the compiled artifact AND touch the source file to force recompilation, or poke asset_compile per source file.
In s&box Yoga, an explicit flex-basis (notably flex-basis: 0 inherited from a base rule) takes precedence over width for a flex item's main-axis size: a fixed column collapses to zero.
A flex-grow slider track holding a normal-flow fill child sized by width:N% balloons wider as the value increases: take the fill out of flow with position:absolute, and make sure the track carries no overflow:hidden.
Foot-slide happens when PlaybackRate is tied to movement top speed instead of the clip's own authored stride distance.
complex.shader has no shipped source and no evidence it reads vertex color as albedo, so don't plan per-vertex color painting through it. The reliable runtime color-per-surface lane is a baked texture plus Material.CreateCopy and Set("Color", tex).
Forge delivery job errors out but the build stage's previewGlbUrl stays downloadable: recover the GLB through Blender into your standard delivery shape instead of re-spending.
When a world model is FP-hidden and replaced by a camera-attached viewmodel, cosmetics that must remain visible in FP need a separate copy parented into the viewmodel. Never re-tag the world copy visible.
Sandbox.Diagnostics.FrameStats and PerformanceStats are whitelist-clean and reachable from game-assembly components: build a relative perf probe without any engine benchmark API. Raw GC.GetAllocatedBytesForCurrentThread/GC.CollectionCount are SB1000-blocked in-editor; use PerformanceStats instead.
Turning a composite physics actor into static scenery by destroying its Rigidbody silently kills every child system that keyed its own liveness off that body. Set MotionEnabled = false instead: the body stays alive, dependents keep ticking, and a kinematic body reads zero delta-v for free.
A [Sync(SyncFlags.FromHost)] field on a runtime-created singleton never replicates: the object needs NetworkSpawn, not just NetworkMode.Snapshot.
A runtime-generated world root torn down with GameObject.Destroy() keeps rendering in edit mode because the deferred queue isn't flushed: use DestroyImmediate and sweep all matching roots.
GameObject.Destroy() is deferred to the end of the frame, so an object you just destroyed still exists, still answers, and still holds any exclusive claim it owns (IsMainCamera, a singleton slot, a registry entry) for the rest of that frame. Clear exclusive claims on the outgoing owner BEFORE calling Destroy, and never read a leak census in the same frame as the teardown it checks.
Gamepad triggers DO have a public smooth 0..1 analog read via Input.GetAnalog(InputAnalog.LeftTrigger/RightTrigger). Named Input.config actions bound to triggers remain digital-only (on/off): use the direct analog surface for proportional control.
When a lobby query drives a connect, validate the exact lobby candidate you will connect to (not results[0]), or a peer can connect to a lobby it never validated (build-skew, wrong-host connect that no gate catches).
Geometry parented under an IsStatic root samples its lit appearance at creation time and never resamples. A runtime write to a light component is invisible on that geometry until the world is rebuilt. So a lighting A/B that mutates a light live and re-observes static geometry shows no change, no matter how large the delta. The comparison reads as no effect when the real answer is never re-sampled. Run static-geometry lighting tests through the world build command, not a live component write.
.sbproj + Assets/Code/ProjectSettings/tools layout, 4-object scene + Bootstrap, dotnet build before anything else.
A git worktree at a different directory depth than the main checkout breaks the generated csproj's relative references to the sbox install: dotnet build fails with missing-assembly errors.
SUPERSEDED: the text-run-count theory below was owner-settled (26.07.22) to be a CAPTURE-PATH artifact, not a live-render bug, and the mechanism was later traced to the root panel's fractional scale. Do not trim text runs to 'fix' glyph blocks in a capture.
Per-cell dither or contour-wander in a greedy voxel mesher turns cliff skirts into vertical stripes: detect walls and key strata on raw height bands with dither neutralised.
compile_status shows Success and dotnet build is green, but play mode reports errors for symbols and lines that no longer exist in source: the play-mode hotloader compiled a stale mid-edit snapshot.
Lifting a flat overlay clear of the ground is only half the rule. Overlays also z-fight each other, and a full-lap overlay on a self-crossing path z-fights itself, which no single lift value can fix.
An idempotent ground-snap jitters on curved terrain because the slope curves away within each step: ease the downward snap at a bounded glue rate.
A grounded wish-speed servo (MoveTowards) silently clamps any externally applied velocity (mantle carry, knockback, launch) to the wish target within a few ticks of ground contact -- boundary measurements read green while the effect is imperceptible.
A per-frame visual-smoothing offset computed from raw fixed-tick state double-smooths against the engine's built-in FixedUpdateInterpolation, producing a 50 Hz sawtooth that reads as model flicker on stepped terrain: delete the manual smoother or compute against interpolated state.
The editor discovers a library under Libraries/ only if the folder contains exactly one .sbproj file. A hand-vendored library without one is silently ignored, producing a wall of CS0246 errors on every type it defines.
dotnet build reports 0 errors on .razor files the in-editor compiler rejects: the headless build doesn't surface the Razor errors the live editor's Roslyn compiler flags.
A headless dotnet build against the engine assemblies does not enforce the s&box sandbox access-control whitelist: code that builds clean headlessly can fail the editor compile with SB1000.
GameTask.RunInThreadAsync for parse/math; main thread only for engine objects; Yield every N items for loading UI.
A near-white chalky sky stays mid-grey or blue: fixing the sky texture alone isn't enough because the default tonemapping curve crushes highlights.
Top model plans and reviews; cheaper agents execute on disjoint files; telemetry-driven feel tuning: whitelist and stale-assembly traps included.
Deferred Destroy() leaves the old code-built world overlapping the fresh one for a frame: use DestroyImmediate for teardown before rebuild, and pair it with a recipe hash for belt-and-suspenders join verification.
The render node in a vmdl honours import_rotation. PhysicsHullFile and PhysicsMeshFile ignore it. So correcting an off-axis import with import_rotation fixes the picture and leaves the collision exactly where it was. The model builds clean with no error and no warning, photographs correctly, and a player walks straight through it. Bake a corrected engine-frame copy of the mesh that both the render node and the physics node read, rather than rotating one consumer with a property the other ignores.
CC0 kits import like any OBJ+vmdl; city kits share colormap.png, nature kits need per-color vmats, and facing is a per-model yaw guess.
An Input.config action bound to an editor/host-reserved key (F1-F3, F7, F8, Escape) silently never fires in Play. The capture map also differs between editor and published client -- bind game hotkeys to plain letters and verify in both.
WASD as Forward/Backward/Left/Right feeds AnalogMove; new Input.config actions need an editor restart: dotnet build is not enough.
Input.Keyboard.Pressed fires again on the OS key auto-repeat, not only on the physical down edge, so a toggle written on Pressed flips twice for any held key. Use a true down-edge with previous-frame state (Down && !wasDown).
Input.Pressed (edge-trigger) is frame-scoped -- reading it in OnFixedUpdate drops presses on frames with no tick, or fires them twice on frames with multiple ticks. Level reads (Input.Down) are fine in OnFixedUpdate. A systematic 100% input failure usually points elsewhere -- instrument each hop.
A dropdown paints cleanly over the block below it, and that block still eats every press. Paint order and hit order come from two different sums: render depth accumulates z-index down the tree, but hit-testing ranks siblings by SiblingIndex + ZIndex within each parent. An absolute menu that overhangs a later sibling looks perfect and is unclickable. Fix the ancestors, not the popup.
Whitelist divergence, loose Resource Files, and silent cloud-asset failures after publish.
A static Instance claimed behind if (!IsProxy) in OnStart grabs the host's character on a joining client: the client camera follows the wrong player forever.
A joining client's static join state (invite code, mode, attempt ID) gets wiped by the networked scene handoff: the bootstrap's OnEnabled resets statics before the join handshake uses them.
Standalone export hangs if PackageReferences still need sbox.game to resolve: don't accumulate cloud package deps casually.
Converting euler poses per-key can land on q vs -q. The interpolation takes a violent 360-degree detour. Negate the quat if dot(prev, new) < 0.
Always handle tr.StartedSolid: ignore that frame so an overlapped body can walk free; slide-trace the wish onto the hit plane.
A library extraction seam covers only the headline behavior: every other side effect of the replaced code path silently disappears unless explicitly reproduced on the consumer side.
A library host project fails to compile a library-mounted .scene asset: the resource compiler probes a mangled path, and the scene silently becomes an empty impostor.
sbox.exe -joinlocal +instanceid 1 gives you a real second peer against an editor host with no publish, no second Steam account, and no lobby discovery. It has no host selector: it joins whichever local editor is in PLAY MODE, so no other editor on the machine may be playing.
PNG/WAV/MP3/JSON must be listed in Project Settings → Resource Files without an assets/ prefix: #1 editor-vs-publish break.
Lowering the sea level in a priority-flood water pass doesn't drain interior lakes: they're perched at their own spill surface. Use a per-basin depth gate and a land floor for below-sea valleys instead.
A world-space Sandbox.Decal is fixed in world space, so a splat spawned on a character projects onto empty air the instant they move. Parent the decal under the character, store the hit in a bone's local frame, and re-pin its world transform to that bone every frame so it re-projects onto the moving skinned mesh.
Scene holds four GameObjects; Bootstrap OnStart builds the world in code: hotloads better, no scene/code drift.
Model.Load of a missing vmdl can return the orange ERROR mesh with the requested path as its Name: check IsError, not just null. And a failed load is cached for the life of the editor PROCESS: play_stop/play_start won't clear it, only a fresh editor will.
ModelRenderer.Tint is packed to eight bits per channel and the cast wraps instead of clamping, so a tint above 1.0 renders dark, not brighter. Rendered luminance follows (tint * 255) mod 256, so 1.02 drops to about 56 and 1.10 reads as 24 of 255. The channels do not wrap together, so a population jittered around 1.05 splits into flat red, yellow, and near-black frames that keep their texture detail and read like an atlas or UV fault. Normalise the authored tint ladder so the largest draw reaches white, and clamp at every sink where a colour becomes a renderer component.
Per-instance Tint on a flat-color vmat (white PNG + g_vColorTint) rotates hue or crushes random instances to black: use scale/yaw jitter instead.
Input.AnalogLook returns zero (camera never turns) unless the cursor is locked via Mouse.Visibility = MouseVisibility.Hidden -- the deprecated Mouse.Visible = false does NOT lock it.
Moving legacy assets out of a publish payload with git mv alone leaves compiled artifacts behind (they are gitignored), and a material/model-only dependency closure misses shared textures that kept assets still reference.
Play full path WITH .sound or bare filename only: partial paths like impact/boing never resolve; compiled assets can still be invisible mid-session.
OfType<IInteractable> on GetAllComponents<Component> returns nothing: GetAllComponents answers off a concrete-type index, so enumerate concrete types (or a shared abstract base) and union them.
RenderMeshFile alone compiles clean with zero physics: ModelCollider needs PhysicsMeshFile/PhysicsHullFile in the vmdl.
Blender +X becomes world −Y after OBJ import; yaw +90° faces +X, and Blender +Y rotation tips the +X edge down.
BuildHash() is the only re-render trigger: hash everything the markup reads, including collection contents and flags.
CapsuleCollider and ModelCollider ignore WorldScale; BoxCollider follows it. Bake scale into import_scale instead.
Component.Active is a real inherited member: naming your own bool Active silently shadows the engine's enabled flag. It is a CS0108 warning, not an error, so it ships easily; treat CS0108 as an error in code review.
The navmesh voxeliser erodes walkable surfaces by ceil(agentRadius/cellSize) whole cells on each side, so an opening narrower than that budget has no navmesh through it.
A batch of networking API facts, verified from the installed build's source and XML, that overturn common assumptions when you plan multiplayer code before it touches the compiler. LobbyInformation is a struct, so a null guard does not compile. Networking.Connections is deprecated in favour of Connection.All and emits CS0618. Connection.MaxChunkSize is internal, so game code hard-codes the 131072 value instead of referencing the symbol. NetworkAccessor exposes Owner, OwnerTransfer, and OrphanedMode as get-only, with AssignOwnership, SetOwnerTransfer, and SetOrphanedMode called after NetworkSpawn. Networking.TryConnectSteamId exists and is public. SB1000 whitelisting is assembly-level, so the real constraint on a networking call is public versus internal accessibility, not the whitelist. A green dotnet build does not mean an editor-green result for networked types.
A newly created .razor.scss file is not picked up by a running editor session: the panel component works but is unstyled until the next restart.
Disabling a collider does nothing for a hand-integrated kinematic controller: noclip must be a movement state that skips traces, gravity, and ground-snap entirely.
A trace-swept NPC with 'wall ahead, hold position this frame' freezes permanently when the desired direction is constant -- the identical trace hits the identical wall every frame.
A cached Component/GameObject reference guarded with == null still throws NullReferenceException after the object is destroyed: only IsValid() catches destroyed objects.
A consumer game plus a vendored library can be compile-gated fully offline using two scratch csprojs against the editor install's prebuilt base library DLL.
A singleton claimed in OnEnabled and nulled in OnDisabled traps any re-adopt poll that gates on Instance.IsValid(): the entity is never re-driven after a disable.
A PhysicsShapeList node compiles with several tagged PhysicsHullFile children, so one vmdl can carry a compound collision volume. The per-shape tags stay inert through a scene ModelCollider.
Rotation.FromYaw alone leaves a decal flat on the floor: build a rotation that aligns the thin axis to the surface normal, then offset along it.
Any cross-peer consumer (UI, host validators, scorers, range checks) that reads an owner-only simulation field gets frozen state on network proxies. Anchor off the replicated transform or redirect the field's getter.
[Sync] owner→proxies, IsProxy early-out; FromHost for shared truth. Every object carrying a [Sync] field has to be NetworkSpawned, singletons included.
The citizen's locomotion clips each carry their own authored ground speed in the animgraph's m_blendValue coordinates. Pacing every clip's PlaybackRate against one guessed nominal speed foot-slides every variant except the one it was tuned for.
OnAfterTreeRender(bool) is a Panel hook: on a PanelComponent it fails with CS0115; use parameterless OnTreeBuilt() or OnTreeFirstBuilt().
A per-cell white-noise hash for terrain shade choice reads as a 50/50 checkerboard. Use a smooth low-frequency noise field instead, confining the hash to threshold-edge dithering.
A multi-hull vmdl authored with per-shape collision_tags does not get those tags at runtime -- a scene ModelCollider overwrites every shape with the GameObject's own tags, so Scene.Trace.WithoutTags can't filter one hull from another. Split the hulls across separate collider GameObjects instead.
Ident is org.package: two lowercase segments; keep Org local until real; never put TODO placeholders in Org or the editor won't boot.
A Sandbox.Decal projects onto runtime-built chunk meshes (ModelRenderers) and conforms to stepped/curved faces, confirmed live on voxel terrain.
A waypoint-graph builder that prunes only isolated nodes still ships fully-connected but walled-off pockets, because graph kept is not graph reachable. In one build, sealed arena corners stranded 27 of 524 nodes as three internal pockets, and about 5% of a max crowd spawned where it could never leave. Filter destination and spawn candidates by connected component, using a flood fill from a known-good root, not by per-node validity checks.
A published-build client join reloads the game assembly, wiping all statics. The reconstruct-not-reset fix from the scene-handoff case has nothing to reconstruct from unless join intent is persisted to disk.
The Sandbox.Voice component defaults PushToTalkInput to 'voice', but not every project ships a matching 'Voice' InputAction. PTT is a dead key with zero errors until you add it to Input.config.
Networking.QueryLobbies appends a hidden:0 filter unless you pass a truthy hidden key, so a Hidden lobby is structurally excluded from every ordinary query. The bool overload param is includeServers, not hidden-inclusion. And editor hosts force Private privacy, which no filter overrides.
Quit-to-menu tears the game scene down inside Networking.DisconnectScope, so networking is still active during game-side teardown. A local quit is distinguishable from a host disband, and teardown code can still send graceful goodbyes.
s&box's radial-gradient parser accepts a color-stop list only. A standard CSS shape/size/position prelude (circle, ellipse, at 50% 50%) is read as the first color stop and aborts with a red 'Cannot read a color from ...' Code Error, silently dropping the rule. Write color stops only.
PhysicsShapeList + PhysicsJointList in the vmdl + ModelPhysics toggle. No collapse clips, no SetBoneTransform. On current builds ModelPhysics.PhysicsGroup reads NULL: enumerate ModelPhysics.Bodies directly and resolve bones by name→index.
A loading screen mounted right before a synchronous multi-second call never paints: one consumed tick isn't enough; gate the block on a frame counter (~6 frames) so the Razor pipeline finishes mount → style → layout → paint.
Thin flex rows with a gap inside a Razor RenderFragment expression under-measure their height and pile on top of each other. The same markup renders fine in the component's main root.
Razor component tag resolution does not consult global using directives: a library component renders as an inert HTML element while its class resolves fine in code-behind.
A collision rule that keys its direction on the struck object's own velocity is correct for the object that caused the hit and silently backwards for the object that got hit. A car rolling forward at 2 m/s and rammed from behind reads as moving forward, so it dents its nose instead of its rear. Derive the direction from the negated impulse delta-v, which points from the struck face inward for both bodies.
GetVertices/GetIndices flatten a multi-material compiled model into one buffer. Rebuilding with Materials[0] paints everything that first material (often black). Split indices by per-submesh counts and build one Mesh per range.
s&box loads Steam avatars through an avatar:<steamid64> texture-URL scheme usable from both SCSS background-image and C# Texture.Load. It returns a transparent placeholder immediately and swaps in the real avatar with no panel re-render.
GameObject.Tags inherit to all descendants, so a CameraComponent.RenderExcludeTags exclusion on a tagged object culls every child renderer too: cosmetics attached as children silently vanish.
A 'walk up the parent chain to the first ancestor tagged X' resolver silently breaks the moment any later pass tags a descendant with the same tag: the walk stops on the nearest match, not the intended root. Resolve identity against an authoritative roster instead, especially when the tag is also used for physics filtering.
Transfer rest-delta rotations parent-relative (not world): avoid the forward-hunch bug and never transform_apply scale on Mixamo armatures.
Bone-heat auto-weights fail on AI meshes. Use scripted geodesic (along-surface) weights, then FBX + animated vmdl.
Rigidbody API verified across multiple projects: Gravity, MassOverride, Velocity, ApplyForce, and the recipe for a dynamic pushable prop. AutoSleep lives on PhysicsBody (set-only as of 26.08.05), which is now populated on the same tick the component is created.
s&box ships Roboto Mono (all weights): JetBrains Mono and Consolas only resolve on dev machines with those system fonts. Only five families are reachable from UI CSS.
Rotation.FromYaw(+angle) is a LEFT (CCW) turn. Get the sign right or steering, AI, and autopilot spiral the wrong way.
An [Rpc.Broadcast] called on a component whose GameObject is not networked executes locally and silently never crosses the wire -- no warning at any log level.
SCSS background-image only resolves asset paths. Runtime Texture objects must be assigned via Panel.Style.BackgroundImage in OnTreeBuilt.
FlatBox/Prop/Deco/Wire helpers plus Obstacle records as plain data beat physics queries for build validity.
Nesting @{ } inside an already-open Razor code block (like @if or @for) causes RZ1010: you're already in C#, so drop the @.
OnAwake runs synchronously inside Components.Create: set singletons there; derive from [Property] in OnStart after spawn helpers assign.
s&box blends UI alpha in linear color space while browser-authored mockups blend in sRGB, so every low-alpha white/light surface renders substantially lighter in-engine than the same rgba() value looks in a browser. Opaque colors match bit-for-bit: the divergence is isolated to the alpha compositing step and worst at low alpha. Match target rendered pixels, never authored alpha numbers.
Engine 26.07.22 ships no .mixer resource type, so a project cannot author mixer buses as assets. Only Master, Default, and Voice exist, and the Mixer constructor is assembly-internal. Route category volume in code at play time through Sound.Play(string, Mixer) and SoundHandle.TargetMixer. Call Mixer.FindMixerByName first so the project picks up real buses if the engine ever ships authoring.
Assets / Code / Editor / ProjectSettings / tools: the template every project follows.
App 1892930 via SteamCMD runs a headless server with +game pointing at a local .sbproj: clients stream code/assets, no sbox.game publish required.
1 m = 39.37 engine units: design in SI, convert once at the engine boundary, and audit every consumer.
Scenes never load raw OBJ/GLB: always wrap with a .vmdl and remap materials under both bare and .vmat names.
Sandbox.Decal self-seeds with Random.Shared.Int(10000) on enable: a decal spawned identically on two peers renders differently by default.
Sandbox.Decal instances are lightweight scene objects with no hard engine cap, so a persistent-paint system can hold thousands. The failure mode is a gradual frame-time sag driven by fill-rate/overdraw, never a crash cliff. Bound it with a convar-backed ring buffer and bench for your target hardware.
Sandbox.Json.Serialize always emits pretty-printed JSON and exposes no public option to disable it: every network payload pays a whitespace tax. Re-drive the same serializer through a compact writer for a 41–56% size cut.
DTOs + one spawn path + deterministic static world: guard restored defaults; keep enums append-only.
A freshly-scaffolded project's Assembly.cs can be missing global using System. Transplanted code using Math/MathF fails with CS0103.
A component with Enabled = false is invisible to GetAllComponents: search returns null even though the component exists.
ScenePanel's Camera property is GET-ONLY. Assigning a new SceneCamera fails with CS0200. Configure the existing camera in place and build the preview world manually.
SceneTraceResult.EndPosition on a sphere-radius sweep is the sphere's CENTRE at contact, not the contact point. Treating it as where the feet landed is off by a full radius. Derive the real contact position as from + (to - from) * Fraction in one helper. A related trap: snapping the sphere exactly tangent to the floor makes the next horizontal sweep intermittently report StartedSolid.
ScreenPanel.ZIndex defaults to 100 (not 0), so any ScreenPanel that never sets a tier collides with the tier most projects author their modals at, and two roots with equal ZIndex have no defined paint order at all. Cross-root compositing is a stable OrderBy over an unordered HashSet, so tied roots keep an enumeration order that matches creation on a fresh boot but re-rolls on any enable/disable interleave or editor hotload. A full-screen surface can paint a perfectly healthy tree and still be invisible under a tied root.
ScreenPanel.ZIndex orders paint only: pointer input is NOT routed by cross-root stacking, so a lower-ZIndex root keeps swallowing clicks even when a higher-ZIndex modal draws over it.
When a clip already poses hands in a grip and the prop moves/rescales, offset the rendered visual child instead of using IK or SetBoneTransform -- sequence-only rigs have no AnimGraph.
Direct citizen sequence playback needs no AnimGraph, but SkinnedModelRenderer.UseAnimGraph must be set false BEFORE the first Sequence.Name write, or the write silently no-ops while the model's own animgraph keeps driving the pose. The citizen model exposes 466 sequences (raw directional locomotion + IdlePose family), enough for a full movement set with no rig work.
Re-setting a [ConVar] to the value it already holds is a silent no-op: the C# setter never runs, so a convar-triggered action does nothing, with zero console output. Statics survive Play stop/start, so a prior session leaves the value already set.
A trace-based ground controller flickers Ground/Air on seams, re-firing landing VFX mid-run. Require minimum air time before a JustLanded counts.
A SkinnedModelRenderer has no live SceneObject until the renderer first goes live. A Flags.CastShadows write at spawn time lands before the SceneObject exists, so it silently no-ops with no error and no warning. NPCs spawned with a shadow toggle off keep casting shadows anyway. Do not trust the write: read back the state that actually landed and retry on a staggered sweep across the following frames until the read-back matches the value you asked for.
The engine SliderControl renders its thumb position as a raw float in a CSS style attribute: near-min values with snap residue produce scientific notation (4.9E-06%), causing a style parse error.
When a continuous-float render surface sits over a quantized-step collision mesh, every quantize boundary becomes an invisible vertical wall the player hits but cannot see.
Sound playback is a static call, not a component. Use Sound.Play() for 2D and Sound.Play(pos) for 3D, and handle missing events gracefully.
On the host, spawning a joiner's character clobbers the host's own camera-target singleton because IsProxy is false at Components.Create time: re-resolve the claim at the first OnFixedUpdate.
If sbox-launcher.exe stays open during a Steam update, files vanish mid-install. Validate via steam://validate/590830.
Preview as of 2026-07: Valve approval + Facepunch license; full .NET, lose platform services; clean PackageReferences or startup hangs.
A C# static list/registry survives editor Play stop/start and code hotloads, holding references to destroyed GameObjects: gate iteration on IsValid(), don't rely on clearing alone. It can also mask a new scene's state when stale high-priority entries outrank it. Hand registrations back in OnDestroy.
s&box carries old static state forward on hotload and never re-runs static constructors: a registry entry added in source is absent at runtime despite green compile.
A Steam lobby survives its host switching to a different s&box game with stale metadata: a joiner connects and loads the wrong game's content.
A structural .razor change can throw a hotload exception that deregisters the project's entire toolset while compile_status still reports Success. Restart the editor to recover.
For a swept sphere/hull trace, HitPosition is the true surface contact point while EndPosition is the swept shape's centre at impact. Seat surface effects at HitPosition.
Use TextEntry with onsubmit and OnTextEdited: standard Blazor input bindings compile but are not how the engine UI works.
An untyped or expression-bodied lambda on TextEntry.OnTextEdited fails with CS8917 or CS0029. Use an explicit param type plus a block body.
Model compiler rewrites upper_arm.L → upper_arm_L; physics KV3 that still says .L makes limb bodies unknown while the torso works.
The Citizen ragdoll physics rig has 18 shapes (17 capsules plus 1 cylinder) and 16 joints (12 conical ballsockets plus 4 revolute hinges). A common folk estimate lands near 9 to 13 bodies, roughly half the real count, so it undercounts per-body and joint-solve cost. Both prefab files are plain KV3 text, so you count them offline with no editor running.
The editor MCP port is one engine-global preference, not a per-project setting. When the configured port is already bound by another open editor, the second editor logs a bind failure and starts no MCP server at all; it does not auto-increment to a free port. Bump the port by hand before (or after) launching the second editor, and have agents discover the live port by scanning and matching the Project field instead of pinning a number.
The engine ships its own render quality profiles, backed by real convars, that CAP what your scene asked for. A scene authoring 4 shadow cascades renders 2 for a Low-shadow player. And post-processing (AO, DOF, bloom, tonemapping, SSR) is opt-in per camera: none of it runs until the game adds the component, so a code-created camera renders flat, ungraded, and un-occluded no matter how well the lights are authored.
Default −Z/Y axes, bake_space_transform, no leaf bones, X/Z bone axes, mesh FBX + per-clip armature FBX; scale via ScaleAndMirror 0.3937.
A prop that reads as flat, plastic, or untextured almost always has a texture. The mip chain destroyed its contrast before the player saw it, because the detail was authored finer than the scale the surface is seen at.
The official s&box docs serve raw markdown by appending .md to any doc URL, and expose a full index at sbox.game/llms.txt. The site itself is a client-rendered Blazor app whose HTML contains no content, so scraping gets nothing.
The joiner's engine-side connect budget after entering a Steam lobby is a fixed ~3 seconds that game code cannot extend: any host-side delay exhausts it fast, so join recovery must be a fresh retry, never a longer wait.
Razor classes get a RootNamespace/folder-derived namespace: declare @namespace and global using or C# can't find your panels.
A repeating red "Texture manager doesn't know about texture ... default_mask ... returning error texture" pair on engine/RenderSystem is base-menu-addon noise mounted into every project, not your content. It repeats per draw call. There is no supported way to mute it from game code. Filter it visually.
static Instance set in OnAwake, cleared in OnDestroy: everything reads Foo.Instance with null-guards, no inspector wiring.
Sandbox.PlayerController's WalkSpeed / RunSpeed / DuckedSpeed / Speed are private serialized [Property] fields, so an external component can't cleanly scale player move speed (e.g. for a slow/root effect). WishVelocity is public but recomputed every fixed-update, so writing it is order-dependent. Swap in or subclass a controller that exposes a public knob.
The game-reachable engine surface has no scene/global time-scale multiplier: Scene.TimeScale does not exist, and the only TimeScale anywhere is on ParticleEffect. Sandbox.Time is read-only. A slow-mo / fast-forward feature must scale each system's own Time.Delta reads, or expose a hook for a future native mechanism.
SoundEvent has no Looping property: loop via compiled vsnd import options, or re-trigger from code when SoundHandle finishes.
s&box Razor panels have three distinct 'text is there but not on screen' failure modes (long-line clipping, narrow-segment overflow, and inline expression resolution), each with a different structural fix.
A hard SkyBox2D.SkyMaterial swap produces a visible pop, and stacking two SkyBox2D components with Tint alpha crossfade does not composite. The fix is a single custom sky shader that holds all time-slot textures and blends them by weight.
StartupScene is what Play loads; Org must be a valid lowercase ident. Placeholders break editor bootstrap, not just publishing.
SUPERSEDED: the font-size-declaration-count theory below was owner-settled (26.07.22) to be a CAPTURE-PATH artifact, not a real render bug. Panels with these exact font-size declarations render pin-sharp on the physical screen. Never strip font-size from a shipping stylesheet to 'fix' captures. See camera-screenshot-cannot-verify-fonts.
A trace-based kinematic character controller has no collider component, so trigger volumes and ITriggerListener never fire against it. Use distance polling instead.
A hand-integrated trace mover has no collider component: ITriggerListener and OnTriggerEnter never fire. Use distance-polling instead.
Even-time samples of a ballistic arc cluster at the slow apex and spread at the fast ends: sample by arc length for evenly spaced preview dots.
transition-delay, :intro and :outro all parse in the engine's razor-scss pipeline, tested isolated on engine build 26.07.22. An earlier caution that treated these selectors as unsupported can relax. A novel selector is worth one isolated test before you write it off, because an unparsed selector aborts the whole stylesheet to a 0x0 render.
The C# layer of s&box never closes per-pair Steam P2P sessions, so a host crash or task-kill poisons the pairwise transport state between two SteamIDs until Steam-side expiry clears it, typically minutes.
An undefined SCSS variable in a .razor.scss fails at runtime with only a console warning (no compile error, no toast) and the affected panels can render fully invisible. A trailing // comment on a value line fails the same way.
No paid storefront: revenue is clamped player-hours from a daily pool; retention is the monetization feature.
Shader field support is unknown and no .shader source exists: check the install's templates/ folder for authoritative syntax instead of grepping sibling projects.
AI mesh generators (Tripo, Meshy, Rodin) deliver textured OBJ+vmdl, but modeldoc32 headers, ~1m normalize, corrupt textures, bare texture paths, and missing colliders will ERROR the asset until patched.
Source engine convention: Forward = +X, Left = +Y, Right = -Y. Using Vector3.Right for '+X' silently slides geometry the wrong way.
With a visible cursor (MouseVisibility.Visible), mouse buttons that land on a pointer-events panel never reach Input.Down/Pressed, and Input.Keyboard.Down("mouse2") is not a bypass. Raw Mouse.Delta stays live, though, creating a separate trap.
C# hotloads on alt-tab in ms; scene changes and new Input.config actions need Play/editor restart; failed compile keeps the last-good assembly.
Literal spaces adjacent to a tag or @-expression boundary vanish in Razor markup: use a single interpolated string or CSS margin instead.
SetIk is AnimGraph-gated; SetBoneTransform is unsound on clip-keyed bones. Use proxy props, whole-visual motion, or commit to AnimGraph.
A long-running process started over a Windows OpenSSH session is killed the moment the session closes -- use a Scheduled Task instead.
Get-Content/Set-Content re-encodes BOM-less UTF-8 as ANSI; CRLF files break \n-only search-replace: use byte-safe APIs.
Stats.Increment/SetValue, Leaderboards.GetFromStat, Achievements.Unlock: cheap platform polish; total achievement score capped at 1000.
A button that never responds, with a clean console and a correct onclick handler, can be a BuildHash rebuild eating the click. If you write a focus-cursor field from onmouseover and that field participates in the panel's BuildHash, the mouse arriving over a row rebuilds the panel tree on the spot. The rebuild destroys and recreates the element under the cursor, and a press and release that straddles the rebuild is swallowed by the engine, so no onclick fires. Focus is a keyboard and gamepad concept, so never write it from a hover handler. Give the mouse its own affordance from CSS :hover, which needs no rebuild, and keep the keyboard focus index as a separate field if the panel needs both.
A zero-radius Scene.Trace.Ray passes straight through coarse voxel ModelColliders and returns Hit=false. Sweep a thin sphere (.Radius(...)) and it hits.