Better testscene
This commit is contained in:
5
.gitignore
vendored
5
.gitignore
vendored
@@ -1,4 +1,7 @@
|
||||
# SplashEdit build output
|
||||
./vscode
|
||||
*.sln
|
||||
*.slnx
|
||||
/PSXBuild/
|
||||
/.tools/
|
||||
/Library
|
||||
@@ -6,4 +9,4 @@
|
||||
/UserSettings
|
||||
/obj
|
||||
/Build
|
||||
/Temp
|
||||
/Temp
|
||||
|
||||
5
.vscode/extensions.json
vendored
Normal file
5
.vscode/extensions.json
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"visualstudiotoolsforunity.vstuc"
|
||||
]
|
||||
}
|
||||
10
.vscode/launch.json
vendored
Normal file
10
.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Attach to Unity",
|
||||
"type": "vstuc",
|
||||
"request": "attach"
|
||||
}
|
||||
]
|
||||
}
|
||||
70
.vscode/settings.json
vendored
Normal file
70
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
{
|
||||
"files.exclude": {
|
||||
"**/.DS_Store": true,
|
||||
"**/.git": true,
|
||||
"**/.vs": true,
|
||||
"**/.gitmodules": true,
|
||||
"**/.vsconfig": true,
|
||||
"**/*.booproj": true,
|
||||
"**/*.pidb": true,
|
||||
"**/*.suo": true,
|
||||
"**/*.user": true,
|
||||
"**/*.userprefs": true,
|
||||
"**/*.unityproj": true,
|
||||
"**/*.dll": true,
|
||||
"**/*.exe": true,
|
||||
"**/*.pdf": true,
|
||||
"**/*.mid": true,
|
||||
"**/*.midi": true,
|
||||
"**/*.wav": true,
|
||||
"**/*.gif": true,
|
||||
"**/*.ico": true,
|
||||
"**/*.jpg": true,
|
||||
"**/*.jpeg": true,
|
||||
"**/*.png": true,
|
||||
"**/*.psd": true,
|
||||
"**/*.tga": true,
|
||||
"**/*.tif": true,
|
||||
"**/*.tiff": true,
|
||||
"**/*.3ds": true,
|
||||
"**/*.3DS": true,
|
||||
"**/*.fbx": true,
|
||||
"**/*.FBX": true,
|
||||
"**/*.lxo": true,
|
||||
"**/*.LXO": true,
|
||||
"**/*.ma": true,
|
||||
"**/*.MA": true,
|
||||
"**/*.obj": true,
|
||||
"**/*.OBJ": true,
|
||||
"**/*.asset": true,
|
||||
"**/*.cubemap": true,
|
||||
"**/*.flare": true,
|
||||
"**/*.mat": true,
|
||||
"**/*.meta": true,
|
||||
"**/*.prefab": true,
|
||||
"**/*.unity": true,
|
||||
"build/": true,
|
||||
"Build/": true,
|
||||
"Library/": true,
|
||||
"library/": true,
|
||||
"obj/": true,
|
||||
"Obj/": true,
|
||||
"Logs/": true,
|
||||
"logs/": true,
|
||||
"ProjectSettings/": true,
|
||||
"UserSettings/": true,
|
||||
"temp/": true,
|
||||
"Temp/": true
|
||||
},
|
||||
"files.associations": {
|
||||
"*.asset": "yaml",
|
||||
"*.meta": "yaml",
|
||||
"*.prefab": "yaml",
|
||||
"*.unity": "yaml",
|
||||
},
|
||||
"explorer.fileNesting.enabled": true,
|
||||
"explorer.fileNesting.patterns": {
|
||||
"*.sln": "*.csproj",
|
||||
},
|
||||
"dotnet.defaultSolution": "sampleproj.sln"
|
||||
}
|
||||
1
Assets/.~lock.SETUP.md#
Normal file
1
Assets/.~lock.SETUP.md#
Normal file
@@ -0,0 +1 @@
|
||||
,jracek,NTBucitel,29.03.2026 12:52,file:///home/jracek/.config/libreoffice/4;
|
||||
159
Assets/SETUP.md
Normal file
159
Assets/SETUP.md
Normal file
@@ -0,0 +1,159 @@
|
||||
# PSXSplash Test Scene - Unity Setup Guide
|
||||
|
||||
This test scene exercises every Lua API namespace and callback. Follow these steps to set it up in SplashEdit.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Unity project with SplashEdit (the `splashedit` package)
|
||||
- A font atlas configured (for UI text)
|
||||
- Audio clips imported (or skip audio-related tests)
|
||||
|
||||
## Step 1: Create the Scene
|
||||
|
||||
1. Create a new Unity scene
|
||||
2. Add a **PSXSceneExporter** component to a root GameObject
|
||||
3. Add a **PSXPlayer** prefab (for player movement, gravity, collision)
|
||||
4. Add **PSXNavRegion** components to define walkable floor areas
|
||||
|
||||
## Step 2: Create Lua Files
|
||||
|
||||
Create **LuaFile** ScriptableObjects (Assets > Create > PSXSplash > Lua File) for each script:
|
||||
|
||||
| Lua File Name | Script |
|
||||
|---------------|--------|
|
||||
| `scene` | `scene.lua` (attach to scene, not an object) |
|
||||
| `collectible` | `collectible.lua` |
|
||||
| `door` | `door.lua` |
|
||||
| `npc` | `npc.lua` |
|
||||
| `switch` | `switch.lua` |
|
||||
| `spinner` | `spinner.lua` |
|
||||
| `movable` | `movable.lua` |
|
||||
| `entity_scanner` | `entity_scanner.lua` |
|
||||
|
||||
Paste each `.lua` file's content into the corresponding LuaFile asset's text field.
|
||||
|
||||
## Step 3: Set Up Scene Script
|
||||
|
||||
On the PSXSceneExporter, assign the `scene` LuaFile to the **Scene Script** field. This handles `onSceneCreationStart`, `onSceneCreationEnd`, and `onTriggerEnter/Exit`.
|
||||
|
||||
## Step 4: Create Game Objects
|
||||
|
||||
For each entity script, create a GameObject in the scene:
|
||||
|
||||
### Collectibles (x3)
|
||||
- Create 3 GameObjects with mesh renderers (cubes, spheres, etc.)
|
||||
- Add **PSXObjectExporter** to each, assign the `collectible` LuaFile
|
||||
- Space them around the scene so the player can walk into them
|
||||
- They use `onCollideWithPlayer` - no PSXInteractable needed
|
||||
|
||||
### NPC
|
||||
- Create a GameObject with a character mesh
|
||||
- Add **PSXObjectExporter**, assign `npc` LuaFile
|
||||
- Add **PSXInteractable** component (so `onInteract` fires when player presses Cross nearby)
|
||||
|
||||
### Door
|
||||
- Create a door mesh GameObject
|
||||
- Add **PSXObjectExporter**, assign `door` LuaFile
|
||||
- Add **PSXInteractable** component
|
||||
- Create a second GameObject named exactly **"DoorBlocker"** (invisible wall blocking the doorway)
|
||||
- Add **PSXObjectExporter** to DoorBlocker (no script needed)
|
||||
- The door script finds it by name and hides it when opened
|
||||
|
||||
### Switch
|
||||
- Create a switch/lever mesh GameObject
|
||||
- Add **PSXObjectExporter**, assign `switch` LuaFile
|
||||
- Add **PSXInteractable** component
|
||||
- Create a second GameObject named exactly **"SwitchTarget"**
|
||||
- Add **PSXObjectExporter** (no script needed)
|
||||
- The switch toggles this object's active state
|
||||
|
||||
### Spinner
|
||||
- Create a decorative mesh (pillar, gem, etc.)
|
||||
- Add **PSXObjectExporter**, assign `spinner` LuaFile
|
||||
- Add **PSXInteractable** component (so player can start/stop the spin)
|
||||
|
||||
### Movable
|
||||
- Create a box/crate mesh
|
||||
- Add **PSXObjectExporter**, assign `movable` LuaFile
|
||||
- Add **PSXInteractable** component (interact to select, then D-pad to move)
|
||||
|
||||
### Entity Scanner
|
||||
- Create a terminal/pedestal mesh
|
||||
- Add **PSXObjectExporter**, assign `entity_scanner` LuaFile
|
||||
- Add **PSXInteractable** component
|
||||
|
||||
## Step 5: Create Trigger Boxes
|
||||
|
||||
Add **PSXTriggerBox** components to empty GameObjects. The scene script handles these by index:
|
||||
|
||||
| Trigger Index | Purpose | Placement |
|
||||
|---------------|---------|-----------|
|
||||
| 0 | Cutscene zone | Near a scenic viewpoint |
|
||||
| 1 | Damage zone | In a hazard area (lava, spikes, etc.) |
|
||||
| 2 | Scene transition portal | At a doorway/exit |
|
||||
| 3 | Heal zone | Near a health pickup area |
|
||||
|
||||
Trigger indices are assigned in the order they appear in the scene hierarchy.
|
||||
|
||||
## Step 6: Create UI Canvases
|
||||
|
||||
In the SplashEdit UI editor, create two canvases:
|
||||
|
||||
### Canvas: "HUD"
|
||||
| Element Name | Type | Purpose |
|
||||
|-------------|------|---------|
|
||||
| ScoreText | Text | Shows "Score: 0" |
|
||||
| StatusText | Text | Shows status messages |
|
||||
| HealthBar | Progress | Shows health 0-100 |
|
||||
|
||||
### Canvas: "Dialogue"
|
||||
| Element Name | Type | Purpose |
|
||||
|-------------|------|---------|
|
||||
| DialogueText | Text | Shows NPC dialogue lines |
|
||||
|
||||
Set the Dialogue canvas to **initially hidden**.
|
||||
|
||||
## Step 7: Create Cutscenes
|
||||
|
||||
Create **PSXCutsceneClip** assets for:
|
||||
|
||||
| Cutscene Name | Type | Description |
|
||||
|---------------|------|-------------|
|
||||
| `ambient_spin` | Looping | Background ambient animation (object rotation, etc.) |
|
||||
| `camera_flyover` | One-shot | Camera pan across the scene (Camera Position + Rotation tracks) |
|
||||
| `door_open` | One-shot | Door opening animation (Object Position track) |
|
||||
| `spin_loop` | Looping | Full 360-degree rotation for the spinner object (Object Rotation track) |
|
||||
|
||||
## Step 8: Audio Clips
|
||||
|
||||
Import or create placeholder audio clips named:
|
||||
- `collect` - pickup sound
|
||||
- `door_open` - door opening
|
||||
- `switch_on` / `switch_off` - switch toggle sounds
|
||||
- `heal` - healing sound
|
||||
|
||||
## Step 9: Build and Test
|
||||
|
||||
1. Open Splash Control Panel (Window > PSXSplash > Control Panel)
|
||||
2. Click **Build and Run**
|
||||
3. Watch the PSX Console for Debug.Log output from all scripts
|
||||
4. Walk around and interact with objects to test each callback
|
||||
|
||||
## What Each Script Tests
|
||||
|
||||
| Script | Callbacks | API Namespaces |
|
||||
|--------|-----------|----------------|
|
||||
| scene.lua | onSceneCreationStart, onSceneCreationEnd, onTriggerEnter, onTriggerExit | 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 |
|
||||
|
||||
## Key Design Notes
|
||||
|
||||
- **No onUpdate anywhere.** All logic is event-driven. Rotation uses a looping cutscene.
|
||||
- **No float literals.** PS1 Lua uses integer-only numbers. Use `1/2` instead of `0.5`, `1/4` instead of `0.25`, etc.
|
||||
- **Scene globals.** `scene.lua` defines `addScore()`, `setStatus()`, `startDialogue()`, `advanceDialogue()`, `isInDialogue()`, `endDialogue()` as globals. Other scripts call these directly.
|
||||
7
Assets/SETUP.md.meta
Normal file
7
Assets/SETUP.md.meta
Normal file
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 302b4fd6078e4e32da249346a54e7647
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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 |
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e49b0a0d77a22f64c80581f45d810ac5
|
||||
guid: 5ac18ef38b923116eab9127de3b028e0
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
|
||||
@@ -132,6 +132,7 @@ GameObject:
|
||||
- component: {fileID: 172047739}
|
||||
- component: {fileID: 172047738}
|
||||
- component: {fileID: 172047742}
|
||||
- component: {fileID: 900000301}
|
||||
m_Layer: 0
|
||||
m_Name: Movable
|
||||
m_TagString: Untagged
|
||||
@@ -856,6 +857,7 @@ GameObject:
|
||||
- component: {fileID: 672874949}
|
||||
- component: {fileID: 672874948}
|
||||
- component: {fileID: 672874947}
|
||||
- component: {fileID: 900000302}
|
||||
m_Layer: 0
|
||||
m_Name: Spinner
|
||||
m_TagString: Untagged
|
||||
@@ -1099,6 +1101,53 @@ Transform:
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!1 &717858643
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 717858645}
|
||||
- component: {fileID: 717858644}
|
||||
m_Layer: 0
|
||||
m_Name: Room
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!114 &717858644
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 717858643}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: a3c7d8e2f41b5a94b826e91f3d7c0a5e, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: net.psxsplash.splashedit.Runtime::SplashEdit.RuntimeCode.PSXRoom
|
||||
RoomName:
|
||||
VolumeSize: {x: 48.78, y: 22.38, z: 57.94}
|
||||
VolumeOffset: {x: 0, y: 0, z: 0}
|
||||
--- !u!4 &717858645
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 717858643}
|
||||
serializedVersion: 2
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: -2.31339, y: 0, z: -0.27116}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!1 &794639167
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -1553,6 +1602,596 @@ Transform:
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!1 &900000001
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 900000002}
|
||||
- component: {fileID: 900000003}
|
||||
m_Layer: 0
|
||||
m_Name: CutsceneTrigger
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!4 &900000002
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 900000001}
|
||||
serializedVersion: 2
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: -8, y: 0, z: 5}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!114 &900000003
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 900000001}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 72b9d8d2e8eafba46a30ba345beb9692, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: net.psxsplash.splashedit.Runtime::SplashEdit.RuntimeCode.PSXTriggerBox
|
||||
size: {x: 6, y: 4, z: 6}
|
||||
luaFile: {fileID: 271950057456261835, guid: a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6, type: 3}
|
||||
--- !u!1 &900000011
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 900000012}
|
||||
- component: {fileID: 900000013}
|
||||
m_Layer: 0
|
||||
m_Name: DamageTrigger
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!4 &900000012
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 900000011}
|
||||
serializedVersion: 2
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 8, y: 0, z: 5}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!114 &900000013
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 900000011}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 72b9d8d2e8eafba46a30ba345beb9692, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: net.psxsplash.splashedit.Runtime::SplashEdit.RuntimeCode.PSXTriggerBox
|
||||
size: {x: 4, y: 3, z: 4}
|
||||
luaFile: {fileID: 271950057456261835, guid: b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7, type: 3}
|
||||
--- !u!1 &900000021
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 900000022}
|
||||
- component: {fileID: 900000023}
|
||||
m_Layer: 0
|
||||
m_Name: PortalTrigger
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!4 &900000022
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 900000021}
|
||||
serializedVersion: 2
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 12}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!114 &900000023
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 900000021}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 72b9d8d2e8eafba46a30ba345beb9692, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: net.psxsplash.splashedit.Runtime::SplashEdit.RuntimeCode.PSXTriggerBox
|
||||
size: {x: 3, y: 4, z: 3}
|
||||
luaFile: {fileID: 271950057456261835, guid: c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8, type: 3}
|
||||
--- !u!1 &900000031
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 900000032}
|
||||
- component: {fileID: 900000033}
|
||||
m_Layer: 0
|
||||
m_Name: HealTrigger
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!4 &900000032
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 900000031}
|
||||
serializedVersion: 2
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: -8, y: 0, z: -5}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!114 &900000033
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 900000031}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 72b9d8d2e8eafba46a30ba345beb9692, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: net.psxsplash.splashedit.Runtime::SplashEdit.RuntimeCode.PSXTriggerBox
|
||||
size: {x: 4, y: 3, z: 4}
|
||||
luaFile: {fileID: 271950057456261835, guid: d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9, type: 3}
|
||||
--- !u!1 &900000101
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 900000102}
|
||||
- component: {fileID: 900000103}
|
||||
- component: {fileID: 900000104}
|
||||
m_Layer: 5
|
||||
m_Name: HUDCanvas
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &900000102
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 900000101}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children:
|
||||
- {fileID: 900000112}
|
||||
- {fileID: 900000122}
|
||||
- {fileID: 900000132}
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 0, y: 0}
|
||||
m_AnchoredPosition: {x: 160, y: 120}
|
||||
m_SizeDelta: {x: 320, y: 240}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!223 &900000103
|
||||
Canvas:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 900000101}
|
||||
m_Enabled: 1
|
||||
serializedVersion: 3
|
||||
m_RenderMode: 2
|
||||
m_Camera: {fileID: 0}
|
||||
m_PlaneDistance: 100
|
||||
m_PixelPerfect: 0
|
||||
m_ReceivesEvents: 1
|
||||
m_OverrideSorting: 0
|
||||
m_OverridePixelPerfect: 0
|
||||
m_SortingBucketNormalizedSize: 0
|
||||
m_VertexColorAlwaysGammaSpace: 0
|
||||
m_AdditionalShaderChannelsFlag: 0
|
||||
m_UpdateRectTransformForStandalone: 0
|
||||
m_SortingLayerID: 0
|
||||
m_SortingOrder: 0
|
||||
m_TargetDisplay: 0
|
||||
--- !u!114 &900000104
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 900000101}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: dc481397cd94e03409e462478df09d58, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: net.psxsplash.splashedit.Runtime::SplashEdit.RuntimeCode.PSXCanvas
|
||||
canvasName: HUD
|
||||
startVisible: 1
|
||||
sortOrder: 10
|
||||
defaultFont: {fileID: 0}
|
||||
--- !u!1 &900000111
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 900000112}
|
||||
- component: {fileID: 900000113}
|
||||
m_Layer: 5
|
||||
m_Name: ScoreText
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &900000112
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 900000111}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 900000102}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 1}
|
||||
m_AnchorMax: {x: 0, y: 1}
|
||||
m_AnchoredPosition: {x: 80, y: -10}
|
||||
m_SizeDelta: {x: 150, y: 16}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!114 &900000113
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 900000111}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: ca4c021b4490c8f4fb9de4e14055b9e3, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: net.psxsplash.splashedit.Runtime::SplashEdit.RuntimeCode.PSXUIText
|
||||
elementName: ScoreText
|
||||
defaultText: 'Score: 0'
|
||||
textColor: {r: 1, g: 1, b: 1, a: 1}
|
||||
startVisible: 1
|
||||
fontOverride: {fileID: 0}
|
||||
--- !u!1 &900000121
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 900000122}
|
||||
- component: {fileID: 900000123}
|
||||
m_Layer: 5
|
||||
m_Name: StatusText
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &900000122
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 900000121}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 900000102}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0.5, y: 0}
|
||||
m_AnchorMax: {x: 0.5, y: 0}
|
||||
m_AnchoredPosition: {x: 0, y: 20}
|
||||
m_SizeDelta: {x: 300, y: 16}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!114 &900000123
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 900000121}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: ca4c021b4490c8f4fb9de4e14055b9e3, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: net.psxsplash.splashedit.Runtime::SplashEdit.RuntimeCode.PSXUIText
|
||||
elementName: StatusText
|
||||
defaultText:
|
||||
textColor: {r: 1, g: 0.92, b: 0, a: 1}
|
||||
startVisible: 1
|
||||
fontOverride: {fileID: 0}
|
||||
--- !u!1 &900000131
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 900000132}
|
||||
- component: {fileID: 900000133}
|
||||
m_Layer: 5
|
||||
m_Name: HealthBar
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &900000132
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 900000131}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 900000102}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 1, y: 1}
|
||||
m_AnchorMax: {x: 1, y: 1}
|
||||
m_AnchoredPosition: {x: -60, y: -10}
|
||||
m_SizeDelta: {x: 100, y: 12}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!114 &900000133
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 900000131}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: a3c1e93bdff6a714ca5b47989b5b2401, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: net.psxsplash.splashedit.Runtime::SplashEdit.RuntimeCode.PSXUIProgressBar
|
||||
elementName: HealthBar
|
||||
backgroundColor: {r: 0.2, g: 0, b: 0, a: 1}
|
||||
fillColor: {r: 0, g: 1, b: 0, a: 1}
|
||||
initialValue: 100
|
||||
startVisible: 1
|
||||
--- !u!1 &900000201
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 900000202}
|
||||
- component: {fileID: 900000203}
|
||||
- component: {fileID: 900000204}
|
||||
m_Layer: 5
|
||||
m_Name: DialogueCanvas
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &900000202
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 900000201}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children:
|
||||
- {fileID: 900000212}
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 0, y: 0}
|
||||
m_AnchoredPosition: {x: 160, y: 120}
|
||||
m_SizeDelta: {x: 320, y: 240}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!223 &900000203
|
||||
Canvas:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 900000201}
|
||||
m_Enabled: 1
|
||||
serializedVersion: 3
|
||||
m_RenderMode: 2
|
||||
m_Camera: {fileID: 0}
|
||||
m_PlaneDistance: 100
|
||||
m_PixelPerfect: 0
|
||||
m_ReceivesEvents: 1
|
||||
m_OverrideSorting: 0
|
||||
m_OverridePixelPerfect: 0
|
||||
m_SortingBucketNormalizedSize: 0
|
||||
m_VertexColorAlwaysGammaSpace: 0
|
||||
m_AdditionalShaderChannelsFlag: 0
|
||||
m_UpdateRectTransformForStandalone: 0
|
||||
m_SortingLayerID: 0
|
||||
m_SortingOrder: 0
|
||||
m_TargetDisplay: 0
|
||||
--- !u!114 &900000204
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 900000201}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: dc481397cd94e03409e462478df09d58, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: net.psxsplash.splashedit.Runtime::SplashEdit.RuntimeCode.PSXCanvas
|
||||
canvasName: Dialogue
|
||||
startVisible: 0
|
||||
sortOrder: 20
|
||||
defaultFont: {fileID: 0}
|
||||
--- !u!1 &900000211
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 900000212}
|
||||
- component: {fileID: 900000213}
|
||||
m_Layer: 5
|
||||
m_Name: DialogueText
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &900000212
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 900000211}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 900000202}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0.5, y: 0}
|
||||
m_AnchorMax: {x: 0.5, y: 0}
|
||||
m_AnchoredPosition: {x: 0, y: 40}
|
||||
m_SizeDelta: {x: 280, y: 50}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!114 &900000213
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 900000211}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: ca4c021b4490c8f4fb9de4e14055b9e3, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: net.psxsplash.splashedit.Runtime::SplashEdit.RuntimeCode.PSXUIText
|
||||
elementName: DialogueText
|
||||
defaultText:
|
||||
textColor: {r: 1, g: 1, b: 1, a: 1}
|
||||
startVisible: 1
|
||||
fontOverride: {fileID: 0}
|
||||
--- !u!114 &900000301
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 172047737}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 9b542f4ca31fa6548b8914e96dd0fae2, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: net.psxsplash.splashedit.Runtime::SplashEdit.RuntimeCode.PSXInteractable
|
||||
interactionRadius: 3
|
||||
interactButton: 15
|
||||
isRepeatable: 1
|
||||
cooldownFrames: 30
|
||||
showPrompt: 1
|
||||
promptCanvasName: canvas_int
|
||||
requireLineOfSight: 0
|
||||
--- !u!114 &900000302
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 672874946}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 9b542f4ca31fa6548b8914e96dd0fae2, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: net.psxsplash.splashedit.Runtime::SplashEdit.RuntimeCode.PSXInteractable
|
||||
interactionRadius: 3
|
||||
interactButton: 15
|
||||
isRepeatable: 1
|
||||
cooldownFrames: 30
|
||||
showPrompt: 1
|
||||
promptCanvasName: canvas_int
|
||||
requireLineOfSight: 0
|
||||
--- !u!1 &903185315
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -1974,8 +2613,8 @@ MonoBehaviour:
|
||||
SceneType: 1
|
||||
Cutscenes: []
|
||||
LoadingScreenPrefab: {fileID: 7823618876958668176, guid: c528a266b6b4ef649a6dac4e7d5a71aa, type: 3}
|
||||
PreviewBVH: 1
|
||||
PreviewRoomsPortals: 1
|
||||
PreviewBVH: 0
|
||||
PreviewRoomsPortals: 0
|
||||
BVHPreviewDepth: 9999
|
||||
--- !u!4 &1233752199
|
||||
Transform:
|
||||
@@ -2797,3 +3436,10 @@ SceneRoots:
|
||||
- {fileID: 172047741}
|
||||
- {fileID: 836539219110679941}
|
||||
- {fileID: 284994642}
|
||||
- {fileID: 900000002}
|
||||
- {fileID: 900000012}
|
||||
- {fileID: 900000022}
|
||||
- {fileID: 900000032}
|
||||
- {fileID: 900000102}
|
||||
- {fileID: 900000202}
|
||||
- {fileID: 717858645}
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
-- ============================================================================
|
||||
-- collectible.lua - Pickup item
|
||||
-- ============================================================================
|
||||
-- Tests: onCreate, onDestroy, onCollideWithPlayer, onEnable, onDisable,
|
||||
-- Tests: onCreate, onDestroy, onEnable, onDisable, onCollideWithPlayer,
|
||||
-- Entity.SetActive, Audio.Play, Persist, self.active, self.position
|
||||
|
||||
local collected = false
|
||||
|
||||
function onCreate(self)
|
||||
collected = false
|
||||
Debug.Log("Collectible created at " .. self.position.x .. "," .. self.position.y .. "," .. self.position.z)
|
||||
Debug.Log("Collectible created at "
|
||||
.. self.position.x .. "," .. self.position.y .. "," .. self.position.z)
|
||||
end
|
||||
|
||||
function onDestroy(self)
|
||||
@@ -28,9 +27,8 @@ function onCollideWithPlayer(self)
|
||||
collected = true
|
||||
|
||||
Audio.Play("collect", 127, 64)
|
||||
|
||||
-- Update score via scene script global
|
||||
Entity.SetActive(self, false)
|
||||
|
||||
addScore(100)
|
||||
setStatus("Collected! +100 points")
|
||||
Entity.SetActive(self, false)
|
||||
end
|
||||
|
||||
18
Assets/lua/cutscene_trigger.lua
Normal file
18
Assets/lua/cutscene_trigger.lua
Normal file
@@ -0,0 +1,18 @@
|
||||
-- cutscene_trigger.lua - Plays a camera flyover cutscene when player enters
|
||||
-- Attach to a PSXTriggerBox in the cutscene area
|
||||
|
||||
local played = false
|
||||
|
||||
function onTriggerEnter()
|
||||
if played then return end
|
||||
played = true
|
||||
setStatus("Cutscene playing...")
|
||||
Controls.SetEnabled(false)
|
||||
Cutscene.Play("camera_flyover", {
|
||||
onComplete = function()
|
||||
Controls.SetEnabled(true)
|
||||
setStatus("Cutscene complete!")
|
||||
played = false -- allow replay
|
||||
end
|
||||
})
|
||||
end
|
||||
7
Assets/lua/cutscene_trigger.lua.meta
Normal file
7
Assets/lua/cutscene_trigger.lua.meta
Normal file
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
13
Assets/lua/damage_trigger.lua
Normal file
13
Assets/lua/damage_trigger.lua
Normal file
@@ -0,0 +1,13 @@
|
||||
-- damage_trigger.lua - Damages player on entry, heals on exit area
|
||||
-- Attach to a PSXTriggerBox in a hazard zone
|
||||
|
||||
function onTriggerEnter()
|
||||
Debug.Log("Entered damage zone")
|
||||
setStatus("Ouch! Taking damage!")
|
||||
applyDamage(25)
|
||||
end
|
||||
|
||||
function onTriggerExit()
|
||||
Debug.Log("Exited damage zone")
|
||||
setStatus("Escaped the danger!")
|
||||
end
|
||||
7
Assets/lua/damage_trigger.lua.meta
Normal file
7
Assets/lua/damage_trigger.lua.meta
Normal file
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,34 +1,43 @@
|
||||
-- ============================================================================
|
||||
-- entity_scanner.lua - Scans all entities on interact (Entity.ForEach test)
|
||||
-- ============================================================================
|
||||
-- entity_scanner.lua - Scans all entities on interact
|
||||
-- Tests: Entity.ForEach, Entity.GetPosition, Entity.IsActive, Entity.GetCount,
|
||||
-- Entity.FindByIndex, onInteract
|
||||
-- Entity.FindByIndex, Entity.FindByScriptIndex, Vec3.lerp, Vec3.distanceSq
|
||||
|
||||
function onInteract(self)
|
||||
setStatus("Scanning all entities...")
|
||||
Debug.Log("=== Entity Scan ===")
|
||||
Debug.Log("Total entities: " .. Entity.GetCount())
|
||||
|
||||
local total = Entity.GetCount()
|
||||
Debug.Log("Total entities: " .. total)
|
||||
|
||||
local activeCount = 0
|
||||
local inactiveCount = 0
|
||||
|
||||
Entity.ForEach(function(obj)
|
||||
Entity.ForEach(function(obj, index)
|
||||
local pos = Entity.GetPosition(obj)
|
||||
local active = Entity.IsActive(obj)
|
||||
if active then
|
||||
activeCount = activeCount + 1
|
||||
else
|
||||
inactiveCount = inactiveCount + 1
|
||||
end
|
||||
activeCount = activeCount + 1
|
||||
Debug.Log(" [" .. index .. "] pos="
|
||||
.. pos.x .. "," .. pos.y .. "," .. pos.z
|
||||
.. " active=" .. tostring(Entity.IsActive(obj)))
|
||||
end)
|
||||
|
||||
Debug.Log("Active: " .. activeCount .. " Inactive: " .. inactiveCount)
|
||||
setStatus("Scan: " .. activeCount .. " active, " .. inactiveCount .. " inactive")
|
||||
Debug.Log("Active: " .. activeCount .. " of " .. total)
|
||||
setStatus("Scan: " .. activeCount .. "/" .. total .. " active")
|
||||
|
||||
-- Test FindByIndex
|
||||
local first = Entity.FindByIndex(0)
|
||||
if first then
|
||||
local pos = Entity.GetPosition(first)
|
||||
Debug.Log("Entity 0 at " .. pos.x .. "," .. pos.y .. "," .. pos.z)
|
||||
end
|
||||
|
||||
local byScript = Entity.FindByScriptIndex(0)
|
||||
if byScript then
|
||||
Debug.Log("Found entity using script 0")
|
||||
end
|
||||
|
||||
local a = Vec3.new(0, 0, 0)
|
||||
local b = Vec3.new(10, 20, 30)
|
||||
local mid = Vec3.lerp(a, b, 1/2)
|
||||
Debug.Log("Vec3.lerp midpoint: " .. mid.x .. "," .. mid.y .. "," .. mid.z)
|
||||
|
||||
local dsq = Vec3.distanceSq(a, b)
|
||||
Debug.Log("Vec3.distanceSq: " .. dsq)
|
||||
end
|
||||
|
||||
14
Assets/lua/heal_trigger.lua
Normal file
14
Assets/lua/heal_trigger.lua
Normal file
@@ -0,0 +1,14 @@
|
||||
-- heal_trigger.lua - Heals player when entering the zone
|
||||
-- Attach to a PSXTriggerBox near a health pickup
|
||||
|
||||
function onTriggerEnter()
|
||||
Debug.Log("Entered heal zone")
|
||||
setStatus("Healing!")
|
||||
applyHeal(50)
|
||||
Audio.Play("heal", 100, 64)
|
||||
end
|
||||
|
||||
function onTriggerExit()
|
||||
Debug.Log("Left heal zone")
|
||||
setStatus("Left the healing area")
|
||||
end
|
||||
7
Assets/lua/heal_trigger.lua.meta
Normal file
7
Assets/lua/heal_trigger.lua.meta
Normal file
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,43 +1,52 @@
|
||||
-- ============================================================================
|
||||
-- movable.lua - Object that can be pushed with button presses
|
||||
-- ============================================================================
|
||||
-- Tests: onButtonPress, onButtonRelease, Entity.SetPosition, Vec3 math,
|
||||
-- Camera.GetPosition, Input constants, self.position
|
||||
-- movable.lua - Object that teleports on button press (event-driven)
|
||||
-- Tests: onButtonPress, Entity.SetPosition, Vec3 math, Camera.GetPosition,
|
||||
-- Input constants, self.position, self.rotationY
|
||||
|
||||
local pushing = false
|
||||
local selected = false
|
||||
|
||||
function onCreate(self)
|
||||
pushing = false
|
||||
Debug.Log("Movable object created")
|
||||
selected = false
|
||||
Debug.Log("Movable object created at "
|
||||
.. self.position.x .. "," .. self.position.y .. "," .. self.position.z)
|
||||
end
|
||||
|
||||
function onInteract(self)
|
||||
selected = not selected
|
||||
if selected then
|
||||
setStatus("Object selected! D-pad to move, Triangle to deselect.")
|
||||
else
|
||||
setStatus("Object deselected.")
|
||||
end
|
||||
end
|
||||
|
||||
function onButtonPress(self, button)
|
||||
if button == Input.SQUARE then
|
||||
pushing = true
|
||||
if not selected then return end
|
||||
|
||||
local pos = self.position
|
||||
local step = 1
|
||||
|
||||
if button == Input.UP then
|
||||
Entity.SetPosition(self, Vec3.new(pos.x, pos.y, pos.z + step))
|
||||
elseif button == Input.DOWN then
|
||||
Entity.SetPosition(self, Vec3.new(pos.x, pos.y, pos.z - step))
|
||||
elseif button == Input.LEFT then
|
||||
Entity.SetPosition(self, Vec3.new(pos.x - step, pos.y, pos.z))
|
||||
elseif button == Input.RIGHT then
|
||||
Entity.SetPosition(self, Vec3.new(pos.x + step, pos.y, pos.z))
|
||||
elseif button == Input.L1 then
|
||||
Entity.SetPosition(self, Vec3.new(pos.x, pos.y + step, pos.z))
|
||||
elseif button == Input.R1 then
|
||||
Entity.SetPosition(self, Vec3.new(pos.x, pos.y - step, pos.z))
|
||||
elseif button == Input.TRIANGLE then
|
||||
selected = false
|
||||
setStatus("Object deselected.")
|
||||
elseif button == Input.SQUARE then
|
||||
local rot = Entity.GetRotationY(self)
|
||||
Entity.SetRotationY(self, rot + 1/2)
|
||||
end
|
||||
end
|
||||
|
||||
function onButtonRelease(self, button)
|
||||
if button == Input.SQUARE then
|
||||
pushing = false
|
||||
end
|
||||
end
|
||||
|
||||
function onUpdate(self, dt)
|
||||
if not pushing then return end
|
||||
|
||||
-- Move toward the camera position (player) slowly
|
||||
local myPos = self.position
|
||||
local camPos = Camera.GetPosition()
|
||||
local dir = Vec3.sub(camPos, myPos)
|
||||
local dist = Vec3.length(dir)
|
||||
|
||||
if dist > 1 then
|
||||
local norm = Vec3.normalize(dir)
|
||||
local step = Vec3.mul(norm, dt)
|
||||
local newPos = Vec3.add(myPos, step)
|
||||
-- Keep Y the same (don't float)
|
||||
newPos.y = myPos.y
|
||||
Entity.SetPosition(self, newPos)
|
||||
end
|
||||
local diff = Vec3.sub(self.position, camPos)
|
||||
local dist = Vec3.length(diff)
|
||||
Debug.Log("Movable moved. Dist to camera: " .. dist)
|
||||
end
|
||||
|
||||
8
Assets/lua/portal_trigger.lua
Normal file
8
Assets/lua/portal_trigger.lua
Normal file
@@ -0,0 +1,8 @@
|
||||
-- portal_trigger.lua - Scene transition when player enters
|
||||
-- Attach to a PSXTriggerBox at a doorway/exit
|
||||
|
||||
function onTriggerEnter()
|
||||
setStatus("Loading next scene...")
|
||||
Persist.Set("came_from", Scene.GetIndex())
|
||||
Scene.Load(0) -- reload scene 0 as demo
|
||||
end
|
||||
7
Assets/lua/portal_trigger.lua.meta
Normal file
7
Assets/lua/portal_trigger.lua.meta
Normal file
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,8 +1,8 @@
|
||||
-- ============================================================================
|
||||
-- scene.lua - Scene-level script for the PSXSplash test scene
|
||||
-- ============================================================================
|
||||
-- Tests: onSceneCreationStart, onSceneCreationEnd, onTriggerEnter/Exit (scene),
|
||||
-- Persist, UI, Audio, Controls, Cutscene, Scene, Timer, Debug, PSXMath
|
||||
-- Tests: onSceneCreationStart, onSceneCreationEnd, Persist, UI, Audio,
|
||||
-- Controls, Cutscene, Scene, Timer, Debug, PSXMath, Vec3
|
||||
|
||||
-- HUD handles (resolved in onSceneCreationEnd)
|
||||
local hudCanvas = -1
|
||||
@@ -48,17 +48,17 @@ function onSceneCreationEnd()
|
||||
UI.SetCanvasVisible(dialogueCanvas, false)
|
||||
end
|
||||
|
||||
-- Play ambient looping cutscene (tests loop feature)
|
||||
-- Play ambient looping cutscene
|
||||
Cutscene.Play("ambient_spin", {loop = true})
|
||||
|
||||
-- Test PSXMath functions
|
||||
-- Test PSXMath functions (all integer args)
|
||||
local clamped = PSXMath.Clamp(150, 0, 100)
|
||||
local lerped = PSXMath.Lerp(0, 10, 1)
|
||||
local lerped = PSXMath.Lerp(0, 10, 1/2)
|
||||
local sign = PSXMath.Sign(-42)
|
||||
local abs = PSXMath.Abs(-7)
|
||||
local mn = PSXMath.Min(3, 5)
|
||||
local mx = PSXMath.Max(3, 5)
|
||||
Debug.Log("PSXMath tests: clamp=" .. clamped .. " lerp=" .. lerped
|
||||
Debug.Log("PSXMath: clamp=" .. clamped .. " lerp=" .. lerped
|
||||
.. " sign=" .. sign .. " abs=" .. abs .. " min=" .. mn .. " max=" .. mx)
|
||||
|
||||
-- Test Vec3 functions
|
||||
@@ -67,55 +67,17 @@ function onSceneCreationEnd()
|
||||
local c = Vec3.add(a, b)
|
||||
local d = Vec3.cross(a, b)
|
||||
local dist = Vec3.distance(a, b)
|
||||
Debug.Log("Vec3 tests: add=" .. c.x .. "," .. c.y .. "," .. c.z
|
||||
Debug.Log("Vec3: add=" .. c.x .. "," .. c.y .. "," .. c.z
|
||||
.. " cross=" .. d.x .. "," .. d.y .. "," .. d.z
|
||||
.. " dist=" .. dist)
|
||||
end
|
||||
|
||||
-- ============================================================================
|
||||
-- Scene-level trigger callbacks (PSXTriggerBox)
|
||||
-- ============================================================================
|
||||
|
||||
function onTriggerEnter(triggerIndex)
|
||||
Debug.Log("Trigger entered: " .. triggerIndex)
|
||||
|
||||
if triggerIndex == 0 then
|
||||
-- Trigger 0: Cutscene zone
|
||||
setStatus("Cutscene playing...")
|
||||
Controls.SetEnabled(false)
|
||||
Cutscene.Play("camera_flyover", {
|
||||
onComplete = function()
|
||||
Controls.SetEnabled(true)
|
||||
setStatus("Cutscene complete!")
|
||||
end
|
||||
})
|
||||
elseif triggerIndex == 1 then
|
||||
-- Trigger 1: Damage zone
|
||||
health = PSXMath.Clamp(health - 25, 0, 100)
|
||||
updateHealthBar()
|
||||
setStatus("Ouch! Health: " .. health)
|
||||
if health <= 0 then
|
||||
setStatus("You died! Reloading...")
|
||||
Controls.SetEnabled(false)
|
||||
Persist.Set("score", 0)
|
||||
Scene.Load(Scene.GetIndex())
|
||||
end
|
||||
elseif triggerIndex == 2 then
|
||||
-- Trigger 2: Scene transition portal
|
||||
setStatus("Loading next scene...")
|
||||
Persist.Set("came_from", Scene.GetIndex())
|
||||
Scene.Load(0) -- Reload scene 0 as demo
|
||||
end
|
||||
end
|
||||
|
||||
function onTriggerExit(triggerIndex)
|
||||
Debug.Log("Trigger exited: " .. triggerIndex)
|
||||
|
||||
if triggerIndex == 0 then
|
||||
setStatus("Left cutscene zone")
|
||||
elseif triggerIndex == 1 then
|
||||
setStatus("Escaped damage zone")
|
||||
end
|
||||
local scaled = Vec3.mul(a, 3)
|
||||
local dotVal = Vec3.dot(a, b)
|
||||
local lenSq = Vec3.lengthSq(Vec3.new(3, 4, 0))
|
||||
local norm = Vec3.normalize(Vec3.new(0, 5, 0))
|
||||
Debug.Log("Vec3: mul=" .. scaled.x .. "," .. scaled.y .. "," .. scaled.z
|
||||
.. " dot=" .. dotVal .. " lenSq=" .. lenSq
|
||||
.. " norm=" .. norm.x .. "," .. norm.y .. "," .. norm.z)
|
||||
end
|
||||
|
||||
-- ============================================================================
|
||||
@@ -163,7 +125,27 @@ function isInDialogue()
|
||||
end
|
||||
|
||||
-- ============================================================================
|
||||
-- Helpers
|
||||
-- Health system (called from trigger scripts)
|
||||
-- ============================================================================
|
||||
|
||||
function applyDamage(amount)
|
||||
health = PSXMath.Clamp(health - amount, 0, 100)
|
||||
updateHealthBar()
|
||||
if health <= 0 then
|
||||
setStatus("You died! Reloading...")
|
||||
Controls.SetEnabled(false)
|
||||
Persist.Set("score", 0)
|
||||
Scene.Load(Scene.GetIndex())
|
||||
end
|
||||
end
|
||||
|
||||
function applyHeal(amount)
|
||||
health = PSXMath.Clamp(health + amount, 0, 100)
|
||||
updateHealthBar()
|
||||
end
|
||||
|
||||
-- ============================================================================
|
||||
-- Helpers (globals accessible from other scripts)
|
||||
-- ============================================================================
|
||||
|
||||
function updateScoreDisplay()
|
||||
@@ -176,6 +158,13 @@ end
|
||||
function updateHealthBar()
|
||||
if healthBar >= 0 then
|
||||
UI.SetProgress(healthBar, health)
|
||||
if health > 50 then
|
||||
UI.SetProgressColors(healthBar, 0, 40, 0, 0, 255, 0)
|
||||
elseif health > 25 then
|
||||
UI.SetProgressColors(healthBar, 40, 40, 0, 255, 255, 0)
|
||||
else
|
||||
UI.SetProgressColors(healthBar, 40, 0, 0, 255, 0, 0)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -191,3 +180,21 @@ function addScore(amount)
|
||||
Persist.Set("score", score)
|
||||
updateScoreDisplay()
|
||||
end
|
||||
|
||||
-- ============================================================================
|
||||
-- Export shared functions to _G so per-object scripts can call them.
|
||||
-- Each script gets its own environment with __index = _G as fallback.
|
||||
-- Functions defined here live in the scene's environment, not _G itself,
|
||||
-- so we must explicitly publish them.
|
||||
-- ============================================================================
|
||||
|
||||
_G.setStatus = setStatus
|
||||
_G.addScore = addScore
|
||||
_G.startDialogue = startDialogue
|
||||
_G.advanceDialogue = advanceDialogue
|
||||
_G.isInDialogue = isInDialogue
|
||||
_G.endDialogue = endDialogue
|
||||
_G.applyDamage = applyDamage
|
||||
_G.applyHeal = applyHeal
|
||||
_G.updateScoreDisplay = updateScoreDisplay
|
||||
_G.updateHealthBar = updateHealthBar
|
||||
|
||||
@@ -1,25 +1,24 @@
|
||||
-- ============================================================================
|
||||
-- spinner.lua - Continuously rotating object (onUpdate demo)
|
||||
-- ============================================================================
|
||||
-- Tests: onUpdate, self.rotationY, Entity.GetRotationY, Entity.SetRotationY,
|
||||
-- Timer.GetFrameCount, self.position, Entity.GetPosition
|
||||
|
||||
local speed = 1 -- pi-units per frame
|
||||
-- spinner.lua - Object that spins using a looping cutscene
|
||||
-- Tests: onCreate, Cutscene.Play with loop, Cutscene.Stop, Cutscene.IsPlaying,
|
||||
-- onInteract, onCollideWithPlayer, Entity.GetRotationY, Timer
|
||||
|
||||
function onCreate(self)
|
||||
Debug.Log("Spinner created, initial rotY: " .. self.rotationY)
|
||||
Cutscene.Play("spin_loop", {loop = true})
|
||||
end
|
||||
|
||||
function onUpdate(self, dt)
|
||||
-- Rotate the object by speed * dt each frame
|
||||
local current = Entity.GetRotationY(self)
|
||||
Entity.SetRotationY(self, current + speed * dt)
|
||||
|
||||
-- Every 300 frames, log position and rotation (test Timer)
|
||||
if Timer.GetFrameCount() % 300 == 0 then
|
||||
local pos = Entity.GetPosition(self)
|
||||
Debug.Log("Spinner at frame " .. Timer.GetFrameCount()
|
||||
.. " pos=" .. pos.x .. "," .. pos.y .. "," .. pos.z
|
||||
.. " rotY=" .. Entity.GetRotationY(self))
|
||||
function onInteract(self)
|
||||
if Cutscene.IsPlaying() then
|
||||
Cutscene.Stop()
|
||||
setStatus("Spinner stopped!")
|
||||
Debug.Log("Spinner stopped at rotY=" .. Entity.GetRotationY(self)
|
||||
.. " frame=" .. Timer.GetFrameCount())
|
||||
else
|
||||
Cutscene.Play("spin_loop", {loop = true})
|
||||
setStatus("Spinner started!")
|
||||
end
|
||||
end
|
||||
|
||||
function onCollideWithPlayer(self)
|
||||
Debug.Log("Player touched spinner at frame " .. Timer.GetFrameCount())
|
||||
end
|
||||
|
||||
@@ -9,9 +9,10 @@
|
||||
"com.unity.render-pipelines.universal": "17.2.0",
|
||||
"com.unity.test-framework": "1.6.0",
|
||||
"com.unity.timeline": "1.8.9",
|
||||
"com.unity.toolchain.linux-x86_64": "2.0.11",
|
||||
"com.unity.ugui": "2.0.0",
|
||||
"com.unity.visualscripting": "1.9.7",
|
||||
"net.psxsplash.splashedit": "file:E:/Code/psxsplashfix/splashedit",
|
||||
"net.psxsplash.splashedit": "file:/home/jracek/code/secretsplash",
|
||||
"com.unity.modules.accessibility": "1.0.0",
|
||||
"com.unity.modules.ai": "1.0.0",
|
||||
"com.unity.modules.androidjni": "1.0.0",
|
||||
|
||||
@@ -153,6 +153,22 @@
|
||||
"com.unity.searcher": "4.9.3"
|
||||
}
|
||||
},
|
||||
"com.unity.sysroot": {
|
||||
"version": "2.0.10",
|
||||
"depth": 1,
|
||||
"source": "registry",
|
||||
"dependencies": {},
|
||||
"url": "https://packages.unity.com"
|
||||
},
|
||||
"com.unity.sysroot.linux-x86_64": {
|
||||
"version": "2.0.9",
|
||||
"depth": 1,
|
||||
"source": "registry",
|
||||
"dependencies": {
|
||||
"com.unity.sysroot": "2.0.10"
|
||||
},
|
||||
"url": "https://packages.unity.com"
|
||||
},
|
||||
"com.unity.test-framework": {
|
||||
"version": "1.6.0",
|
||||
"depth": 0,
|
||||
@@ -185,6 +201,16 @@
|
||||
},
|
||||
"url": "https://packages.unity.com"
|
||||
},
|
||||
"com.unity.toolchain.linux-x86_64": {
|
||||
"version": "2.0.11",
|
||||
"depth": 0,
|
||||
"source": "registry",
|
||||
"dependencies": {
|
||||
"com.unity.sysroot": "2.0.10",
|
||||
"com.unity.sysroot.linux-x86_64": "2.0.9"
|
||||
},
|
||||
"url": "https://packages.unity.com"
|
||||
},
|
||||
"com.unity.ugui": {
|
||||
"version": "2.0.0",
|
||||
"depth": 0,
|
||||
@@ -205,7 +231,7 @@
|
||||
"url": "https://packages.unity.com"
|
||||
},
|
||||
"net.psxsplash.splashedit": {
|
||||
"version": "file:E:/Code/psxsplashfix/splashedit",
|
||||
"version": "file:/home/jracek/code/secretsplash",
|
||||
"depth": 0,
|
||||
"source": "local",
|
||||
"dependencies": {}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user