diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1ac85dcaf..8d569dd18 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,9 +2,13 @@
## Unreleased
-## Features
+### Fixes
+
+- The SDK now correctly resolves the storage path on Xbox during initialization, enabling offline caching and native crash capturing without user setup out of the box. ([#2617](https://github.com/getsentry/sentry-unity/pull/2617))
+
+### Features
-- The _Metrics_ APIs are now stable: removed `Experimental` from `SentrySdk` and `SentryOptions` ([#2615](https://github.com/getsentry/sentry-unity/pull/2615))
+- The _Metrics_ APIs are now stable: removed `Experimental` from `SentrySdk` and `SentryOptions`. ([#2615](https://github.com/getsentry/sentry-unity/pull/2615))
### Dependencies
diff --git a/package-dev/Runtime/Sentry.Unity.Native.Xbox.dll.meta b/package-dev/Runtime/Sentry.Unity.Native.Xbox.dll.meta
new file mode 100644
index 000000000..a74c98e4e
--- /dev/null
+++ b/package-dev/Runtime/Sentry.Unity.Native.Xbox.dll.meta
@@ -0,0 +1,123 @@
+fileFormatVersion: 2
+guid: ec5bcb9372bd4188912bb7124e548296
+PluginImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ iconMap: {}
+ executionOrder: {}
+ defineConstraints: []
+ isPreloaded: 0
+ isOverridable: 1
+ isExplicitlyReferenced: 0
+ validateReferences: 1
+ platformData:
+ - first:
+ : Any
+ second:
+ enabled: 0
+ settings:
+ Exclude Android: 1
+ Exclude Editor: 1
+ Exclude GameCoreScarlett: 0
+ Exclude GameCoreXboxOne: 0
+ Exclude Linux64: 1
+ Exclude OSXUniversal: 1
+ Exclude PS4: 1
+ Exclude PS5: 1
+ Exclude Switch: 1
+ Exclude WebGL: 1
+ Exclude Win: 1
+ Exclude Win64: 1
+ Exclude iOS: 1
+ Exclude tvOS: 1
+ - first:
+ Android: Android
+ second:
+ enabled: 0
+ settings:
+ CPU: ARMv7
+ - first:
+ Any:
+ second:
+ enabled: 0
+ settings: {}
+ - first:
+ Editor: Editor
+ second:
+ enabled: 0
+ settings:
+ CPU: AnyCPU
+ DefaultValueInitialized: true
+ OS: AnyOS
+ - first:
+ GameCoreScarlett: GameCoreScarlett
+ second:
+ enabled: 1
+ settings:
+ CPU: AnyCPU
+ - first:
+ GameCoreXboxOne: GameCoreXboxOne
+ second:
+ enabled: 1
+ settings:
+ CPU: AnyCPU
+ - first:
+ PS5: PS5
+ second:
+ enabled: 0
+ settings: {}
+ - first:
+ Standalone: Linux64
+ second:
+ enabled: 0
+ settings:
+ CPU: None
+ - first:
+ Standalone: OSXUniversal
+ second:
+ enabled: 0
+ settings:
+ CPU: None
+ - first:
+ Standalone: Win
+ second:
+ enabled: 0
+ settings:
+ CPU: None
+ - first:
+ Standalone: Win64
+ second:
+ enabled: 0
+ settings:
+ CPU: None
+ - first:
+ Switch: Switch
+ second:
+ enabled: 0
+ settings: {}
+ - first:
+ Windows Store Apps: WindowsStoreApps
+ second:
+ enabled: 0
+ settings:
+ CPU: AnyCPU
+ - first:
+ iPhone: iOS
+ second:
+ enabled: 0
+ settings:
+ AddToEmbeddedBinaries: false
+ CPU: AnyCPU
+ CompileFlags:
+ FrameworkDependencies:
+ - first:
+ tvOS: tvOS
+ second:
+ enabled: 0
+ settings:
+ CPU: AnyCPU
+ CompileFlags:
+ FrameworkDependencies:
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/package-dev/Runtime/Sentry.Unity.Native.dll.meta b/package-dev/Runtime/Sentry.Unity.Native.dll.meta
index dc4b000cf..3c76509d5 100644
--- a/package-dev/Runtime/Sentry.Unity.Native.dll.meta
+++ b/package-dev/Runtime/Sentry.Unity.Native.dll.meta
@@ -18,8 +18,8 @@ PluginImporter:
settings:
Exclude Android: 0
Exclude Editor: 1
- Exclude GameCoreScarlett: 0
- Exclude GameCoreXboxOne: 0
+ Exclude GameCoreScarlett: 1
+ Exclude GameCoreXboxOne: 1
Exclude Linux64: 0
Exclude OSXUniversal: 1
Exclude WebGL: 1
@@ -52,13 +52,13 @@ PluginImporter:
- first:
GameCoreScarlett: GameCoreScarlett
second:
- enabled: 1
+ enabled: 0
settings:
CPU: AnyCPU
- first:
GameCoreXboxOne: GameCoreXboxOne
second:
- enabled: 1
+ enabled: 0
settings:
CPU: AnyCPU
- first:
diff --git a/src/Sentry.Unity.Native/Sentry.Unity.Native.csproj b/src/Sentry.Unity.Native/Sentry.Unity.Native.csproj
index f6c13a6ef..ca7e5386e 100644
--- a/src/Sentry.Unity.Native/Sentry.Unity.Native.csproj
+++ b/src/Sentry.Unity.Native/Sentry.Unity.Native.csproj
@@ -46,4 +46,23 @@
/>
+
+
+
+
+
+
+
diff --git a/src/Sentry.Unity.Native/SentryNativeBridge.cs b/src/Sentry.Unity.Native/SentryNativeBridge.cs
index 81ac5c721..66dc18fcd 100644
--- a/src/Sentry.Unity.Native/SentryNativeBridge.cs
+++ b/src/Sentry.Unity.Native/SentryNativeBridge.cs
@@ -31,7 +31,9 @@ public static bool Init(SentryUnityOptions options)
UseLibC = Application.platform
is RuntimePlatform.LinuxPlayer or RuntimePlatform.LinuxServer
or RuntimePlatform.PS5 or RuntimePlatform.Switch;
- IsWindows = Application.platform is RuntimePlatform.WindowsPlayer or RuntimePlatform.WindowsServer;
+ IsWindows = Application.platform
+ is RuntimePlatform.WindowsPlayer or RuntimePlatform.WindowsServer
+ or RuntimePlatform.GameCoreXboxSeries or RuntimePlatform.GameCoreXboxOne;
var cOptions = sentry_options_new();
@@ -69,6 +71,10 @@ is RuntimePlatform.LinuxPlayer or RuntimePlatform.LinuxServer
sentry_options_set_attach_screenshot(cOptions, options.AttachScreenshot ? 1 : 0);
}
+#if SENTRY_NATIVE_XBOX
+ SentryNativeXbox.ResolveStoragePath(options, Logger);
+#endif
+
var databasePath = GetDatabasePath(options);
#if SENTRY_NATIVE_SWITCH
Logger?.LogDebug("Setting DatabasePath: {0}", databasePath);
@@ -119,6 +125,8 @@ internal static string GetDatabasePath(SentryUnityOptions options, IApplication?
return Path.Combine(options.CacheDirectoryPath, ".sentry-native");
}
+ // This is a fallback attempting to provide native crash support in case of CacheDirectoryPath not being set.
+ // Xbox and Switch rely on their own mechanisms to resolve storage, see SentryNativeXbox and SentryNativeSwitch.
application ??= ApplicationAdapter.Instance;
return Path.Combine(application.PersistentDataPath, ".sentry-native");
}
diff --git a/src/Sentry.Unity.Native/SentryNativeXbox.cs b/src/Sentry.Unity.Native/SentryNativeXbox.cs
new file mode 100644
index 000000000..fb67c850f
--- /dev/null
+++ b/src/Sentry.Unity.Native/SentryNativeXbox.cs
@@ -0,0 +1,62 @@
+#if SENTRY_NATIVE_XBOX
+using System;
+using System.Runtime.InteropServices;
+using Sentry.Extensibility;
+
+namespace Sentry.Unity.Native;
+
+///
+/// Xbox-specific helpers for Sentry native support.
+///
+///
+/// On Xbox, Application.persistentDataPath returns an empty string for packaged (installed) builds.
+/// The writable storage must be resolved via the Xbox Persistent Local Storage (PLS) API, which requires
+/// PersistentLocalStorage to be configured in the game's MicrosoftGame.config.
+///
+internal static class SentryNativeXbox
+{
+ [DllImport("sentry")]
+ private static extern IntPtr sentry_xbox_utils_get_pls_path();
+
+ ///
+ /// Resolves the Xbox Persistent Local Storage path and sets .
+ ///
+ ///
+ /// Called from before native SDK initialization.
+ /// If PLS is not available (e.g. not configured in MicrosoftGame.config), the cache directory
+ /// is left unset. The SDK will operate without offline caching, session persistence, or native crash reporting.
+ ///
+ internal static void ResolveStoragePath(SentryUnityOptions options, IDiagnosticLogger? logger)
+ {
+ if (!string.IsNullOrEmpty(options.CacheDirectoryPath))
+ {
+ logger?.LogWarning("The 'CacheDirectoryPath' has already been set by the user. " +
+ "Storage path resolution will be skipped.");
+ return;
+ }
+
+ string? plsPath = null;
+ try
+ {
+ var plsPathPtr = sentry_xbox_utils_get_pls_path();
+ plsPath = Marshal.PtrToStringAnsi(plsPathPtr);
+ }
+ catch (EntryPointNotFoundException)
+ {
+ logger?.LogWarning("Failed to find 'sentry_xbox_utils_get_pls_path' in sentry.dll.");
+ }
+
+ if (!string.IsNullOrEmpty(plsPath))
+ {
+ logger?.LogDebug("Setting Persistent Local Storage as cache directory path: '{0}'", plsPath);
+ options.CacheDirectoryPath = plsPath;
+ }
+ else
+ {
+ logger?.LogWarning("Failed to retrieve Xbox Persistent Local Storage path. " +
+ "Ensure 'PersistentLocalStorage' is configured in MicrosoftGame.config. " +
+ "Offline caching, session persistence, and native crash support will be disabled.");
+ }
+ }
+}
+#endif
diff --git a/src/Sentry.Unity/Properties/AssemblyInfo.cs b/src/Sentry.Unity/Properties/AssemblyInfo.cs
index 160616284..9e8226ca7 100644
--- a/src/Sentry.Unity/Properties/AssemblyInfo.cs
+++ b/src/Sentry.Unity/Properties/AssemblyInfo.cs
@@ -3,6 +3,7 @@
[assembly: InternalsVisibleTo("Sentry.Unity.Native")]
[assembly: InternalsVisibleTo("Sentry.Unity.Native.PlayStation")]
[assembly: InternalsVisibleTo("Sentry.Unity.Native.Switch")]
+[assembly: InternalsVisibleTo("Sentry.Unity.Native.Xbox")]
[assembly: InternalsVisibleTo("Sentry.Unity.Tests")]
[assembly: InternalsVisibleTo("Sentry.Unity.Editor")]
[assembly: InternalsVisibleTo("Sentry.Unity.Editor.Tests")]
diff --git a/src/Sentry.Unity/SentryUnityOptions.cs b/src/Sentry.Unity/SentryUnityOptions.cs
index 7690ce845..76235352a 100644
--- a/src/Sentry.Unity/SentryUnityOptions.cs
+++ b/src/Sentry.Unity/SentryUnityOptions.cs
@@ -501,9 +501,12 @@ or RuntimePlatform.PS5
};
// Only assign the cache directory path if we're on a "known" platform.
- // Special casing Switch here: Accessing `Application.persistentDataPath` implicitly creates a directory
- // and leads to a crash.
- if (IsKnownPlatform(application.Platform) && application.Platform is not RuntimePlatform.Switch)
+ // Special casing Switch: `Application.persistentDataPath` implicitly creates a directory and crashes.
+ // Special casing Xbox: `Application.persistentDataPath` returns an empty string on packaged builds.
+ if (IsKnownPlatform(application.Platform)
+ && application.Platform is not RuntimePlatform.Switch
+ && application.Platform is not RuntimePlatform.GameCoreXboxSeries
+ && application.Platform is not RuntimePlatform.GameCoreXboxOne)
{
CacheDirectoryPath = application.PersistentDataPath;
}
diff --git a/test/Scripts.Tests/package-release.zip.snapshot b/test/Scripts.Tests/package-release.zip.snapshot
index 0fc135018..b989804c8 100644
--- a/test/Scripts.Tests/package-release.zip.snapshot
+++ b/test/Scripts.Tests/package-release.zip.snapshot
@@ -267,6 +267,10 @@ Runtime/Sentry.Unity.Native.Switch.dll
Runtime/Sentry.Unity.Native.Switch.dll.meta
Runtime/Sentry.Unity.Native.Switch.pdb
Runtime/Sentry.Unity.Native.Switch.pdb.meta
+Runtime/Sentry.Unity.Native.Xbox.dll
+Runtime/Sentry.Unity.Native.Xbox.dll.meta
+Runtime/Sentry.Unity.Native.Xbox.pdb
+Runtime/Sentry.Unity.Native.Xbox.pdb.meta
Runtime/Sentry.Unity.pdb
Runtime/Sentry.Unity.pdb.meta
Runtime/Sentry.xml