Skip to main content

Release Notes 4.5.0

Highlights​

Features/Fixes​

Play back Scaniverse playback sessions​

Developers can now download a playback session recorded in Scaniverse and play it back. The recording is cached on the device, and the download reports its progress. In Swift and Kotlin, open it with PlaybackDataset.open(scanId:onProgress:) (Swift) or PlaybackDataset.open(scanId, onProgress) (Kotlin). In Unity, open it with PlaybackDataset.OpenAsync(...), then assign the dataset to RuntimeNsdkSettings.PlaybackDataset. A cache session lets you check whether a recording is cached, list and delete cached recordings, and read a recording's frame count, size, and duration before downloading. It is NSDKPlaybackCacheSession in Swift, NSDKSession.playbackCache in Kotlin, and PlaybackCacheClient in Unity.

Native playback on every platform​

Swift, Kotlin, and Unity now read playback datasets through the native playback reader, so all platforms parse a recording the same way. In Swift and Kotlin, PlaybackDataset.open(datasetPath) replaces the capture.json loaders, which are now deprecated. It exposes dataset info and per-frame PlaybackFrameMetadata, and Kotlin also opens asset:// paths from the APK. Unity's PlaybackDataset is now public, and Unity playback no longer accepts .zip dataset paths; see Breaking Changes and Setting up playback.

Localize to a specific VPS map asset​

VPS2 can now localize against one VPS map asset of a site by its UUID, including assets that are not in production. Use localize(siteId:assetId:) in Swift, localize(siteId, assetId) in Kotlin, or TryLocalize(siteId, assetId) in Unity. Stopping localization now cancels the site's requests that are still in flight. Universal localization can also use areas mapped by aerial capture when aerialLocalizationEnabled is set in Swift, enableAerialLocalization in Kotlin, or AerialLocalizationEnabled in Unity.

List site scans and non-production assets​

Sites can now list a site's scans and fetch one scan's details as ScanInfo. Use requestScansForSite and requestScanInfo in Swift and Kotlin, or RequestScansForSiteAsync and RequestScanInfoAsync on SitesClient in Unity. Location queries take a new AssetScope to include non-production assets; production-only remains the default. See Getting started with Sites.

Mesh download caching and memory budget​

Mesh downloads can now be cached on disk, which avoids downloading the same geometry and textures again. Enable the cache with configure(with:) on NSDKMeshDownloader, configure(MeshDownloaderConfig) on MeshDownloaderSession, or ConfigureCache on LocationMeshManager. Asset mesh downloads now stop at a decoded-size budget, 256 MB by default and adjustable through maxDecodedSizeKb, and meshes decode on a background thread to lower peak memory. See Mesh download.

Kotlin and Swift SDK hardening​

On Kotlin, NSDKSession can now be closed safely more than once and from any thread, and feature Flows such as Vps2Session.localizationUpdates survive close() and acquire(). The published Maven POM now declares its dependencies, and the AAR no longer adds storage permissions to apps. On Swift, the SDK is ready for Swift 6 strict concurrency, with Sendable value types and sessions and @Sendable progress callbacks.

Changelog​

Added​

  • Added localize(siteId, assetId) to localize against one VPS map asset by UUID, including non-production assets (Unity TryLocalize).
  • Added an AssetScope parameter to requestSiteAssetsByLocation to list non-production assets nearby; it defaults to Production.
  • Added requestScansForSite and requestScanInfo to list a site's scans and fetch scan details as ScanInfo (Unity RequestScansForSiteAsync, RequestScanInfoAsync).
  • Unity: Added the HttpUnauthorized Sites error for a missing, expired, or invalid access token.
  • Added an opt-in on-disk mesh download cache, configured with MeshDownloaderSession.configure (Swift configure(with:), Unity LocationMeshManager.ConfigureCache).
  • Added a maxDecodedSizeKb budget to asset mesh downloads, capping the decoded memory of delivered chunks.
  • Swift, Kotlin, Unity: Added aerialLocalizationEnabled (Kotlin enableAerialLocalization, Unity AerialLocalizationEnabled) to localize against areas mapped by aerial capture.
  • Swift, Kotlin: Added PlaybackDataset.open(scanId, onProgress) to download, cache, and open a Scaniverse playback session.
  • Swift, Kotlin: Added a playback cache session (NSDKPlaybackCacheSession, Kotlin NSDKSession.playbackCache) with isCached, cachedPlaybacks, playbackFileInfo, deleteCached, and clearCache.
  • Swift, Kotlin: Added PlaybackDataset.open(datasetPath), which reads datasets through native playback and exposes info and per-frame PlaybackFrameMetadata.
  • Kotlin: Added asset:// APK asset paths to PlaybackDataset.open and made PlaybackDataset AutoCloseable.
  • Unity: Added PlaybackCacheClient and PlaybackDataset.OpenAsync to open Scaniverse playback sessions, with IsCached, GetCachedPlaybacks, DeleteCached, and ClearCache.
  • Unity: Made PlaybackDataset public and IDisposable, with FrameCount, FrameRate, and Close().
  • Unity: Added RuntimeNsdkSettings.PlaybackDataset to play an app-opened PlaybackDataset from the next XR initialization.
  • Unity: Added AreaId to Vps2LocalizedAsset and XRVps2AssetTrackingData.
  • Unity: Added MeshChunkData, GetLocationMeshChunkDataByVpsMapAssetIdAsync, and CreateMeshChunk on LocationMeshManager to stream mesh data and build chunks later.
  • Unity: Added SiteNotFound and VpsAssetsNotFound to Vps2LocalizationError, matching the native site localization errors.
  • Python: Added Ardk.set_frame_pacing_clock to pace module frame rates on camera frame timestamps.
  • Python: Added Vps2Session.localize_to_site and Vps2Session.get_asset_tracking_data.
  • Python: Added a portal_endpoint parameter to Ardk.create() and Ardk.create_with_env_config() to choose the sites and assets endpoint.

Changed​

  • stopLocalize now cancels the site's in-flight localize requests, whose request records end Failed with Unknown.
  • Asset tracking data for an asset whose localize request is still fetching now reports not-yet-tracked instead of InvalidArgument.
  • When VPS stops georeferencing, the coarse output now holds the last confident VPS georeference instead of jumping to WPS.
  • Swift, Kotlin, Unity: Asset mesh downloads now stop at a 256 MB decoded-size budget by default; pass 0 for no budget but beware that large sites can surpass mobile device memory budgets.
  • Mesh downloads now decode on a background thread and free each node's response on arrival, lowering peak memory.
  • VPS2 area targeting now excludes every map when a trusted position is out of range of all of them, stopping localization requests.
  • Scanning no longer requires GPS and compass input; frames without them are recorded without location.
  • Unity: Playback datasets are now read through native playback instead of the managed capture.json reader.
  • Kotlin: Feature-session Flows such as Vps2Session.localizationUpdates now survive close()/acquire(), complete when NSDKSession closes, and emit an error only when it changes.
  • Swift: GeolocationData, Vps2AssetTrackingData, Vps2LocalizedAsset, NSDKMapStorage, NSDKRecordingExporter, and NSDKSitesSession now conform to Sendable.

Deprecated​

  • Swift: Deprecated PlaybackDatasetLoader, BundlePlaybackDatasetLoader, PlaybackDatasetSource, captureRoot, compassTimestampBase, and PlaybackFrame.metadata; use PlaybackDataset.open instead.
  • Kotlin: Deprecated PlaybackDataset.loadFrom, AssetPlaybackDatasetLoader, PlaybackDatasetLoader, PlaybackDatasetSource, CaptureRoot, and FrameMetadata; use PlaybackDataset.open instead.

Fixed​

  • Fixed a hang when two threads closed the same network request at once.
  • Fixed a possible crash when a mesh download was released while its HTTP callback was still decoding the mesh.
  • Fixed a crash when a feature getter ran on one thread while another thread destroyed that feature.
  • Fixed data races when Sites results were polled while the network response was still being written.
  • Fixed a scanning crash on Android devices with Samsung Xclipse 960 or newer GPUs.
  • Fixed playback mishandling datasets with a malformed depth resolution or missing frame fields.
  • Unity: Fixed the location manifest importer rejecting legacy location zips with a LocalizationTargetId or no top-level node.
  • Swift, Kotlin: Fixed PlaybackSession timestamps jumping backwards when playback looped to the first frame.
  • Swift: Fixed PlaybackSession playing slower than the dataset's recorded frame rate.
  • Swift: Fixed playback repeating edge pixels outside the image, instead of dark gray, when view and image aspect ratios differed.
  • Kotlin: Fixed PlaybackSession crashing when a frame failed to load, and running two workers after quick pause()/play() calls.
  • Kotlin: Fixed JNI strings corrupting characters such as emoji and aborting CheckJNI apps; strings now convert as standard UTF-8.
  • Kotlin: Fixed native crashes when NSDKSession creation failed or SceneSegmentationConfig.numThresholds exceeded the thresholds array length.
  • Kotlin: Fixed createLiveDataSource missing late precise-location grants and leaving GPS and compass running after destroy.
  • Kotlin: Fixed crashes when closing NSDKSession twice, from another thread, during an in-flight call, or with features still started.
  • Kotlin: Fixed the published Maven POM omitting dependencies, which caused compile errors and NoClassDefFoundError for Maven consumers.

Breaking Changes​

  • Unity: Vps2LocalizedAsset.Equals and GetHashCode now include AreaId, so values for different areas of the same asset no longer compare equal. Review dictionary keys and change detection that relied on site and asset IDs alone.
  • Unity: Playback no longer accepts .zip dataset paths, and the NSDK settings editor no longer rebuilds missing frame images from video.mp4. Unzip datasets into a directory that contains every frame image, and point the playback dataset path at that directory.
  • Kotlin: The NSDK AAR no longer merges READ_EXTERNAL_STORAGE and WRITE_EXTERNAL_STORAGE into apps. Apps that point PathConfig or log output at shared storage must declare these permissions in their own manifest.
  • Kotlin: NSDKSession.close() now throws IllegalStateException when called from inside an NSDK call on the same thread, including NsdkLogCallback.onLog, where it would otherwise deadlock. Close the session from outside NSDK callbacks.
  • Swift: Progress closures passed to the NSDKRecordingExporter export methods must now be @Sendable. They run off the main actor, so hop to the main actor before updating UI. NSDKDashcamSession.saveBuffer and NSDKScanningSession.saveCurrentScan are now @MainActor.

Known Issues​

  • Importing the NSDK UPM in a project started from Universal 3D template might cause a few build errors reported in the console. Restarting the editor should fix this.
  • VPS2 can keep reporting precise localization and tracked anchors while the device is disturbed, such as a covered camera or a dark room, so content can stay at a stale pose until confidence drops or the device localizes again.
  • On iPad Pro running iOS 17 in the Unity NSDK sample app, rotating the device from landscape to portrait may cause a soft lock and screen flickering.