field-guide / search

301 results · client-side index

[GameResource] and NavMesh.GetSimplePath are obsolete on engine 26.07: use [AssetType] and CalculatePath

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>).

tooling-environment · ✓ 26.07.15a
[GameResource] is obsolete: declare custom resources with [AssetType]

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.

building-ui · ✓ 26.07.15a
[Sync] component created after NetworkSpawn silently never replicates

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).

writing-gameplay · ✓ 26.07.22
@ref on a bare private field silently never assigns

@ref on a private field compiles with only a CS0649 warning: the ref stays null at runtime. Bind to a property instead.

building-ui · ✓ 26.07.08e
#if DEBUG in a .razor file is always false: dev panels leak into release

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.

building-ui · ✓ 26.08.05
A -joinlocal dev-host client CAN read the host's Networking.SetData lobby metadata

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.

writing-gameplay · ✓ 26.07.15a
A -joinlocal peer joins whoever owns 127.0.0.1:55333, not whoever is in play mode

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.

writing-gameplay · ✓ 26.08.05
A -joinlocal test peer presents an empty invite code, so a wire-verified code gate rejects it

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.

writing-gameplay · ✓ 26.07.15
A baked navmesh does not follow a moving door

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.

writing-gameplay · ✓ 26.08.05
A code-behind Panel has no Style.Rotate shortcut: rotate it with a PanelTransform

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.

building-ui · ✓ 26.07.22
A code-built world can run TWICE on a network join and stack a second world on the first

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.

writing-gameplay · ✓ 26.07.15a
A complete Blender-headless → s&box pipeline

Two-stage flow: Blender headless emits Y-up OBJ, then pure Python writes vmats/vmdls and a C# model catalog.

getting-art-in · ✓ 26.07.08e
A component added at runtime updates after every authored one

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.

writing-gameplay · ✓ 26.08.05
A component that reads Input in OnUpdate fires on every instance at once

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.

writing-gameplay · ✓ 26.07.22
A console or editor text field with keyboard focus starves every Input read in game code

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.

writing-gameplay · ✓ 26.07.22
A custom asset extension can lose a registration race against an engine type

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.

tooling-environment · ✓ 26.08.05
A decal on a character paints bare skin but skips clothing: projection depth must span the shell

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.

writing-gameplay · ✓ 26.07.18
A dedicated server never creates a Steam lobby, so lobby-based join code does nothing

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.

writing-gameplay · ✓ 26.07.22
A flex: 1 spacer in a clipping column hides every control after it

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.

building-ui · ✓ 26.08.05
A frame-budget method for stylized s&box scenes

Census tris × instances before decimating; prefer BoxCollider over ModelCollider for decorative props.

making-it-perform · ✓ 26.07.08e
A git worktree can't build: the .csproj files are gitignored

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.

tooling-environment · ✓ 26.07.15a
A give-up timer gated on a control signal never fires when the control pulses through its reset value

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.

writing-gameplay · ✓ 26.07.22
A green compile status does not prove the new assembly loaded

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.

tooling-environment · ✓ 26.07.22
A green offline dotnet build misses s&box whitelist violations

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.

tooling-environment · ✓ 26.07.22
A hyphen in a sequence name drops the clip from the compiled model, silently

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.

rigging-animation · ✓ 26.08.05
A literal glued to the front of a Razor expression parses as an email address

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}")`.

building-ui · ✓ 26.07.22
A loose PNG in razor CSS renders in the editor but goes blank in the published build

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.

building-ui · ✓ 26.07.08e
A low sun in a street canyon leaves the ground unshadowed

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.

getting-art-in · ✓ 26.07.22
A new library Assets/ folder never mounts until you restart the editor

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.

tooling-environment · ✓ 26.07.22
A panel's width and height are the outer size (border-box by default)

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.

building-ui · ✓ 26.07.22
A percent-sized absolute fill floods the panel when its track has no position

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.

building-ui · ✓ 26.07.22
A percent-width flex child renders as a floating pill, not a left-anchored progress fill

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.

building-ui · ✓ 26.07.22
A PointLight born with Shadows = true renders nothing: use a SpotLight

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.

getting-art-in · ✓ 26.08.05
A pre-publish checklist for sbox.game

Org/ident rules, every store-page field is launch-blocking, AI thumbnails demoted: verify as a player after publish.

publishing-shipping · ✓ 26.07.08e
A property initializer that reads another property compiles headless but breaks the editor (CS0182)

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.

building-ui · ✓ 26.07.22
A public Reset() on a Component silently shadows the engine's Component.Reset()

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.

writing-gameplay · ✓ 26.07.22
A rotated procedural primitive spins about its own origin, not the part pivot

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.

getting-art-in · ✓ 26.07.22
A runtime-written Data-filesystem image needs a code Texture, not a CSS background-image URL

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.

building-ui · ✓ 26.07.15a
A Scene.Trace only reports a model hitbox when it opts in with UseHitboxes(true)

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.

writing-gameplay · ✓ 26.08.05
A ScreenPanel lays out against a height-fixed logical canvas, not a fixed 1920x1080

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.

building-ui · ✓ 26.07.22
A scroll container steals press-and-drag from every control inside it

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.

building-ui · ✓ 26.08.05
A second render material can seal a doorway shut in the compiled collision

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.

getting-art-in · ✓ 26.08.05
A second s&box instance on the same Steam account can make P2P joins fail rendezvous

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.

writing-gameplay · ✓ 26.07.15a
A self-crossing track breaks nearest-waypoint lap position; drive it from a monotone cursor

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.

writing-gameplay · ✓ 26.07.22
A standalone export differs from the editor runtime and breaks editor-built tooling

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.

tooling-environment · ✓ 26.07.22
A static Func/Action lambda orphaned by hotload throws NotImplementedException

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.

writing-gameplay · ✓ 26.07.15a
A struct's Default => new() silently skips your all-optional constructor

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).

building-ui · ✓ 26.07.22
A text line box is the taller of the declared line-height and the font's natural box

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.

building-ui · ✓ 26.07.22
A uniform font-size declaration still triggers glyph corruption

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.

building-ui · ✓ 26.07.15a
Absolute biome altitude thresholds break when height amplitude changes

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.

writing-gameplay · ✓ 26.07.15a
Absolutely-positioned flex column with auto height silently drops trailing children

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.

building-ui · ✓ 26.07.08e
Agent workflow: file-ownership and plan-review-delegate

Disjoint file ownership, serialize hot files, report-don't-fix foreign errors, resume after interrupts: the concurrency rules that keep agent waves shippable.

ai-assisted-workflow · ✓ 26.07.08e
An absolute child of an unpositioned panel escapes to the screen, not the panel

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.

building-ui · ✓ 26.08.05
An accumulator guard that resets on a transient flicker never fires

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.

writing-gameplay · ✓ 26.07.15a
An automated input harness reads zero movement unless it runs first and injects on both steps

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.

writing-gameplay · ✓ 26.08.05
An ICameraModifier writes to every camera that draws, including the editor viewport

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.

writing-gameplay · ✓ 26.08.05
An MCP camera_screenshot cannot verify font faces or text legibility

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.

building-ui · ✓ 26.07.15a
An output-path override can poison the engine's base addon and stop it booting

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.

tooling-environment · ✓ 26.08.05
An unbaked sound-mixer slot resolves to null and plays nothing, silently

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.

audio · ✓ 26.07.22
An undefined scss variable silently kills the whole panel -- no compile gate catches it

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.

building-ui · ✓ 26.07.15
An XML doc comment on the field's own line deletes the field

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.

building-ui · ✓ 26.07.22
Angles struct fields are lowercase

Angles uses .pitch/.yaw/.roll (lowercase) and Vector3 uses .x/.y/.z. Capitalized sightings in a codebase belong to unrelated component properties.

tooling-environment · ✓ 26.07.08e
Array.Clone() blocked by whitelist but dotnet build misses it

System.Array.Clone() compiles clean in dotnet build but fails SB1000 in the editor: the headless build does not enforce the whitelist.

writing-gameplay · ✓ 26.07.08e
Assembly.cs global usings as project bootstrap

global using Sandbox + your razor namespace in Assembly.cs: without it, panels and game types don't resolve across the assembly.

getting-set-up · ✓ 26.07.15a
Attachments and bones read wrong on the spawn frame

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.

rigging-animation · ✓ 26.07.22
Authoring s&box .sound events by hand

MP3 + JSON .sound beside it: no wav/ffmpeg; Distance is in inches; copy schema from addons/menu box_open.sound.

audio · ✓ 26.07.08e
Bind lazily to a component created in OnStart, not from your own OnStart

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.

writing-gameplay · ✓ 26.08.05
Blender OBJ export face order is not deterministic

bpy.ops.wm.obj_export can reorder face lines across runs on the same mesh: diff the manifest, not the raw OBJ bytes.

getting-art-in · ✓ 26.07.08e
Blocking the main thread on a GameTask.RunInThreadAsync result is a permanent deadlock

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.

tooling-environment · ✓ 26.07.22
border-style: solid is a parse error that kills the whole stylesheet

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.

building-ui · ✓ 26.07.15a
box-shadow: inset paints outside the element in Razor panels

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.

building-ui · ✓ 26.07.22
Build an s&box game assembly offline without stomping the live editor

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.

tooling-environment · ✓ 26.08.05
BuildHash() overrides only compile on PanelComponent, not on a plain Component

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.

building-ui · ✓ 26.07.15a
Building a draggable slider with click-to-jump and drag-to-scrub

No native drag helper exists for PanelComponent sliders. Use the engine's SliderControl pattern: MousePanelEvent.LocalPosition over track width, with pointer-events routing.

building-ui · ✓ 26.07.08e
Building an s&box HUD

One ScreenPanel host, static UIState for modals, self-closing panels, toast stack: BuildHash every flag the markup reads.

building-ui · ✓ 26.07.08e
Camera focus target switch causes jerk: smooth the target, not just the follower

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.

writing-gameplay · ✓ 26.07.08e
Character facing derived from velocity flips 180 degrees on every pendulum reversal

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.

tooling-environment · ✓ 26.07.08e
Character stacking: seat at the visual mesh head-top, not the physics capsule height

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.

writing-gameplay · ✓ 26.07.15a
Chase camera using raw fixed-tick position causes model sawtooth jitter

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.

writing-gameplay · ✓ 26.07.15a
Child-combinator universal selector (`.parent > *`) never matches in s&box SCSS

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.

building-ui · ✓ 26.07.15a
Chunked mesh generation is math-bound, not draw-call-bound

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.

making-it-perform · ✓ 26.07.08e
Citizen animgraph combat params are unwrapped and unnetworked

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.

rigging-animation · ✓ 26.07.22
Citizen body aim needs SetLookDirection, not the aim_body floats

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.

rigging-animation · ✓ 26.08.05
Citizen held-item pose map: HoldType, aim, and IK hand targets

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.

rigging-animation · ✓ 26.07.15
Cloud assets fail silently under backend load after publish

Published game boots with error.vmdl placeholders; engine may rewrite prefab refs, no auto-retry; restart editor + republish.

publishing-shipping · ✓ 26.07.08e
Collider choice that actually costs you

BoxCollider is cheap and follows WorldScale; Capsule/ModelCollider don't scale with WorldScale and ModelCollider is costly on clutter.

making-it-perform · ✓ 26.07.08e
Commit a new .shader together with its compiled .shader_c, or it fails its first load

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.

getting-art-in · ✓ 26.07.22
Components.Get misses a SkinnedModelRenderer on a child object

Components.Get<SkinnedModelRenderer>() only searches the same GameObject: a renderer on a child returns null, silently no-oping every Set() call.

writing-gameplay · ✓ 26.07.15a
Compute a follow slot from the leader's heading, not the line between the pair

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.

writing-gameplay · ✓ 26.07.22
Connection.Stats reads zero on a local two-instance session

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.

writing-gameplay · ✓ 26.07.22
CreateLobby is async: IsActive is still false on the same frame

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.

writing-gameplay · ✓ 26.07.08e
Cross-assembly hot-reload throws MissingMethodException despite green compile

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.

tooling-environment · ✓ 26.07.15a
Cross-fade animations WITHOUT an AnimGraph

Set Sequence.Blending = true once: per-clip fade_in/fade_out times in the vmdl shape the blend; no AnimGraph required.

rigging-animation · ✓ 26.07.08e
CSS @keyframes and animation shorthand work in razor SCSS

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.

building-ui · ✓ 26.07.15a
Custom GameResource extension must be 8 characters or fewer

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.

tooling-environment · ✓ 26.07.15a
Decal colour is lit surface albedo: pale tints wash out

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.

writing-gameplay · ✓ 26.07.15a
Decimated heightfield cliffs render as sawtooth teeth: snap the above-gap cluster

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.

writing-gameplay · ✓ 26.07.15a
Decimating AI meshes without wrecking them

Census tris × instances first: silhouette fails before UVs; inject usemtl after scripted OBJ export.

getting-art-in · ✓ 26.07.08e
Dedicated server dies at launch with 'You must install .NET to run this application'

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.

writing-gameplay · ✓ 26.07.08e
Dedicated server with an unpublished package: clients can't join

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).

writing-gameplay · ✓ 26.07.08e
Deep vertical terrain sink defeats lateral eject and mantle: escalate through hard-recover to a top-out

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.

writing-gameplay · ✓ 26.07.08e
Defer a synchronous blocking call a few frames so the loading overlay actually paints

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.

building-ui · ✓ 26.07.15a
Derive procedural character geometry from the collision surface, not the render mesh

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.

writing-gameplay · ✓ 26.07.15a
Dev-host streaming skips loose data files, breaking deterministic sync

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.

writing-gameplay · ✓ 26.07.15a
DirectionalLight.LightColor is a hue control, not a brightness dial

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.

getting-art-in · ✓ 26.07.22
Disabled components vanish from GetAllComponents: hold spawn-time references

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.

writing-gameplay · ✓ 26.07.22
Disabling per-instance shadows on ModelRenderer

ModelRenderer.CastShadows doesn't exist as a settable property: use renderer.SceneObject.Flags.CastShadows instead.

getting-art-in · ✓ 26.07.08e
dotnet build verifies compile but NOT the whitelist

Headless dotnet build is green while the in-editor compiler emits SB1000: Environment/IO/Process/reflection are banned in game code.

tooling-environment · ✓ 26.07.08e
Double jump doesn't work with Jump(): set Velocity.z directly

Jump() helpers clamp against rising velocity, eating the second impulse. Set Velocity.z directly for a reliable double jump.

writing-gameplay · ✓ 26.07.08e
Edit-mode Destroy() is deferred: scene queries return stale objects

GameObject.Destroy() in edit mode is deferred; a query fired right after returns the previous build's objects.

writing-gameplay · ✓ 26.07.08e
Editing .razor safely (shell/emoji mojibake)

Razor HUD emoji and dashes die under Get-Content/Set-Content: edit with byte-safe UTF-8 APIs or a real editor.

tooling-environment · ✓ 26.07.08e
Editor auto-exposure makes screenshot comparisons report false positives

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.

writing-gameplay · ✓ 26.07.08e
Editor compiles the checked-out tree, not a git worktree branch

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.

tooling-environment · ✓ 26.07.15a
Editor play mode is hard-capped at 60 fps: cvars won't lift it

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.

making-it-perform · ✓ 26.07.22
Editor stuck running stale assembly with green compile: only a restart clears it

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.

tooling-environment · ✓ 26.07.08e
Editor vsync hides physics cost: time the step directly

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.

making-it-perform · ✓ 26.07.22
Engine ships built-in McpTool source as readable C#: read it before writing your own

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.

tooling-environment · ✓ 26.07.08e
Every ICameraModifier runs against the drawing camera, not the one it was authored for

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.

writing-gameplay · ✓ 26.08.05
Everything broke at once: check for a stale assembly first

Failed package compile leaves the editor running the last-good hotload: multi-symptom 'regressions' are often stale code.

tooling-environment · ✓ 26.07.08e
FacingYawOffset swaps which local axis is the flip axis vs the cartwheel axis

A front-flip rotation uses _baseRot.Forward (not .Right) when FacingYawOffset is ±90°: the offset swaps which local axis is perpendicular to travel.

tooling-environment · ✓ 26.07.08e
FileSystem is ambiguous in editor assemblies: CS0104 between Editor.FileSystem and Sandbox.FileSystem

An unqualified FileSystem compiles in a game assembly but CS0104s in an editor assembly: fully-qualify Sandbox.FileSystem in editor code.

tooling-environment · ✓ 26.07.08e
First successful Play: what to verify after the skeleton

Folders → sbproj → Assembly.cs → 4-object scene → green dotnet build → tagged logs on Play, then optional art tools.

getting-set-up · ✓ 26.07.08e
First-person hide: use the viewer tag, not RenderType

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.

writing-gameplay · ✓ 26.07.08e
FirstOrDefault() on SkinnedModelRenderer can grab clothing, not the body

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.

writing-gameplay · ✓ 26.07.22
Fixing a source asset doesn't always trigger recompilation

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.

tooling-environment · ✓ 26.07.08e
flex-basis: 0 overrides width and collapses a fixed column in Yoga

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.

building-ui · ✓ 26.07.15a
Flex-grow track with a percentage-width child causes a layout feedback loop

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.

building-ui · ✓ 26.07.08e
Foot-sliding on locomotion: pace clips by their authored stride, not the controller's top speed

Foot-slide happens when PlaybackRate is tied to movement top speed instead of the clip's own authored stride distance.

rigging-animation · ✓ 26.07.08e
For runtime per-surface color, bake a texture: don't rely on complex.shader vertex color

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).

getting-art-in · ✓ 26.07.15a
Forge delivery fails but the preview GLB is still downloadable: recover it

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.

getting-art-in · ✓ 26.07.08e
FP cosmetics need a parallel viewmodel copy, not a re-tagged world child

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.

writing-gameplay · ✓ 26.07.15a
FrameStats and PerformanceStats are accessible from game code: no engine benchmark system needed

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.

making-it-perform · ✓ 26.07.22
Freeze a physics actor by going kinematic, not by destroying its Rigidbody

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.

writing-gameplay · ✓ 26.07.22
FromHost field on a runtime singleton does not replicate without NetworkSpawn

A [Sync(SyncFlags.FromHost)] field on a runtime-created singleton never replicates: the object needs NetworkSpawn, not just NetworkMode.Snapshot.

writing-gameplay · ✓ 26.07.08e
GameObject.Destroy keeps rendering in edit mode: deferred queue not processed between regenerations

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.

writing-gameplay · ✓ 26.07.08e
GameObject.Destroy() is deferred: a destroyed object still holds its exclusive claims for the rest of the frame

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.

writing-gameplay · ✓ 26.07.22
Gamepad triggers have a public analog read: Input.GetAnalog works

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.

writing-gameplay · ✓ 26.07.08e
Gate the exact lobby you connect to, not query result [0]

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).

writing-gameplay · ✓ 26.07.15a
Geometry under an IsStatic root samples its lighting once, at creation

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.

getting-art-in · ✓ 26.07.22
Getting set up: new project skeleton

.sbproj + Assets/Code/ProjectSettings/tools layout, 4-object scene + Bootstrap, dotnet build before anything else.

getting-set-up · ✓ 26.07.08e
Git worktree at different depth breaks sbox csproj relative references

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.

tooling-environment · ✓ 26.07.15a
Glyph corruption (text renders as solid blocks) is also text-count dependent

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.

building-ui · ✓ 26.07.08e
Greedy voxel mesher produces vertical stripes on cliff faces instead of horizontal strata

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.

writing-gameplay · ✓ 26.07.08e
Green compile_status coexists with a stale play-mode hotload reporting phantom errors

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.

tooling-environment · ✓ 26.07.08e
Ground overlays z-fight each other, and a full-lap overlay z-fights itself

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.

writing-gameplay · ✓ 26.07.22
Ground snap pops on rolling slopes: rate-limit the downward snap

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.

writing-gameplay · ✓ 26.07.08e
Grounded wish-speed servo silently destroys applied velocity

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.

writing-gameplay · ✓ 26.07.15a
Hand-rolled visual smoother fights engine FixedUpdateInterpolation: 50 Hz model flicker

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.

writing-gameplay · ✓ 26.07.08e
Hand-vendored library without an .sbproj is silently skipped

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.

tooling-environment · ✓ 26.07.15a
Headless dotnet build misses Razor compile errors

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.

tooling-environment · ✓ 26.07.08e
Headless dotnet build skips sandbox whitelist enforcement

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.

tooling-environment · ✓ 26.07.15a
Heavy work without frame hitches

GameTask.RunInThreadAsync for parse/math; main thread only for engine objects; Yield every N items for loading UI.

writing-gameplay · ✓ 26.07.08e
High-key chalky sky is capped by two defaults: texture AND tonemapping must both change

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.

getting-art-in · ✓ 26.07.08e
How we built a playable s&box game in a day with AI agents

Top model plans and reviews; cheaper agents execute on disjoint files; telemetry-driven feel tuning: whitelist and stale-assembly traps included.

ai-assisted-workflow · ✓ 26.07.08e
Idempotent world rebuild needs DestroyImmediate, not Destroy

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.

writing-gameplay · ✓ 26.07.15a
import_rotation fixes the render mesh and leaves PhysicsHullFile collision unrotated

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.

getting-art-in · ✓ 26.08.05
Importing Kenney / CC0 kits into s&box

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.

getting-art-in · ✓ 26.07.08e
Input.config action on an editor-reserved key silently never fires in Play

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.

writing-gameplay · ✓ 26.07.08e
Input.config and AnalogMove for a new game

WASD as Forward/Backward/Left/Right feeds AnalogMove; new Input.config actions need an editor restart: dotnet build is not enough.

getting-set-up · ✓ 26.07.08e
Input.Keyboard.Pressed refires on OS key auto-repeat: toggles flip twice

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).

writing-gameplay · ✓ 26.08.05
Input.Pressed edges drop or double-fire inside OnFixedUpdate

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.

writing-gameplay · ✓ 26.07.15a
Inside one panel tree, z-index paints the popup but does not order the click

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.

building-ui · ✓ 26.08.05
It worked in the editor but broke after publishing

Whitelist divergence, loose Resource Files, and silent cloud-asset failures after publish.

publishing-shipping · ✓ 26.07.08e
Joining client's singleton claim grabs the host's character

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.

writing-gameplay · ✓ 26.07.15a
Joining client's static state wiped by networked scene handoff

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.

writing-gameplay · ✓ 26.07.08e
Keep PackageReferences clean from day one

Standalone export hangs if PackageReferences still need sbox.game to resolve: don't accumulate cloud package deps casually.

getting-set-up · ✓ 26.07.08e
Keep quaternion keys hemisphere-continuous

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.

rigging-animation · ✓ 26.07.08e
Kinematic movement that doesn't get stuck

Always handle tr.StartedSolid: ignore that frame so an overlapped body can walk free; slide-trace the wish onto the hit plane.

writing-gameplay · ✓ 26.07.08e
Library extraction seam must cover every side effect

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.

tooling-environment · ✓ 26.07.18
Library host project fails to compile library-mounted scenes

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.

tooling-environment · ✓ 26.07.15a
Local two-peer multiplayer testing with -joinlocal

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.

writing-gameplay · ✓ 26.07.22
Loose resource files don't auto-publish

PNG/WAV/MP3/JSON must be listed in Project Settings → Resource Files without an assets/ prefix: #1 editor-vs-publish break.

publishing-shipping · ✓ 26.07.08e
Lowering sea level doesn't drain interior lakes: depression lakes are perched

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.

writing-gameplay · ✓ 26.07.08e
Make a Sandbox.Decal follow an animated character by re-pinning it to a bone each frame

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.

writing-gameplay · ✓ 26.07.18
Minimal scene: Sun, Skybox, Camera, Bootstrap

Scene holds four GameObjects; Bootstrap OnStart builds the world in code: hotloads better, no scene/code drift.

getting-set-up · ✓ 26.07.08e
Model.Load of a missing vmdl returns the error model, not null

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.

tooling-environment · ✓ 26.07.22
ModelRenderer.Tint above 1.0 wraps a byte and renders dark, not brighter

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.

getting-art-in · ✓ 26.08.05
ModelRenderer.Tint on flat-color vmats causes purple/black corruption

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.

writing-gameplay · ✓ 26.07.08e
Mouse-look camera reads zero from Input.AnalogLook unless cursor is locked

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.

writing-gameplay · ✓ 26.07.08e
Moving legacy assets with git mv leaves compiled files behind and misses shared textures

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.

tooling-environment · ✓ 26.07.08e
My custom sound event won't play

Play full path WITH .sound or bare filename only: partial paths like impact/boing never resolve; compiled assets can still be invisible mid-session.

audio · ✓ 26.07.22
My interface scan returns nothing at runtime

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.

writing-gameplay · ✓ 26.07.22
My model has no collision even though it loads fine

RenderMeshFile alone compiles clean with zero physics: ModelCollider needs PhysicsMeshFile/PhysicsHullFile in the vmdl.

getting-art-in · ✓ 26.07.08e
My model imported upside down / sideways / facing the wrong way

Blender +X becomes world −Y after OBJ import; yaw +90° faces +X, and Blender +Y rotation tips the +X edge down.

getting-art-in · ✓ 26.07.08e
My s&box UI won't update / is frozen

BuildHash() is the only re-render trigger: hash everything the markup reads, including collection contents and flags.

building-ui · ✓ 26.07.08e
My scaled-up tree's collider didn't scale

CapsuleCollider and ModelCollider ignore WorldScale; BoxCollider follows it. Bake scale into import_scale instead.

getting-art-in · ✓ 26.07.08e
Naming a property 'Active' shadows Component.Active

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.

writing-gameplay · ✓ 26.07.08e
Navmesh openings erode by whole cells against agent radius

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.

writing-gameplay · ✓ 26.08.05
Networking API facts to check against the installed build before you compile

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.

writing-gameplay · ✓ 26.07.22
New .razor.scss files are not applied until the editor restarts

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.

writing-gameplay · ✓ 26.07.08e
Noclip in a trace-based kinematic controller is a state, not a collider toggle

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.

writing-gameplay · ✓ 26.07.08e
NPC steer loop freezes forever against a wall

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.

writing-gameplay · ✓ 26.07.15a
Null check on a destroyed GameObject still NREs: use IsValid()

A cached Component/GameObject reference guarded with == null still throws NullReferenceException after the object is destroyed: only IsValid() catches destroyed objects.

writing-gameplay · ✓ 26.07.08e
Offline two-assembly compile gate with prebuilt base library

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.

tooling-environment · ✓ 26.07.18
OnDisabled nulls a singleton, blocking re-adoption forever

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.

writing-gameplay · ✓ 26.07.15a
One vmdl, many tagged collision hulls

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.

getting-art-in · ✓ 26.08.05
Orient a flat decal box to the hit normal

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.

writing-gameplay · ✓ 26.07.08e
Owner-only simulation field reads frozen state on network proxies

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.

writing-gameplay · ✓ 26.07.08e
Owner-simulated networking

[Sync] owner→proxies, IsProxy early-out; FromHost for shared truth. Every object carrying a [Sync] field has to be NetworkSpawned, singletons included.

writing-gameplay · ✓ 26.07.08e
Pace citizen locomotion clips by each clip's own blend-value speed

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.

rigging-animation · ✓ 26.07.22
PanelComponent uses OnTreeBuilt, not OnAfterTreeRender

OnAfterTreeRender(bool) is a Panel hook: on a PanelComponent it fails with CS0115; use parameterless OnTreeBuilt() or OnTreeFirstBuilt().

building-ui · ✓ 26.07.08e
Per-cell white noise hash gives salt-and-pepper terrain instead of organic shade patches

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.

writing-gameplay · ✓ 26.07.08e
Per-shape collision_tags in a vmdl are inert at runtime on a ModelCollider

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.

getting-art-in · ✓ 26.07.15a
Pick org and ident early for sbox.game

Ident is org.package: two lowercase segments; keep Org local until real; never put TODO placeholders in Org or the editor won't boot.

getting-set-up · ✓ 26.07.08e
Projected decals conform to runtime model renderers

A Sandbox.Decal projects onto runtime-built chunk meshes (ModelRenderers) and conforms to stepped/curved faces, confirmed live on voxel terrain.

writing-gameplay · ✓ 26.07.18
Prune a waypoint graph by connected component, not by isolated nodes

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.

writing-gameplay · ✓ 26.07.22
Published-build client join reloads the assembly, wiping all statics

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.

writing-gameplay · ✓ 26.07.08e
Push-to-talk silently dead: Voice action missing from Input.config

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.

audio · ✓ 26.07.15a
QueryLobbies never finds your Hidden lobby

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.

writing-gameplay · ✓ 26.07.15
Quit-to-menu teardown runs inside DisconnectScope: networking is still active

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.

writing-gameplay · ✓ 26.07.15a
radial-gradient with a CSS shape keyword errors as a color and drops the rule

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.

building-ui · ✓ 26.07.15a
Ragdoll a scripted-rig NPC with pure engine physics

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.

rigging-animation · ✓ 26.08.05
Razor panel mounted before a sync call never paints: budget frames, not ticks

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.

building-ui · ✓ 26.07.08e
Razor RenderFragment flex rows with gap collapse on top of each other

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.

building-ui · ✓ 26.07.08e
Razor tag resolution ignores global usings

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.

building-ui · ✓ 26.07.18
Read collision direction from the impulse, not the struck object's velocity

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.

writing-gameplay · ✓ 26.07.22
Rebuilding a multi-material model loses submesh materials

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.

writing-gameplay · ✓ 26.07.15a
Render a player's Steam avatar with the avatar: texture-URL scheme

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.

building-ui · ✓ 26.07.15a
RenderExcludeTags on a tagged parent culls all child renderers too

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.

writing-gameplay · ✓ 26.07.15a
Resolve identity by registry, not by walking the tag chain

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.

writing-gameplay · ✓ 26.07.22
Retargeting free Mixamo mocap onto a custom rig

Transfer rest-delta rotations parent-relative (not world): avoid the forward-hunch bug and never transform_apply scale on Mixamo armatures.

rigging-animation · ✓ 26.07.08e
Rigging an AI-generated (rigless) character mesh

Bone-heat auto-weights fail on AI meshes. Use scripted geodesic (along-surface) weights, then FBX + animated vmdl.

rigging-animation · ✓ 26.07.08e
Rigidbody component API

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.

writing-gameplay · ✓ 26.08.05
Roboto Mono is the engine's monospace font

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.

building-ui · ✓ 26.07.08e
Rotation.FromYaw is counter-clockwise

Rotation.FromYaw(+angle) is a LEFT (CCW) turn. Get the sign right or steering, AI, and autopilot spiral the wrong way.

writing-gameplay · ✓ 26.07.08e
Rpc.Broadcast on a non-networked GameObject runs locally only -- no warning

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.

writing-gameplay · ✓ 26.07.08e
Runtime textures for UI panels must be assigned from C#

SCSS background-image only resolves asset paths. Runtime Texture objects must be assigned via Panel.Style.BackgroundImage in OnTreeBuilt.

building-ui · ✓ 26.07.08e
Runtime world-building helpers

FlatBox/Prop/Deco/Wire helpers plus Obstacle records as plain data beat physics queries for build validity.

writing-gameplay · ✓ 26.07.08e
RZ1010 error from nested @{ } inside a Razor code block

Nesting @{ } inside an already-open Razor code block (like @if or @for) causes RZ1010: you're already in C#, so drop the @.

building-ui · ✓ 26.07.08e
s&box component lifecycle in practice

OnAwake runs synchronously inside Components.Create: set singletons there; derive from [Property] in OnStart after spawn helpers assign.

writing-gameplay · ✓ 26.07.08e
s&box composites UI alpha in linear space, so low-alpha whites render too light

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.

building-ui · ✓ 26.07.22
s&box has no project-authorable mixer bus system

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.

audio · ✓ 26.07.22
s&box project folder layout

Assets / Code / Editor / ProjectSettings / tools: the template every project follows.

getting-set-up · ✓ 26.07.08e
s&box ships a headless dedicated server that can run an unpublished local project

App 1892930 via SteamCMD runs a headless server with +game pointing at a local .sbproj: clients stream code/assets, no sbox.game publish required.

tooling-environment · ✓ 26.07.08e
s&box units are inches

1 m = 39.37 engine units: design in SI, convert once at the engine boundary, and audit every consumer.

getting-art-in · ✓ 26.07.08e
s&box won't load my OBJ/GLB

Scenes never load raw OBJ/GLB: always wrap with a .vmdl and remap materials under both bare and .vmat names.

getting-art-in · ✓ 26.07.08e
Sandbox.Decal renders differently on each peer due to random self-seed

Sandbox.Decal self-seeds with Random.Shared.Int(10000) on enable: a decal spawned identically on two peers renders differently by default.

writing-gameplay · ✓ 26.07.15a
Sandbox.Decal scales to thousands: the bound is fill rate, not a hard cap

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.

writing-gameplay · ✓ 26.07.18
Sandbox.Json.Serialize always writes indented JSON

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.

building-ui · ✓ 26.07.22
Save/load without drift

DTOs + one spawn path + deterministic static world: guard restored defaults; keep enums append-only.

writing-gameplay · ✓ 26.07.08e
Scaffolded project missing global using System in Assembly.cs

A freshly-scaffolded project's Assembly.cs can be missing global using System. Transplanted code using Math/MathF fails with CS0103.

building-ui · ✓ 26.07.08e
Scene.GetAllComponents skips disabled components

A component with Enabled = false is invisible to GetAllComponents: search returns null even though the component exists.

writing-gameplay · ✓ 26.07.08e
ScenePanel Camera is read-only: configure it in place for 3D previews

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.

building-ui · ✓ 26.07.08e
SceneTrace sphere sweep EndPosition is the sphere centre, not the feet

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.

writing-gameplay · ✓ 26.07.22
ScreenPanel.ZIndex defaults to 100, and tied roots have no paint order

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.

building-ui · ✓ 26.07.22
ScreenPanel.ZIndex orders paint only: pointer input falls through

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.

building-ui · ✓ 26.07.22
Sequence-only rig: land hands on a moved prop by reseating the visual, not IK

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.

rigging-animation · ✓ 26.07.08e
Set UseAnimGraph = false before writing Sequence.Name, or the write no-ops

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.

rigging-animation · ✓ 26.07.22
Setting a [ConVar] to the value it already holds does nothing

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.

tooling-environment · ✓ 26.07.22
Single-tick ground-check flicker machine-guns the landing squash

A trace-based ground controller flickers Ground/Air on seams, re-firing landing VFX mid-run. Require minimum air time before a JustLanded counts.

writing-gameplay · ✓ 26.07.08e
SkinnedModelRenderer.SceneObject is null until the renderer goes live, so a spawn-time CastShadows write no-ops

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.

writing-gameplay · ✓ 26.07.22
SliderControl near-min values render scientific notation in CSS style

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.

building-ui · ✓ 26.07.15a
Smooth render mesh over quantized collision creates invisible curbs

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.

writing-gameplay · ✓ 26.07.15a
Sound.Play() is fully static: no component wiring needed

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.

audio · ✓ 26.07.08e
Spawning a joiner's character clobbers the host's camera target

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.

writing-gameplay · ✓ 26.07.08e
Stalled Steam update half-deletes the s&box install

If sbox-launcher.exe stays open during a Steam update, files vanish mid-install. Validate via steam://validate/590830.

tooling-environment · ✓ 26.07.08e
Standalone Steam export

Preview as of 2026-07: Valve approval + Facepunch license; full .NET, lose platform services; clean PackageReferences or startup hangs.

publishing-shipping · ✓ 26.07.08e
Static registry persists across editor Play restarts: gate on live objects

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.

tooling-environment · ✓ 26.07.22
Static registry populated by a static constructor doesn't pick up new entries on hotload

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.

tooling-environment · ✓ 26.07.08e
Steam lobby metadata survives host game switch

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.

writing-gameplay · ✓ 26.07.15a
Structural Razor edit hotload exception silently deregisters project tools

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.

tooling-environment · ✓ 26.07.08e
Swept trace: HitPosition is the surface, EndPosition is the shape centre

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.

writing-gameplay · ✓ 26.07.15a
TextEntry is the house control, not HTML input

Use TextEntry with onsubmit and OnTextEdited: standard Blazor input bindings compile but are not how the engine UI works.

building-ui · ✓ 26.07.08e
TextEntry.OnTextEdited needs an explicit-type block lambda

An untyped or expression-bodied lambda on TextEntry.OnTextEdited fails with CS8917 or CS0029. Use an explicit param type plus a block body.

writing-gameplay · ✓ 26.07.15a
The bone-name `.` → `_` compiler trap

Model compiler rewrites upper_arm.L → upper_arm_L; physics KV3 that still says .L makes limb bodies unknown while the torso works.

rigging-animation · ✓ 26.07.08e
The Citizen ragdoll has 18 bodies and 16 joints, countable offline

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.

rigging-animation · ✓ 26.07.22
The editor MCP port is one global setting: bump it by hand, let your agent discover it

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.

tooling-environment · ✓ 26.07.15a
The engine ships render quality profiles that cap your scene, and post-processing is opt-in per camera

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.

getting-art-in · ✓ 26.07.22
The FBX export recipe that actually works

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.

rigging-animation · ✓ 26.07.08e
The mip chain erases texture detail finer than the object it represents

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.

getting-art-in · ✓ 26.08.05
The official s&box docs are machine-readable via llms.txt and .md URLs

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.

tooling-environment · ✓ 26.07.15a
The P2P join handshake has a fixed ~3-second connect budget

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.

writing-gameplay · ✓ 26.07.15a
The Razor @namespace trap

Razor classes get a RootNamespace/folder-derived namespace: declare @namespace and global using or C# can't find your panels.

building-ui · ✓ 26.07.08e
The repeating "error texture" / default_mask console flood is base-menu content, not your project

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.

tooling-environment · ✓ 26.07.22
The singleton pattern that removes reference-wiring

static Instance set in OnAwake, cleared in OnDestroy: everything reads Foo.Instance with null-guards, no inspector wiring.

writing-gameplay · ✓ 26.07.08e
The stock PlayerController has no public speed property: you can't scale move speed from outside

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.

tooling-environment · ✓ 26.07.15a
There is no scene/global time-scale API: slow-mo has no seam to set

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.

tooling-environment · ✓ 26.07.15a
There's no Looping field on SoundEvent

SoundEvent has no Looping property: loop via compiled vsnd import options, or re-trigger from code when SoundHandle finishes.

audio · ✓ 26.07.08e
Three ways Razor text is in the DOM but invisible on screen

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.

building-ui · ✓ 26.07.08e
Time-of-day sky swap pops: use a weighted-blend shader instead

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.

getting-art-in · ✓ 26.07.15a
Title / Ident / StartupScene fields that bite new projects

StartupScene is what Play loads; Org must be a valid lowercase ident. Placeholders break editor bootstrap, not just publishing.

getting-set-up · ✓ 26.07.08e
Too many font-size declarations (or too much text) corrupt UI glyph rendering

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.

building-ui · ✓ 26.07.08e
Trace-based kinematic controllers don't fire trigger volumes

A trace-based kinematic character controller has no collider component, so trigger volumes and ITriggerListener never fire against it. Use distance polling instead.

writing-gameplay · ✓ 26.07.08e
Trace-based kinematic controllers don't fire triggers

A hand-integrated trace mover has no collider component: ITriggerListener and OnTriggerEnter never fire. Use distance-polling instead.

writing-gameplay · ✓ 26.07.08e
Trajectory preview dots bunch at the apex: sample by arc length, not time

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.

getting-art-in · ✓ 26.07.08e
transition-delay, :intro and :outro parse cleanly in razor-scss

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.

building-ui · ✓ 26.07.22
Unclean host exit poisons the Steam P2P transport between two peers

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.

writing-gameplay · ✓ 26.07.15a
Undefined SCSS variable silently kills panels at runtime

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.

building-ui · ✓ 26.07.22
Understanding the Play Fund

No paid storefront: revenue is clamped player-hours from a daily pool; retention is the monetization feature.

publishing-shipping · ✓ 26.07.08e
Unknown shader field? Check the engine's own templates before grepping projects

Shader field support is unknown and no .shader source exists: check the install's templates/ folder for authoritative syntax instead of grepping sibling projects.

getting-art-in · ✓ 26.07.08e
Using AI-generated 3D models in a real s&box game

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.

getting-art-in · ✓ 26.07.08e
Vector3.Right is (0, -1, 0), not +X

Source engine convention: Forward = +X, Left = +Y, Right = -Y. Using Vector3.Right for '+X' silently slides geometry the wrong way.

getting-art-in · ✓ 26.07.08e
Visible cursor blocks game mouse input: no raw bypass exists

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.

writing-gameplay · ✓ 26.07.22
What hotload does (and doesn't) for a new project

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.

getting-set-up · ✓ 26.07.08e
Whitespace next to a Razor tag or expression boundary collapses to nothing

Literal spaces adjacent to a tag or @-expression boundary vanish in Razor markup: use a single interpolated string or CSS margin instead.

writing-gameplay · ✓ 26.07.08e
Why SetBoneTransform / SetIk silently do nothing

SetIk is AnimGraph-gated; SetBoneTransform is unsound on clip-keyed bones. Use proxy props, whole-visual motion, or commit to AnimGraph.

rigging-animation · ✓ 26.08.05
Windows SSH-launched server process dies when the SSH session closes

A long-running process started over a Windows OpenSSH session is killed the moment the session closes -- use a Scheduled Task instead.

tooling-environment · ✓ 26.07.08e
Windows/PowerShell traps that corrupt s&box source

Get-Content/Set-Content re-encodes BOM-less UTF-8 as ANSI; CRLF files break \n-only search-replace: use byte-safe APIs.

tooling-environment · ✓ 26.07.08e
Wiring Sandbox.Services

Stats.Increment/SetValue, Leaderboards.GetFromStat, Achievements.Unlock: cheap platform polish; total achievement score capped at 1000.

publishing-shipping · ✓ 26.07.08e
Writing focus from onmouseover rebuilds the panel and swallows the click

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.

building-ui · ✓ 26.07.22
Zero-radius Scene.Trace.Ray slips through coarse voxel ModelColliders

A zero-radius Scene.Trace.Ray passes straight through coarse voxel ModelColliders and returns Hit=false. Sweep a thin sphere (.Radius(...)) and it hits.

writing-gameplay · ✓ 26.07.15a

Want to know when new guides or fixes drop? Join the community to help build this out. Report gotchas, flag outdated fixes, or just lurk.

Join the Discord