找回密码
 立即注册
查看: 355|回复: 0

重新生成项目资源的GUID

[复制链接]
发表于 2022-4-14 17:30 | 显示全部楼层 |阅读模式
有时候合并多个项目时,因为资源GUID相同,导致合并出问题
因为在A项目中同一个文件,可能在B项目中已经被修改过了,但GUID还是同一个
所以需要重新生成所有资源的GUID
在 github 上找到一个好用的
https://github.com/jeffjadulco/unity-guid-regenerator
/*GitHub: https://github.com/jeffjads/unity-guid-regeneratorRelated Docs: https://docs.unity3d.com/ScriptReference/AssetDatabase.html              https://docs.unity3d.com/ScriptReference/AssetDatabase.FindAssets.html=== DISCLAIMER ===Only use this if really needed. Intentionally modifying asset GUID is not recommended unless certain issues are encountered.=== DISCLAIMER ====== LICENSE ===MIT LicenseCopyright (c) 2021 Jefferson JadulcoPermission is hereby granted, free of charge, to any person obtaining a copyof this software and associated documentation files (the "Software"), to dealin the Software without restriction, including without limitation the rightsto use, copy, modify, merge, publish, distribute, sublicense, and/or sellcopies of the Software, and to permit persons to whom the Software isfurnished to do so, subject to the following conditions:The above copyright notice and this permission notice shall be included in allcopies or substantial portions of the Software.THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS ORIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THEAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHERLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THESOFTWARE.=== LICENSE ===*/#if UNITY_EDITORusing System;using System.Collections.Generic;using System.IO;using System.Linq;using UnityEditor;using UnityEngine;namespace Jads.Tools{    public class AssetGUIDRegeneratorMenu    {        public const string Version = "1.0.4";        [MenuItem("Assets/Regenerate GUID/Files Only", true)]        public static bool RegenerateGUID_Validation()        {            return DoValidation();        }        [MenuItem("Assets/Regenerate GUID/Files and Folders", true)]        public static bool RegenerateGUIDWithFolders_Validation()        {            return DoValidation();        }        private static bool DoValidation()        {            var bAreSelectedAssetsValid = true;            foreach (var guid in Selection.assetGUIDs)            {                var assetPath = AssetDatabase.GUIDToAssetPath(guid);                bAreSelectedAssetsValid = !string.IsNullOrEmpty(guid) && guid != "0";            }            return bAreSelectedAssetsValid;        }        [MenuItem("Assets/Regenerate GUID/Files Only")]        public static void RegenerateGUID_Implementation()        {            DoImplementation(false);        }        [MenuItem("Assets/Regenerate GUID/Files and Folders")]        public static void RegenerateGUIDWithFolders_Implementation()        {            DoImplementation(true);        }        private static void DoImplementation(bool includeFolders)        {            var assetGUIDS = AssetGUIDRegenerator.ExtractGUIDs(Selection.assetGUIDs, includeFolders);            var option = EditorUtility.DisplayDialogComplex($"Regenerate GUID for {assetGUIDS.Length} asset/s",                "DISCLAIMER: Intentionally modifying asset GUID is not recommended unless certain issues are encountered. " +                "\n\nMake sure you have a backup or is using a version control system. \n\nThis operation can take a long time on larger projects. Do you want to proceed?",                "Yes, please", "Nope", "I need more info");            if (option == 0)            {                AssetDatabase.StartAssetEditing();                AssetGUIDRegenerator.RegenerateGUIDs(assetGUIDS);                AssetDatabase.StopAssetEditing();                AssetDatabase.SaveAssets();                AssetDatabase.Refresh();            }            else if (option == 2)            {                Application.OpenURL("https://github.com/jeffjads/unity-guid-regenerator/blob/master/README.md");            }        }    }    internal class AssetGUIDRegenerator    {        // Basically, we want to limit the types here (e.g. "t:GameObject t:Scene t:Material").        // But to support ScriptableObjects dynamically, we just include the base of all assets which is "t:Object"        private const string SearchFilter = "t:Object";        // Set to "Assets/" folder only. We don't want to include other directories of the root folder        private static readonly string[] SearchDirectories = { "Assets" };        public static void RegenerateGUIDs(string[] selectedGUIDs)        {            var assetGUIDs = AssetDatabase.FindAssets(SearchFilter, SearchDirectories);            var updatedAssets = new Dictionary<string, int>();            var skippedAssets = new List<string>();            var inverseReferenceMap = new Dictionary<string, HashSet<string>>();            /*            * PREPARATION PART 1 - Initialize map to store all paths that have a reference to our selectedGUIDs            */            foreach (var selectedGUID in selectedGUIDs)            {                inverseReferenceMap[selectedGUID] = new HashSet<string>();            }            /*             * PREPARATION PART 2 - Scan all assets and store the inverse reference if contains a reference to any selectedGUI...             */            var scanProgress = 0;            var referencesCount = 0;            foreach (var guid in assetGUIDs)            {                scanProgress++;                var path = AssetDatabase.GUIDToAssetPath(guid);                if (IsDirectory(path)) continue;                var dependencies = AssetDatabase.GetDependencies(path);                foreach (var dependency in dependencies)                {                    EditorUtility.DisplayProgressBar($"Scanning guid references on:", path, (float) scanProgress / assetGUIDs.Length);                    var dependencyGUID = AssetDatabase.AssetPathToGUID(dependency);                    if (inverseReferenceMap.ContainsKey(dependencyGUID))                    {                        inverseReferenceMap[dependencyGUID].Add(path);                        referencesCount++;                    }                }            }            var countProgress = 0;            foreach (var selectedGUID in selectedGUIDs)            {                var newGUID = GUID.Generate().ToString();                try                {                    /*                     * PART 1 - Replace the GUID of the selected asset itself. If the .meta file does not exists or does not match the guid (which shouldn't happen), do not proceed to part 2                     */                    var assetPath = AssetDatabase.GUIDToAssetPath(selectedGUID);                    var metaPath = AssetDatabase.GetTextMetaFilePathFromAssetPath(assetPath);                    if (!File.Exists(metaPath))                    {                        skippedAssets.Add(assetPath);                        throw new FileNotFoundException($"The meta file of selected asset cannot be found. Asset: {assetPath}");                    }                    var metaContents = File.ReadAllText(metaPath);                    // Check if guid in .meta file matches the guid of selected asset                    if (!metaContents.Contains(selectedGUID))                    {                        skippedAssets.Add(assetPath);                        throw new ArgumentException($"The GUID of [{assetPath}] does not match the GUID in its meta file.");                    }                    // Allow regenerating guid of folder because modifying it doesn't seem to be harmful                    // if (IsDirectory(assetPath)) continue;                    // Skip scene files                    if (assetPath.EndsWith(".unity"))                    {                        skippedAssets.Add(assetPath);                        continue;                    }                    var metaAttributes = File.GetAttributes(metaPath);                    var bIsInitiallyHidden = false;                    // If the .meta file is hidden, unhide it temporarily                    if (metaAttributes.HasFlag(FileAttributes.Hidden))                    {                        bIsInitiallyHidden = true;                        HideFile(metaPath, metaAttributes);                    }                    metaContents = metaContents.Replace(selectedGUID, newGUID);                    File.WriteAllText(metaPath, metaContents);                    if (bIsInitiallyHidden) UnhideFile(metaPath, metaAttributes);                    if (IsDirectory(assetPath))                    {                        // Skip PART 2 for directories as they should not have any references in assets or scenes                        updatedAssets.Add(AssetDatabase.GUIDToAssetPath(selectedGUID), 0);                        continue;                    }                    /*                     * PART 2 - Update the GUID for all assets that references the selected GUID                     */                    var countReplaced = 0;                    var referencePaths = inverseReferenceMap[selectedGUID];                    foreach(var referencePath in referencePaths)                    {                        countProgress++;                        EditorUtility.DisplayProgressBar($"Regenerating GUID: {assetPath}", referencePath, (float) countProgress / referencesCount);                        if (IsDirectory(referencePath)) continue;                        var contents = File.ReadAllText(referencePath);                        if (!contents.Contains(selectedGUID)) continue;                        contents = contents.Replace(selectedGUID, newGUID);                        File.WriteAllText(referencePath, contents);                        countReplaced++;                    }                    updatedAssets.Add(AssetDatabase.GUIDToAssetPath(selectedGUID), countReplaced);                }                catch (Exception e)                {                    Debug.LogError(e);                }                finally                {                    EditorUtility.ClearProgressBar();                }            }            if (EditorUtility.DisplayDialog("Regenerate GUID",                $"Regenerated GUID for {updatedAssets.Count} assets. \nSee console logs for detailed report.", "Done"))            {                var message = $"<b>GUID Regenerator {AssetGUIDRegeneratorMenu.Version}</b>\n";                if (updatedAssets.Count > 0) message += $"<b><color=green>{updatedAssets.Count} Updated Asset/s</color></b>\tSelect this log for more info\n";                message = updatedAssets.Aggregate(message, (current, kvp) => current + $"{kvp.Value} references\t{kvp.Key}\n");                if (skippedAssets.Count > 0) message += $"\n<b><color=red>{skippedAssets.Count} Skipped Asset/s</color></b>\n";                message = skippedAssets.Aggregate(message, (current, skipped) => current + $"{skipped}\n");                Debug.Log($"{message}");            }        }        // Searches for Directories and extracts all asset guids inside it using AssetDatabase.FindAssets        public static string[] ExtractGUIDs(string[] selectedGUIDs, bool includeFolders)        {            var finalGuids = new List<string>();            foreach (var guid in selectedGUIDs)            {                var assetPath = AssetDatabase.GUIDToAssetPath(guid);                if (IsDirectory(assetPath))                {                    string[] searchDirectory = {assetPath};                    if (includeFolders) finalGuids.Add(guid);                    finalGuids.AddRange(AssetDatabase.FindAssets(SearchFilter, searchDirectory));                }                else                {                    finalGuids.Add(guid);                }            }            return finalGuids.ToArray();        }        private static void HideFile(string path, FileAttributes attributes)        {            attributes &= ~FileAttributes.Hidden;            File.SetAttributes(path, attributes);        }        private static void UnhideFile(string path, FileAttributes attributes)        {            attributes |= FileAttributes.Hidden;            File.SetAttributes(path, attributes);        }        public static bool IsDirectory(string path) => File.GetAttributes(path).HasFlag(FileAttributes.Directory);    }}#endif
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-9-22 14:40 , Processed in 0.089170 second(s), 25 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表