11 KiB
Test Scene Setup Guide
This guide walks you through building the PSXSplash test scene in Unity step by step. The scene exercises every major feature: player movement, collision, Lua scripting (all callbacks), cutscenes (loop + callback), UI, audio, triggers, interactables, persist, controls enable/disable, and scene transitions.
Prerequisites
- SplashEdit package installed in Unity
- PSXSplash native project cloned and configured in the Control Panel
- The Lua files from
test-scene/lua/copied into your Unity project's Assets folder
Step 1: Create the Scene
- File > New Scene (Basic Built-in)
- Save as
TestScenein your Scenes folder
Step 2: Build the Room
Create a simple enclosed room for the player to walk around in.
Floor
- GameObject > 3D Object > Plane
- Name:
Floor - Position: (0, 0, 0), Scale: (3, 1, 3) (gives a 30x30 unit floor)
- Add component: PSX Object Exporter
- Bit Depth: 8bpp
- Collision Type: Mesh (nav regions will be generated from this)
Walls (4 total)
Create 4 stretched cubes around the edges:
| Name | Position | Scale |
|---|---|---|
| WallNorth | (0, 2, 15) | (30, 4, 0.5) |
| WallSouth | (0, 2, -15) | (30, 4, 0.5) |
| WallEast | (15, 2, 0) | (0.5, 4, 30) |
| WallWest | (-15, 2, 0) | (0.5, 4, 30) |
For each wall:
- Add component: PSX Object Exporter
- Bit Depth: 4bpp
- Collision Type: Mesh
Step 3: Add the Player
- Create an empty GameObject named
PSXPlayer - Position: (0, 0, -10) (near the south wall)
- Add component: PSX Player
- Move Speed: 2.0
- Sprint Speed: 4.0
- Player Height: 3.0
- Player Radius: 1.0
- Jump Velocity: 8.0
- Gravity: 15.0
Step 4: Scene Exporter Setup
- Select the scene root or create an empty
SceneSetupobject - Add component: PSX Scene Exporter
- Scene Type: Exterior
- GTE Scaling: 100
- Fog: Disabled (or enable for atmosphere)
- Scene Lua File: Assign
scene.lua
Step 5: Create the Objects
Collectibles (3x)
| Name | Position | Lua File |
|---|---|---|
| Collectible1 | (-8, 1, 8) | collectible.lua |
| Collectible2 | (0, 1, 8) | collectible.lua |
| Collectible3 | (8, 1, 8) | collectible.lua |
For each:
- GameObject > 3D Object > Sphere, scale (0.5, 0.5, 0.5)
- Add PSX Object Exporter
- Bit Depth: 4bpp
- Collision Type: Sphere
- Lua File:
collectible.lua - Collision Radius: 2.0
Spinner
- GameObject > 3D Object > Cube, name:
Spinner - Position: (-8, 1, 2), Scale: (1, 1, 1)
- Add PSX Object Exporter
- Lua File:
spinner.lua - Collision Type: None
- Lua File:
Door
- GameObject > 3D Object > Cube, name:
Door - Position: (8, 2, 5), Scale: (0.5, 4, 3)
- Add PSX Object Exporter
- Collision Type: None
- Lua File:
door.lua
- Add PSX Interactable
- Interaction Radius: 3.0
- Interaction Button: Cross
- Show Prompt: true
- Repeatable: true
Door Blocker
- GameObject > 3D Object > Cube, name:
DoorBlocker - Position: (8, 2, 5), Scale: (0.5, 4, 3)
- Add PSX Object Exporter
- Collision Type: Mesh (blocks the player)
- No Lua file needed - the door script finds it by name
NPC
- GameObject > 3D Object > Capsule, name:
NPC - Position: (0, 1.5, 2), Scale: (1, 1.5, 1)
- Add PSX Object Exporter
- Collision Type: None
- Lua File:
npc.lua
- Add PSX Interactable
- Interaction Radius: 3.0
- Interaction Button: Cross
- Show Prompt: true
- Repeatable: true
Switch
- GameObject > 3D Object > Cube, name:
Switch - Position: (-8, 0.5, -5), Scale: (0.5, 1, 0.5)
- Add PSX Object Exporter
- Lua File:
switch.lua
- Lua File:
- Add PSX Interactable
- Interaction Radius: 2.5
- Interaction Button: Cross
- Show Prompt: true
- Repeatable: true
Switch Target
- GameObject > 3D Object > Cube, name:
SwitchTarget - Position: (-5, 1, -5), Scale: (2, 2, 2)
- Add PSX Object Exporter
- Active: true (the switch script will toggle it)
Movable Object
- GameObject > 3D Object > Sphere, name:
Movable - Position: (5, 0.5, -5), Scale: (1, 1, 1)
- Add PSX Object Exporter
- Lua File:
movable.lua - Collision Type: None
- Lua File:
Entity Scanner
- GameObject > 3D Object > Cylinder, name:
Scanner - Position: (0, 1, -8), Scale: (0.5, 1, 0.5)
- Add PSX Object Exporter
- Lua File:
entity_scanner.lua
- Lua File:
- Add PSX Interactable
- Interaction Radius: 2.5
- Interaction Button: Cross
- Show Prompt: true
- Repeatable: true
Step 6: Trigger Boxes
Cutscene Trigger (index 0)
- Create empty GameObject, name:
CutsceneTrigger - Position: (10, 0, 0)
- Add PSXTriggerBox
- Size: (4, 4, 4)
- Trigger Index: 0
Damage Zone (index 1)
- Create empty GameObject, name:
DamageZone - Position: (-10, 0, -10)
- Add PSXTriggerBox
- Size: (4, 2, 4)
- Trigger Index: 1
Scene Portal (index 2)
- Create empty GameObject, name:
ScenePortal - Position: (0, 0, 12)
- Add PSXTriggerBox
- Size: (3, 4, 1)
- Trigger Index: 2
Step 7: UI Canvases
HUD Canvas
- Create empty GameObject, name:
HUD - Add PSXCanvas
- Visible: true
Add children with PSXUIBox or appropriate UI components:
| Name | Component | Position | Details |
|---|---|---|---|
| ScoreText | PSXUIText | Top-left (10, 10) | Text: "Score: 0" |
| StatusText | PSXUIText | Bottom-left (10, 220) | Text: "Welcome!" |
| HealthBar | PSXUIProgressBar | Top-right (220, 10) | Value: 100, Width: 80 |
Dialogue Canvas
- Create empty GameObject, name:
Dialogue - Add PSXCanvas
- Visible: false (hidden by default)
Add children:
| Name | Component | Position | Details |
|---|---|---|---|
| DialogueText | PSXUIText | Center-bottom (40, 180) | Text: "" |
Font
- Create a PSXFontAsset (Right-click > Create > PSXFontAsset)
- Assign your font texture
- Reference it in the PSX Scene Exporter's font slot
Step 8: Audio Clips
Add the following audio clips to the scene (via PSXAudioClip components or the scene exporter's audio list):
| Clip Name | Usage |
|---|---|
collect |
Collectible pickup sound |
door_open |
Door opening sound |
switch_on |
Switch activation |
switch_off |
Switch deactivation |
These names must match what the Lua scripts pass to Audio.Play(). Use any short WAV files - they will be converted to PS1 ADPCM during export.
Step 9: Cutscenes
Create the following PSXCutsceneClip assets and add them to the Scene Exporter's cutscene list:
ambient_spin
A looping animation that rotates an object continuously (used with loop = true).
- 1 track: Object RotationY targeting
Spinner - Keyframes: frame 0 = 0.0, frame 60 = 2.0 (full rotation in 2 seconds)
- Interpolation: Linear
- Total frames: 60
camera_flyover
A camera pan triggered by trigger box 0.
- Track 1: Camera Position
- Frame 0: Player position (0, 3, -10)
- Frame 30: Above room (0, 15, 0)
- Frame 60: Back to player (0, 3, -10)
- Interpolation: EaseInOut
- Track 2: Camera Rotation
- Frame 0: (0.15, 0, 0) (slight downward tilt)
- Frame 30: (0.5, 0, 0) (looking straight down)
- Frame 60: (0.15, 0, 0) (back to normal)
- Interpolation: EaseInOut
- Total frames: 60
door_open
Animates the door object and camera for the door interaction.
- Track 1: Camera Position (pan to look at door)
- Frame 0: (current position, captured automatically)
- Frame 15: (7, 3, 2) (viewing angle on door)
- Frame 45: (7, 3, 2) (hold)
- Frame 60: (current position, blends back)
- Interpolation: EaseInOut
- Track 2: Object Position targeting
Door- Frame 15: (8, 2, 5) (closed position)
- Frame 45: (8, 6, 5) (moved up / opened)
- Interpolation: EaseOut
- Total frames: 60
Step 10: Navigation Setup
- Select the Floor and Wall objects
- In the PSX Scene Exporter, configure navigation:
- Agent Radius: 1.0
- Agent Height: 3.0
- Max Step Height: 0.5
- Max Slope: 45
- Bake navigation (this generates the nav regions from the floor mesh)
- Verify the blue nav region overlay covers the walkable area
Step 11: Export and Build
- Open the SplashEdit Control Panel (Window > SplashEdit > Control Panel)
- Go to the Scenes tab
- Add
TestSceneas Scene 0 - Go to the Build tab
- Click Export All Scenes
- Click Build & Run (for emulator) or Build ISO (for real hardware)
What the Test Scene Verifies
| Feature | How it's tested |
|---|---|
| Player movement | Walk around the room |
| Jumping | Jump with Cross button |
| Collision | Walk into walls, they block you |
| Nav regions | Floor constrains movement |
| Gravity | Fall back down after jumping |
| onCollideWithPlayer | Touch the collectible spheres |
| onInteract | Press Cross near Door, NPC, Switch, Scanner |
| onTriggerEnter/Exit | Walk into the trigger boxes |
| onButtonPress/Release | Hold Square near the Movable object |
| onUpdate | Watch the Spinner rotate continuously |
| onCreate/onDestroy | Check debug log at scene load |
| onEnable/onDisable | Collect an item (disables it) |
| onSceneCreationStart/End | Check debug log |
| Cutscene.Play | Walk into trigger box 0 |
| Cutscene loop | ambient_spin runs from scene start |
| Cutscene onComplete | Door cutscene re-enables controls |
| Cutscene.Stop | Stop ambient when needed |
| Cutscene.IsPlaying | Door script checks before playing |
| Controls.SetEnabled | Disabled during cutscenes and dialogue |
| Controls.IsEnabled | Available for query |
| Camera.GetPosition | Used by movable.lua |
| Camera.SetPosition | Tested via cutscene camera tracks |
| Camera.SetRotation | Tested via cutscene camera tracks |
| Entity.Find | Door finds DoorBlocker, Switch finds SwitchTarget |
| Entity.FindByIndex | Scanner tests this |
| Entity.ForEach | Scanner iterates all entities |
| Entity.GetCount | Switch and Scanner log it |
| Entity.SetActive | Collectible, Switch, Door all toggle objects |
| Entity.IsActive | Switch checks target state |
| Entity.Get/SetPosition | Movable object moves via Lua |
| Entity.Get/SetRotationY | Spinner rotates via Lua |
| Vec3 (all functions) | scene.lua tests in onSceneCreationEnd |
| PSXMath (all functions) | scene.lua tests in onSceneCreationEnd |
| Audio.Play | Collectible, Door, Switch play sounds |
| UI.FindCanvas | scene.lua resolves HUD and Dialogue |
| UI.FindElement | scene.lua resolves text and progress bar |
| UI.SetText | Score, status, dialogue display |
| UI.SetProgress | Health bar updates on damage |
| UI.SetCanvasVisible | Dialogue canvas show/hide |
| Persist.Get/Set | Score persists across scene reloads |
| Scene.Load | Portal trigger reloads scene |
| Scene.GetIndex | Logged on scene start |
| Timer.GetFrameCount | Spinner logs periodically |
| Debug.Log | Used throughout all scripts |
| Input constants | NPC dialogue uses Input.CROSS |
Debugging Tips
- Open the PSX Console window (Window > SplashEdit > PSX Console) to see Debug.Log output
- In PCSX-Redux, enable the Lua console to see printf output
- In Duckstation, check the CD-ROM debug window for drive state
- If something doesn't work, check the debug log for error messages from the Lua scripts