#if UNITY_6000_0_OR_NEWER using System; using System.Diagnostics; using System.IO; using UnityEngine; using Debug = UnityEngine.Debug; namespace UnityEditor.AddressableAssets.Build { /// /// Handles conversion of legacy BinaryFormatter files to the new DataContractSerializer format. /// This class provides utilities for detecting legacy formats and running the converter tool. /// internal static class LegacyFormatConverter { /// /// Version marker for content state files (.bin): "ACS" + version 1 /// public static readonly byte[] ContentStateVersionMarker = { 0x41, 0x43, 0x53, 0x01 }; /// /// Version marker for config data files (.dat): "ACD" + version 1 /// public static readonly byte[] ConfigDataVersionMarker = { 0x41, 0x43, 0x44, 0x01 }; /// /// Checks if a file is in the legacy BinaryFormatter format by comparing against the expected version marker. /// /// Path to the file to check. /// The version marker bytes expected for the new format. /// True if the file is in legacy format (doesn't have the version marker), false otherwise. public static bool IsLegacyFormat(string path, byte[] versionMarker) { if (!File.Exists(path)) return false; using (var stream = new FileStream(path, FileMode.Open, FileAccess.Read)) { return IsLegacyFormat(stream, versionMarker); } } /// /// Checks if a stream contains legacy BinaryFormatter format data. /// /// The stream to check. Position will be reset after checking. /// The version marker bytes expected for the new format. /// True if the stream contains legacy format data. public static bool IsLegacyFormat(Stream stream, byte[] versionMarker) { if (stream.Length < versionMarker.Length) return true; // Too short, assume legacy var originalPosition = stream.Position; var header = new byte[versionMarker.Length]; stream.Read(header, 0, versionMarker.Length); stream.Position = originalPosition; for (int i = 0; i < versionMarker.Length; i++) { if (header[i] != versionMarker[i]) return true; // Doesn't match new format marker, assume legacy } return false; } /// /// Gets the path to the converter tool for the current platform. /// The tool is located in the package's Editor/Tools~ directory. /// /// Path to the converter tool executable. public static string GetConverterToolPath() { var packagePath = Path.GetFullPath("Packages/com.unity.addressables"); var toolsPath = Path.Combine(packagePath, "Editor", "Tools~"); #if UNITY_EDITOR_WIN return Path.Combine(toolsPath, "win/AddressablesFormatConverter.exe"); #elif UNITY_EDITOR_OSX #if UNITY_EDITOR_ARM64 return Path.Combine(toolsPath, "osx-arm64/AddressablesFormatConverter"); #else return Path.Combine(toolsPath, "osx-x64/AddressablesFormatConverter"); #endif #elif UNITY_EDITOR_LINUX return Path.Combine(toolsPath, "linux/AddressablesFormatConverter"); #else return Path.Combine(toolsPath, "win/AddressablesFormatConverter.exe"); #endif } /// /// Converts a legacy BinaryFormatter file to the new format using the converter tool. /// /// Path to the legacy file. /// If true, logs failures as warnings instead of errors. /// Path to the converted file (same as input, replaced in-place), or null if conversion failed. public static string ConvertLegacyFile(string legacyPath, bool logAsWarning = false) { var converterPath = GetConverterToolPath(); if (string.IsNullOrEmpty(converterPath) || !File.Exists(converterPath)) { var message = $"Format converter tool not found at: {converterPath}"; if (logAsWarning) Debug.LogWarning(message); else Debug.LogError(message); return null; } var convertedPath = legacyPath + ".converted"; try { var startInfo = new ProcessStartInfo { FileName = converterPath, Arguments = $"\"{legacyPath}\" \"{convertedPath}\"", UseShellExecute = false, RedirectStandardOutput = true, RedirectStandardError = true, CreateNoWindow = true }; using (var process = Process.Start(startInfo)) { process.WaitForExit(60000); // 60 second timeout if (process.ExitCode != 0) { var error = process.StandardError.ReadToEnd(); var message = $"Format converter failed with exit code {process.ExitCode}: {error}"; if (logAsWarning) Debug.LogWarning(message); else Debug.LogError(message); return null; } } if (!File.Exists(convertedPath)) { var message = "Format converter did not produce output file."; if (logAsWarning) Debug.LogWarning(message); else Debug.LogError(message); return null; } // Replace the original file with the converted one File.Delete(legacyPath); File.Move(convertedPath, legacyPath); Debug.Log($"Successfully converted legacy file: {legacyPath}"); return legacyPath; } catch (Exception e) { if (logAsWarning) Debug.LogWarning($"Failed to convert legacy file: {e.Message}"); else Debug.LogException(e); return null; } } } } #endif