Better testscene

This commit is contained in:
2026-03-29 13:18:13 +02:00
parent 1fdb223f5d
commit 3f462d3482
27 changed files with 3714 additions and 3036 deletions

View File

@@ -1,382 +1,78 @@
# 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
1. File > New Scene (Basic Built-in)
2. Save as `TestScene` in your Scenes folder
---
## Step 2: Build the Room
Create a simple enclosed room for the player to walk around in.
### Floor
1. GameObject > 3D Object > Plane
2. Name: `Floor`
3. Position: (0, 0, 0), Scale: (3, 1, 3) (gives a 30x30 unit floor)
4. 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
1. Create an empty GameObject named `PSXPlayer`
2. Position: (0, 0, -10) (near the south wall)
3. 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
1. Select the scene root or create an empty `SceneSetup` object
2. 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:
1. GameObject > 3D Object > Sphere, scale (0.5, 0.5, 0.5)
2. Add **PSX Object Exporter**
- Bit Depth: 4bpp
- Collision Type: **Sphere**
- Lua File: `collectible.lua`
- Collision Radius: 2.0
### Spinner
1. GameObject > 3D Object > Cube, name: `Spinner`
2. Position: (-8, 1, 2), Scale: (1, 1, 1)
3. Add **PSX Object Exporter**
- Lua File: `spinner.lua`
- Collision Type: None
### Door
1. GameObject > 3D Object > Cube, name: `Door`
2. Position: (8, 2, 5), Scale: (0.5, 4, 3)
3. Add **PSX Object Exporter**
- Collision Type: None
- Lua File: `door.lua`
4. Add **PSX Interactable**
- Interaction Radius: 3.0
- Interaction Button: Cross
- Show Prompt: true
- Repeatable: true
### Door Blocker
1. GameObject > 3D Object > Cube, name: `DoorBlocker`
2. Position: (8, 2, 5), Scale: (0.5, 4, 3)
3. Add **PSX Object Exporter**
- Collision Type: **Mesh** (blocks the player)
- No Lua file needed - the door script finds it by name
### NPC
1. GameObject > 3D Object > Capsule, name: `NPC`
2. Position: (0, 1.5, 2), Scale: (1, 1.5, 1)
3. Add **PSX Object Exporter**
- Collision Type: None
- Lua File: `npc.lua`
4. Add **PSX Interactable**
- Interaction Radius: 3.0
- Interaction Button: Cross
- Show Prompt: true
- Repeatable: true
### Switch
1. GameObject > 3D Object > Cube, name: `Switch`
2. Position: (-8, 0.5, -5), Scale: (0.5, 1, 0.5)
3. Add **PSX Object Exporter**
- Lua File: `switch.lua`
4. Add **PSX Interactable**
- Interaction Radius: 2.5
- Interaction Button: Cross
- Show Prompt: true
- Repeatable: true
### Switch Target
1. GameObject > 3D Object > Cube, name: `SwitchTarget`
2. Position: (-5, 1, -5), Scale: (2, 2, 2)
3. Add **PSX Object Exporter**
- Active: true (the switch script will toggle it)
### Movable Object
1. GameObject > 3D Object > Sphere, name: `Movable`
2. Position: (5, 0.5, -5), Scale: (1, 1, 1)
3. Add **PSX Object Exporter**
- Lua File: `movable.lua`
- Collision Type: None
### Entity Scanner
1. GameObject > 3D Object > Cylinder, name: `Scanner`
2. Position: (0, 1, -8), Scale: (0.5, 1, 0.5)
3. Add **PSX Object Exporter**
- Lua File: `entity_scanner.lua`
4. Add **PSX Interactable**
- Interaction Radius: 2.5
- Interaction Button: Cross
- Show Prompt: true
- Repeatable: true
---
## Step 6: Trigger Boxes
### Cutscene Trigger (index 0)
1. Create empty GameObject, name: `CutsceneTrigger`
2. Position: (10, 0, 0)
3. Add **PSXTriggerBox**
- Size: (4, 4, 4)
- Trigger Index: 0
### Damage Zone (index 1)
1. Create empty GameObject, name: `DamageZone`
2. Position: (-10, 0, -10)
3. Add **PSXTriggerBox**
- Size: (4, 2, 4)
- Trigger Index: 1
### Scene Portal (index 2)
1. Create empty GameObject, name: `ScenePortal`
2. Position: (0, 0, 12)
3. Add **PSXTriggerBox**
- Size: (3, 4, 1)
- Trigger Index: 2
---
## Step 7: UI Canvases
### HUD Canvas
1. Create empty GameObject, name: `HUD`
2. 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
1. Create empty GameObject, name: `Dialogue`
2. Add **PSXCanvas**
- Visible: false (hidden by default)
Add children:
| Name | Component | Position | Details |
|------|-----------|----------|---------|
| DialogueText | PSXUIText | Center-bottom (40, 180) | Text: "" |
### Font
1. Create a **PSXFontAsset** (Right-click > Create > PSXFontAsset)
2. Assign your font texture
3. 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
1. Select the Floor and Wall objects
2. In the PSX Scene Exporter, configure navigation:
- Agent Radius: 1.0
- Agent Height: 3.0
- Max Step Height: 0.5
- Max Slope: 45
3. Bake navigation (this generates the nav regions from the floor mesh)
4. Verify the blue nav region overlay covers the walkable area
---
## Step 11: Export and Build
1. Open the SplashEdit Control Panel (Window > SplashEdit > Control Panel)
2. Go to the Scenes tab
3. Add `TestScene` as Scene 0
4. Go to the Build tab
5. Click **Export All Scenes**
6. 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
# PSXSplash Test Scene
This Unity project is a complete test scene for PSXSplash's Lua scripting API.
Open it in Unity with the SplashEdit package installed.
## What's In the Scene
### Game Objects
- **PSXPlayer** - Player controller at (0, 0, -10)
- **Floor** - Walkable ground plane
- **Wall1-4** - Boundary walls
- **Collectible1-3** - Pickup items (onCollideWithPlayer)
- **NPC** - Interactable NPC with multi-line dialogue
- **Door** - Interactable door with cutscene animation
- **DoorBlocker** - Invisible wall removed when door opens
- **Switch** - Toggle switch controlling SwitchTarget
- **SwitchTarget** - Object toggled by the switch
- **Spinner** - Object with looping cutscene rotation (onInteract to toggle)
- **Movable** - Object selected via onInteract, moved via D-pad button presses
- **Scanner** - Entity scanner terminal (onInteract)
### Trigger Boxes (PSXTriggerBox)
Each trigger has its own Lua script - no trigger index routing.
- **CutsceneTrigger** at (-8, 0, 5) - Plays camera_flyover cutscene
- **DamageTrigger** at (8, 0, 5) - Damages player on entry
- **PortalTrigger** at (0, 0, 12) - Scene transition
- **HealTrigger** at (-8, 0, -5) - Heals player on entry
### UI Canvases (PSXCanvas)
- **HUD** (always visible, sort order 10):
- ScoreText - shows "Score: 0"
- StatusText - shows status messages
- HealthBar - progress bar 0-100
- **Dialogue** (hidden by default, sort order 20):
- DialogueText - shows NPC dialogue lines
## Still Needed
### Cutscenes
Create PSXCutsceneClip assets with these names and add to SceneExporter:
- `ambient_spin` - Looping background animation
- `camera_flyover` - One-shot camera pan (Camera Position + Rotation tracks)
- `door_open` - Door opening animation (Object Position track)
- `spin_loop` - Full 360 rotation for Spinner (Object Rotation track)
### Audio Clips
- `collect` - pickup sound
- `door_open` - door opening
- `switch_on` / `switch_off` - switch toggle
- `heal` - healing sound
### Navigation
Bake nav regions from the floor geometry via PlayStation 1 > Nav Region Builder.
## Design Notes
- **Zero onUpdate.** All logic is event-driven.
- **Zero float literals.** Uses `1/2` instead of `0.5` etc.
- **Each trigger has its own script.** No index-based routing.
- **Scene globals.** scene.lua defines: setStatus(), addScore(), applyDamage(),
applyHeal(), startDialogue(), advanceDialogue(), isInDialogue(), endDialogue().
## API Coverage
| Script | Callbacks | Namespaces |
|--------|-----------|------------|
| scene.lua | onSceneCreationStart/End | Scene, Persist, UI, Audio, Controls, Cutscene, Timer, Debug, PSXMath, Vec3 |
| collectible.lua | onCreate, onDestroy, onEnable, onDisable, onCollideWithPlayer | Entity, Audio, Persist |
| door.lua | onCreate, onInteract | Entity, Audio, Controls, Cutscene |
| npc.lua | onCreate, onInteract, onButtonPress | Input, Controls, UI |
| switch.lua | onCreate, onInteract | Entity, Audio |
| spinner.lua | onCreate, onInteract, onCollideWithPlayer | Cutscene, Entity, Timer |
| movable.lua | onCreate, onInteract, onButtonPress | Entity, Vec3, Camera, Input |
| entity_scanner.lua | onInteract | Entity, Vec3 |
| cutscene_trigger.lua | onTriggerEnter | Controls, Cutscene |
| damage_trigger.lua | onTriggerEnter, onTriggerExit | Debug |
| portal_trigger.lua | onTriggerEnter | Persist, Scene |
| heal_trigger.lua | onTriggerEnter, onTriggerExit | Audio, Debug |