# Spaces360 Scene Authoring Guide This guide supersedes the Spaces360 quick start in SETUP.md and the hotspot sections in README.md. The Dialogue system is separate and unchanged. ## Installing an update Exit Play mode and back up your project. Extract the package, then overwrite the matching scripts in `Assets/DialogueAndSpaces`; also copy any new scripts. Do not delete your scenes, graph assets, media, or existing `.meta` files. Retaining `.meta` files preserves Unity's references to the scripts. Wait for compilation to finish, then reopen the graph window if it was already open. For the catalog-removal update specifically, also delete `Spaces360/Runtime/SpacesMediaCatalog.cs` and its `.meta` file. Remove unused catalog `.asset` files through the Project window; they are no longer read by the system. Do not delete your journey graph assets or anchors. The new `SpaceMedia.cs` is a runtime value type, not an authoring asset. See `UPDATE_NOTES.md` for the complete file list. ## Concepts - **Space:** a GameObject with a `SpaceAnchor`, placed under a `SpacesJourney` root. It is paired by ID with a node in the journey's graph asset. - **Position:** the anchor's position is where the 360 media was captured. - **Panorama alignment:** the anchor's Y rotation aligns the panorama to the physical space. Pitch, roll and scale have no effect. - **Media:** drag a 360 image or video directly onto the anchor. If both are set, the video is used. - **Graph canvas:** node positions in the graph window are layout only. They never move the physical location. - **Connections:** explicit and directed. Nearby spaces are never connected automatically, so walls are respected by not connecting across them. - **Arrival heading:** the player faces the direction of travel (destination minus source, flattened to the ground plane). A to B to C faces one way and C to B to A faces the opposite way. The first entry uses the entry space's starting yaw. If two spaces share a location, the current heading is kept. Pitch resets to level. - **Markers:** in Play mode, a clickable marker appears for each connected space, in the direction of that space. ## Setup 1. In the Hierarchy, choose GameObject > Dialogue and Spaces > Create Spatial Journey. Pick a location for its graph asset. 2. Optional: on the SpatialJourney, press Create Reference Map Quad, assign your floor plan as an Unlit material, and size it to real dimensions. It is hidden in Play mode. 3. With the journey selected, choose GameObject > Dialogue and Spaces > Create Space Anchor. You can also use Create Space Here on the journey, or Add Space in the graph window. Anchors must be children of the journey. 4. On each anchor, drag a 360 image or video onto the 360 Image or 360 Video field. 5. In a top-down Scene view, move each anchor to its capture location. Rotate it on Y to align the panorama. 6. To connect spaces, select an anchor and set "Connect both ways" as desired. Drop another anchor into **Add destination** under **Add Connection**. This immediately saves the link; there is no Connect button. The destination then appears under **Saved Connections**, with an outgoing-connection count. The add field stays empty so you can add more destinations. Directed links draw as yellow lines with arrows in the Scene view; the graph window also shows connecting lines. 7. On the anchor you want to start from, press Set as Entry Space. Set its Starting yaw for the first view. 8. Select the Main Camera and add `SpacesLookController`. 9. Create one empty object, add `Spaces360Host`, and assign **Journey** and **Player Camera**. The read-only **Journey Graph** field confirms the graph used. Keep exactly one enabled host across the loaded scenes. There is no separate Graph assignment or Media Catalog. 10. Press Play. Left-drag to look around and click markers to travel. ## Editing - **Graph and scene stay paired:** creating a space in one creates its pair in the other. Moving or rotating an anchor updates the graph. - **Duplicating an anchor** creates a new space with no connections. - **Saved connections:** deselecting and reselecting an anchor rebuilds the connection list from the graph asset. Save the scene and graph assets with File > Save / Save Project before closing Unity. Adding the same destination twice does not create duplicate links. - **Removing links:** Remove deletes only the current anchor's outgoing link. For a two-way link, remove the reverse link on the destination too. - **Deleting:** use Delete Space and Paired Node in the anchor inspector. This removes the node, the GameObject and all incoming connections. - **Validate:** the graph window's Validate button reports missing media, missing destinations and unreachable spaces. - **Self tests:** the journey inspector's Run Navigation Self Tests button checks the arrival and connection rules. - **Connection persistence test:** Window > Dialogue and Spaces > Run Connection Persistence Self Tests checks that links survive graph serialization, create graph edges, avoid duplicates, and can be removed without removing other destinations. This is a graph-data test, not an automated inspector-selection test. - **JSON:** export and import are in the graph window. `mediaName` is an informational label, not a lookup key. The actual images and videos stay on the anchors; importing JSON does not assign media references to newly created anchors. - **Media:** the catalog, key lookup, and fallback constructors have been removed. Every playable space needs its image or video assigned directly on its scene anchor. Current schema 2 journey graphs and their connection IDs remain usable; old schema 1 migration is no longer supported. ## Customizing navigation buttons Select the object with `Spaces360Host` and use **Navigation Button Appearance**. These controls affect all navigation buttons on that host: - **Marker Size:** width and height in screen pixels. - **Marker Font / Font Size:** custom font and text size. - **Marker Text Color / Background Color:** text color and background tint. - **Marker Background / Hover Background:** optional Texture2D artwork for normal and hover states. Use transparent artwork for arrow-shaped or circular markers. The click area remains rectangular. - **Marker Icon:** optional icon shared by the buttons. - **Marker Show Labels:** display destination names, or disable labels for icon-only markers. For different wording on individual routes, select the source anchor and edit **Button label** below the destination in **Saved Connections**. Empty labels fall back to the destination's display name. A reverse route has its own label. This version still uses immediate-mode GUI buttons, not replaceable Canvas/TMP prefabs. Their positions remain tied to the destinations' physical directions; styling does not change connections or travel direction. The look controller uses the same marker bounds to prevent looking around when pressing a button. ## Panorama image quality and the wrap seam The anchor inspector shows **Loaded image size** and **Mip levels** for its assigned image. Unity's **Max Size** limits imported dimensions, and mipmaps are smaller versions of the texture, so these settings are useful checkpoints when investigating blur ([Unity texture import settings](https://docs.unity3d.com/2021.3/Documentation/Manual/class-TextureImporter.html)). For an image-quality comparison, exit Play mode and click **Apply Panorama Quality Test Settings...** on one anchor. The confirmation names the image asset and the settings to be changed. This opt-in diagnostic preset: - Raises Max Size to at least 8192, without lowering a higher existing limit. - Disables compression, Crunch, mipmaps, streaming, and non-power-of-two scaling. - Sets horizontal wrap (U) to Repeat, vertical wrap (V) to Clamp, and filtering to Bilinear. The renderer also applies Repeat-U/Clamp-V sampling when displaying an image, and uses it on video render textures. Repeat tiles across the horizontal boundary, whereas Clamp extends edge pixels; this is a sampling change, not a modification of your image pixels ([Unity TextureWrapMode](https://docs.unity3d.com/6000.5/Documentation/ScriptReference/TextureWrapMode.html)). The preset changes the image's importer settings, affects other objects using that image, and may substantially increase memory use. Back up its `.meta` file or use version control before applying it. Platform-specific overrides are intentionally untouched: check those if the loaded image is still smaller or compressed. This is a diagnostic baseline, not a blanket production recommendation; disabling mipmaps can introduce aliasing. If the white line remains, inspect the original panorama's leftmost and rightmost columns at full resolution. A border or stitching mismatch in the source image cannot be repaired merely by changing sampler settings. Also compare the Game view at native scale and test without camera post-processing to separate source/import issues from presentation effects. The reported seam has not yet been reproduced here, so these steps are tests, not a confirmed diagnosis. ## Video resolution Video no longer renders to a fixed 2048 x 1024 target. It uses the clip dimensions, capped by **Max Video Texture Size** on the host and the device's texture limit, preserving aspect ratio and never upscaling. Clip width is provided by Unity's video API ([Unity VideoClip.width](https://docs.unity3d.com/6000.6/Documentation/ScriptReference/Video.VideoClip-width.html)). The default cap is 8192. Lower it for memory-constrained devices; source video import/transcoding settings can still limit quality before playback. This change does not improve an already low-resolution source. ## Parallel journeys at different dates/times Each journey can have a **Journey name**, **Time label**, and optional **Date/time (ISO)** in its inspector. Create independent journeys for 2018, 2020, and 2024 and give them separate graph assets. On overlapping anchors, use **Parallel Date / Time Connections** to map counterparts across those journeys. **Map both ways** creates the return mapping. These are separate from ordinary spatial connections and are not inferred from proximity. On the single host, keep **Journey** as the starting era, add the other roots to **Parallel Journeys**, and enable **Show Time Controls**. The upper-right panel shows the current date/time and buttons for directly mapped alternatives at the active anchor. Time switches preserve yaw/pitch, use the destination capture position and graph, and leave the old journey active if media loading fails. See `PARALLEL_JOURNEYS.md` for the three-year setup, full changed-file list, JSON references, tests, and current limits. This release uses year/date buttons; it does not yet include an interpolating or discrete slider. ## Checking a connection 1. Select anchor A, enable Connect both ways, and drop anchor B into Add destination. 2. B should appear under A's Saved Connections and the outgoing count should increase. 3. Select B. A should appear in B's Saved Connections. 4. Select A again. B should still be listed. The empty Add destination field is for the next link, not the one already saved. 5. Open the paired graph window. Connecting lines should appear. Turn on Scene-view Gizmos to inspect the scene markers as well. 6. Save the scene and project, then reopen the scene to check the saved setup. ## Duplicate or stale navigation buttons Two different connected destinations can legitimately produce two buttons. However, overlapping copies with the same label can also come from multiple enabled `Spaces360Host` components maintaining separate navigation states. Search the Hierarchy for `t:Spaces360Host`, including old test objects and other loaded scenes, and keep only the intended host enabled. The current runtime permits only one active host, because the renderer uses Unity's global skybox ([Unity RenderSettings.skybox](https://docs.unity3d.com/6000.6/Documentation/ScriptReference/RenderSettings-skybox.html)). An extra host is disabled with a Console warning identifying it and the host that already owns navigation. The host inspector warns about multiple enabled hosts before Play. Buttons are generated only from the current space's valid outgoing destinations. Duplicate destinations, missing targets, and the current space itself are not shown. Clicks are processed in Update and carry the source space ID and visit revision, so a button from an earlier space or visit cannot navigate after a transition. Disabling a host disposes its renderer and releases ownership. Run Window > Dialogue and Spaces > Run Stale Marker Self Tests for data-level tests of destination filtering and stale-click rejection. These tests do not reproduce or verify the Game-view screenshot. If overlapping buttons remain with one host, check for duplicated space names and genuine separate destinations along the same bearing, and share the current space's Saved Connections and Host inspector. ## Known limits - Schema 1 graphs are not supported. Current authoring uses schema 2. - Use one journey root per graph asset in the open scenes. - The direction a panorama turns when you rotate an anchor has not been verified in Unity. If it turns the wrong way, report it. - The current patch has been syntax-checked outside Unity, but it has not been compiled or play-tested here. Run the included self-tests in your Unity project. - For sharp Insta360 images, set the texture's Max Size to 8192 in the import settings.