Skip to main content

Build and Runtime Troubleshooting

Use this page when the editor validates incorrectly, the PS1 build fails, or the runtime reports a load error.

Fast Triage​

  1. Run Build > Validate Project.
  2. Open Problems and fix hard errors first.
  3. Open Build > Tools & Diagnostics > Show PS1 Budget and inspect hard limits.
  4. Check Build/ps1/logs/ after a failed build.
  5. Inspect Build/ps1/disc_root/DATA/MANIFEST.JSN when a runtime asset cannot load.
  6. Test the generated .cue from Build/ps1/package/.

Common Build Issues​

SymptomLikely causeFix
Missing runtime compiler toolsPrivate/source build selected without its toolchainUse the installed binary runtime or open Build > Tools & Diagnostics > Tool Paths...
Missing Ninja pathPrivate/source runtime build selected without its build runnerConfigure Ninja for that source build; binary releases use the bundled runtime
Missing mkpsxiso pathTool path not configuredSet mkpsxiso executable path
Build & Run failsDuckStation path missing or invalidConfigure DuckStation path
Sticks do not move the player or cameraAnalog mode is off or the emulator has no Port 1 stick mappingConfigure Port 1 as Analog Controller / DualShock and enable Automatically Enable Analog Mode, or press the mapped Analog/Guide button. Last Exit also supports the D-Pad and L1/R1/L2/R2 in digital mode.
Camera or player moves without touching the sticks on a physical PS1Resting stick values exceed the configured dead zone; an emulator may return a more precise centerStart with PlayerInput > Dead Zone = 0.35. In Last Exit, set the player LuaBehaviour's deadZone to 0.35. Rebuild the game; updating the editor alone does not change an existing project or disc. See Input.
Startup scene missingBuild Settings points to a missing sceneOpen Build > Build Settings...
Scene load fails at runtimeScene not included in Scenes In BuildAdd the scene to Build Settings
Repackage Disc (Reuse Runtime) failsNo available runtime or stale staged filesRun full Build Disc Image (.bin + .cue)
Model import reports collapses at PS1 vertex precisionSmall details lose their area during PS1 coordinate conversionRecenter or split the source mesh, simplify very thin details, and reimport. See Model Import.
Texture import reports invalid image sizeThe source image is invalid or too large to decode safelyResize or re-export the original image in a supported format, then use Apply & Import.
Needs optimization or a tight main RAM marginA PS1 production target is close to its limit; this is separate from your PC's memoryOpen PS1 Budget from the warning. Check the exact free bytes, reduce resident mesh/animation data or split the scene, then rebuild. See Understanding warnings in Problems.

Runtime Load Errors​

failed to load MANIFEST.JSN​

Check:

  • Build/ps1/disc_root/DATA/MANIFEST.JSN exists,
  • packaging completed successfully,
  • the .cue points to the expected .bin,
  • the runtime is launched from the latest build output.

Missing script or script load error​

Check:

  • the Lua Behaviour Script field points to an existing .lua file,
  • the script is under the project and staged into compact runtime folder DATA/L,
  • the script does not exceed the configured size limit,
  • the target callback function exists if a UI button or Interactable calls it.

Missing mesh, texture, material, or audio​

Check:

  • the asset exists in Library/asset_db.json,
  • the source asset still exists under Assets/,
  • the imported output exists under Library/,
  • the staged file exists under the compact Build/ps1/disc_root/DATA runtime folders (S, L, M, R, T, A, or X),
  • Validate Project does not report missing GUIDs or files.

Streaming music does not play​

Check:

  • the source WAV has Streaming Music (CD-XA) enabled,
  • no more than 8 streaming tracks are enabled,
  • Build/ps1/disc_root/DATA/X/ contains the encoded track,
  • the name passed to Music.Play() matches the WAV filename stem; comparison is case-insensitive,
  • the script checks the boolean returned by Music.Play().

Gameplay Issues​

SymptomCheck
Player walks through an objectObject has Collider, Collider is not trigger, Level Builder placement created collider
Trigger does not fireCollider exists, Is Trigger is enabled, and the Lua Behaviour defines OnTriggerEnter
Interact does nothingPlayer has Interaction Ray, target has Interactable, and the configured function name matches exactly
UI button does nothingButton On Click target GameObject/function is set and the Lua Behaviour defines that function
SceneManager.LoadScene() does nothingTarget scene path is correct and included in Build Settings
Audio sounds distorted on PS1 but clean in Play ModeRebuild with the current editor so older WAV imports are regenerated. If needed, select the source WAV and use Reimport, then build a new disc image. Also check Audio Source Volume or Music.SetVolume and avoid clipping in the source WAV.
Audio does not playGameObject has Audio Source, clip GUID exists, and the resident clip fits the SPU budget
Music does not playStreaming flag is enabled, track is staged in DATA/X, and Music.Play() uses the source filename stem
Save fails in DuckStationEnable a writable Memory Card in Slot 1 with one free block; read SaveData.GetLastError() immediately after failure and retry. Wait for card access to finish; CD-XA music pauses and restarts during the operation.
Save/load does not persistUse PlayerPrefs.Save() for typed preferences or SaveData.Flush() for raw values; use SaveData.Reload() before expecting fresh device data
Game uses the wrong refresh rateSelect NTSC or PAL under Project Settings, save, then run a full Release build instead of Repackage Disc (Reuse Runtime)
Progress Bar does not changeResolve it with UI.Find(), then check the boolean returned by ProgressBar.SetValue()
Navigation destination returns falseGameObject has an enabled root NavMesh Agent, referenced surface exists, preview bake has a connected path on that surface, and the complete route fits within 32 points
Agent crosses a dynamic obstacleRuntime navigation has no dynamic avoidance; use authored colliders in the bake or stop/replan from script
Portal room disappearsRenderer Room assignment, camera inside expected Room, Portal enabled/open and direction/two-sided state, non-zero opening size, and valid Portal transform
Timeline.Play() returns falseClip name matches exactly and the clip exists in the active scene
Native player still moves in a cutsceneEnable Disable Player Controls on the clip; custom Lua movement must be gated separately
Rumble is unavailableUse Rumble.IsSupported(); verify an analog/DualShock pad, DuckStation vibration mapping, and that the active BIOS handler supports the fail-closed optional output patch

Rendering and Performance Issues​

SymptomCheck
Faces disappear or fold when the camera turnsRebuild with the current runtime and compare the same view in Game preview and the packaged CUE. Check source winding, duplicate/intersecting faces, camera collision and near-plane placement; do not flip UVs or make every material double-sided. See Model Import.
Polygons overlap incorrectlyCheck coplanar duplicates, embedded decorations and transparent surfaces. Automatic boundary ordering and subdivision reduce artifacts but do not supply a depth buffer. See Rendering and Level Authoring.
Walls look coarse while small props look detailedCompare imported dimensions and atlas space per surface. Correct UV proportions and texel density in the source model; increasing palette size alone adds no pixels. See Texture Import.
Scene is slowTriangle count, packet estimate, texture count, audio clips, active scripts
UI draws over world unexpectedlyUI element sort/order and foreground OT reservation
Transparent object sorts badlyKeep transparent surfaces small and isolated
VRAM packing conflictOpen VRAM Inspector, select the red region, reveal the texture, then change format/size and reimport
Mesh colors are missingImported mesh contains vertex colors and Mesh Renderer uses Mesh Vertex Colors
GTE lighting is flatMesh contains usable normals, scene lighting is active, and Mesh Renderer uses GTE Vertex Lighting
Distance fog band looks coarseIncrease geometry subdivision where a large triangle spans much of the fog range; PS1 fog is interpolated from per-vertex factors, not evaluated per pixel

Low frame rate in DuckStation​

  1. After updating the engine, run Build Disc Image (.bin + .cue) and open the newly generated .cue. Repackage Disc (Reuse Runtime) can reuse a previously staged runtime; it does not replace a full rebuild.
  2. Check DuckStation's Game counter. Video: 60 FPS (100%) describes NTSC output and emulation speed, not 60 game updates per second. Measure with CPU overclock disabled and normal emulation speed; enhancements such as PGXP do not establish original-hardware performance.
  3. Hold L1 + R1 and tap Select to show the runtime overlay. Its frame value counts VSync intervals per game frame: at nominal NTSC 60 Hz, 1 interval is about 60 FPS, 2 about 30 FPS, and 3 about 20 FPS. At PAL 50 Hz, the same intervals mean about 50, 25, and 16.7 FPS. The slow counter counts frames taking more than one interval; it is not an error count or a configurable 30 FPS target.
  4. Compare several views while moving through the level. If render time dominates, reduce simultaneously visible geometry, excessive subdivision, overlapping transparent surfaces, and distant detail. Use Rooms, Portals, and Navigation to organize interiors. If physics time dominates, simplify collision shapes and remove unnecessary overlapping Colliders. If Lua time dominates, avoid repeated scene searches and rebuilding strings or tables every frame; refresh HUD text only when its value changes.
  5. Rebuild and repeat the same route after each change. Check packet drops, allocation failures, and Lua errors as well as frame timing. Test loading and scene transitions separately from steady gameplay, then test with the overlay hidden too.

PS1 Ready and the documented triangle limits are budget checks, not a frame-rate guarantee. A larger level needs its own measurements; neither a small demo's result nor Play Mode performance predicts every game's speed. See PS1 Budget Dashboard for the counters and reports.

UI, loading and event audio​

SymptomWhat to check
Item image overlaps storage rowsCheck authored Enabled, parents, Canvas visibility and layout mode. Start an inspection preview disabled and enable it only in the intended view; changing text does not hide images.
UI image stays black or is missing on PS1Check the texture GUID, import output and scene dependency. A filename passed to Image.SetTexture is not a GUID. Reference dynamic choices in authored UI so the build loads them, including hidden elements.
Reticle has a solid rectangle behind itUse transparent source pixels and Mask1Bit import; check whether a separate Panel supplies the background.
Dialogue stops revealing text or clips a sentenceCheck Visible Characters, the 127-byte label limit, bitmap glyph coverage and rectangle size. Use the complete line for layout and change only its reveal count.
UI animation stops during pauseEnable the clip's Unscaled Time setting or use Time.UnscaledDeltaTime for a Lua presentation timer. Keep its Canvas enabled until the exit finishes.
Sound cannot be stopped, or IsPlaying is false while it is audibleIndependent PlayOneShot voices are not tracked by that Audio Source. Use Play/Stop for door creaks and other sounds owned by an action. See AudioSource.
Navigation or footsteps repeat too rapidlyTrigger from selection changes or actual movement, not a held condition every frame. Check each playback result; overlapping one-shots can run out of voices.
Loading image appears after the first frame, or percent restartsArt/font must be read before use, and progress describes the current read. Black presentation intentionally hides the regular UI. See Loading settings.
Reinstalling still opens an older demoUpdate the editable example copy or create a fresh one; engine installation does not replace user projects. Rebuild and open its new CUE. See Updating the example.

What to Save When Reporting a Bug​

Include:

  • project name and active scene,
  • exact build command,
  • Problems panel output,
  • Console build/runtime logs,
  • Build/ps1/logs/ps1_budget_current_scene.json,
  • Build/ps1/logs/build_summary.json,
  • relevant script file,
  • screenshot or short video of the runtime issue,
  • whether the issue happens in editor Play Mode, DuckStation, or hardware.

Script, memory, and loading problems​

SymptomWhat to try
Lua instruction budget exceededCheck for unbounded loops and shorten callbacks or spread work across frames. Review Project > Project Settings... > Scripting > Lua VM Instructions / Callback. Raising Lua Heap (KB) does not fix an instruction limit. Reproduce the error in Play Mode for source-line diagnostics; normal PS1 exports use Release and strip that information.
not enough memory or Lua heap exhaustedLua has exhausted its configured memory pool. Check Project > Project Settings... > Scripting > Lua Heap (KB). For an older First Person Example still set to 64, use its updated 104 KiB preset, then Save, restart Play Mode and rebuild the disc for DuckStation. See the memory guidance below.
Script exceeds max script sizeCheck Max Script Size (KB) in the same settings section. This is a per-file limit, separate from the shared Lua heap. Reduce or split an oversized script; the engine cap is 64 KiB per file.
RAM budget exceeded after an updateBuild again to refresh the report, then reduce scene or asset size using the Budget Dashboard. Check scene transitions as well as individual scenes.
Music restarts after loadingXA playback resumes from the beginning of the track. Plan transitions with that behavior in mind.
Diagnostic text disappearsCheck packet-drop counters in the runtime overlay and reduce geometry or UI load.
Saving or loading failsOpen Save Data Simulator, check the selected failure mode, and inspect SaveData.GetLastError(). Show a failure message and a retry option in your game.

Adjusting Lua memory​

PlayStation has 2 MiB of main RAM for the entire game: executable code, scene data, meshes, loading buffers and Lua all share it. This is not a 2 MiB allowance for scripts. VRAM and sound RAM are separate pools.

Lua Heap (KB) reserves memory for the Lua VM, its libraries and all active scripts, including their tables, strings and temporary allocations. It is shared across scripts, not assigned to each one. The editor uses KB for units of 1,024 bytes (KiB). On 64-bit Windows, Play Mode reserves twice the configured physical heap to accommodate larger pointers and allocation headers. This preview allowance does not change the exported PS1 budget, and Play Mode memory figures are not console measurements.

  1. Stop Play Mode and open Project > Project Settings....
  2. Under Scripting, check Lua Heap (KB). The supported range is 64–512 KiB. Keep the budget supplied with your example: First Person Example uses 104 KiB. Other projects may need a different value; increasing it also reduces the RAM available to the rest of the game.
  3. Click Save, then start Play Mode again. To test in DuckStation, rebuild the disc; an existing build keeps its previous settings.
  4. If it still runs out of memory, review allocations and retained data. Avoid rebuilding tables or strings every frame and loading large amounts of script data at once. Increase the heap gradually only while the overall RAM budget allows it, then review Budget Dashboard and the rebuilt project's reports. A setting of 256 KiB can leave too little RAM for a scene that fits with a smaller Lua heap. At 512 KiB, reduce script memory use rather than raising the setting beyond the engine limit.

A memory error can happen while loading a scene, before any Update callback runs. Shortening callbacks alone will not fix an undersized heap. An instruction-budget error, on the other hand, measures execution work rather than memory use.

The Console identifies the script and entity that failed. Play Mode pauses automatic retries for a failed load or frame callback; edit the script, assign a different script or restart Play Mode to retry. A changed memory setting requires a restart. Check scene transitions as well as initial loading, and test the rebuilt game in the emulator and on hardware: passing a budget report does not prove that every script allocation will fit.