Skip to content

Instantly share code, notes, and snippets.

@ms502040
Forked from dyeo/UnityGuidRegenerator.cs
Created February 12, 2022 00:22
Show Gist options
  • Select an option

  • Save ms502040/f33a350a766cadb801c030a24dca664f to your computer and use it in GitHub Desktop.

Select an option

Save ms502040/f33a350a766cadb801c030a24dca664f to your computer and use it in GitHub Desktop.

Revisions

  1. @dyeo dyeo revised this gist Nov 22, 2019. 1 changed file with 3 additions and 5 deletions.
    8 changes: 3 additions & 5 deletions UnityGuidRegenerator.cs
    Original file line number Diff line number Diff line change
    @@ -1,5 +1,3 @@
    // Drop into Assets/Editor, use "Tools/Regenerate asset GUIDs"

    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    @@ -8,10 +6,10 @@

    namespace UnityGuidRegenerator {
    public class UnityGuidRegeneratorMenu {
    [MenuItem("Tools/Regenerate asset GUIDs")]
    [MenuItem("Tools/Regenerate All GUIDs")]
    public static void RegenerateGuids() {
    if (EditorUtility.DisplayDialog("GUIDs regeneration",
    "You are going to start the process of GUID regeneration. This may have unexpected results. \n\nMAKE A PROJECT BACKUP BEFORE PROCEEDING!",
    if (EditorUtility.DisplayDialog("Regenerate All GUIDs",
    "You are going to start the process of GUID regeneration. This may have unexpected results and may break unsaved changes. Are you sure you want to do this?",
    "Regenerate GUIDs", "Cancel")) {
    try {
    AssetDatabase.StartAssetEditing();
  2. Serhii Yolkin revised this gist Aug 6, 2018. 1 changed file with 2 additions and 0 deletions.
    2 changes: 2 additions & 0 deletions UnityGuidRegenerator.cs
    Original file line number Diff line number Diff line change
    @@ -38,6 +38,8 @@ internal class UnityGuidRegenerator {
    "*.unity",
    "*.asset",
    "*.guiskin",
    "*.fontsettings",
    "*.controller",
    };

    private readonly string _assetsPath;
  3. Serhii Yolkin revised this gist Sep 19, 2016. 1 changed file with 2 additions and 1 deletion.
    3 changes: 2 additions & 1 deletion UnityGuidRegenerator.cs
    Original file line number Diff line number Diff line change
    @@ -36,7 +36,8 @@ internal class UnityGuidRegenerator {
    "*.anim",
    "*.prefab",
    "*.unity",
    "*.asset"
    "*.asset",
    "*.guiskin",
    };

    private readonly string _assetsPath;
  4. Serhii Yolkin renamed this gist Sep 2, 2014. 1 changed file with 0 additions and 0 deletions.
    File renamed without changes.
  5. Serhii Yolkin renamed this gist Sep 2, 2014. 1 changed file with 0 additions and 0 deletions.
    File renamed without changes.
  6. Serhii Yolkin created this gist Sep 2, 2014.
    177 changes: 177 additions & 0 deletions gistfile1.txt
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,177 @@
    // Drop into Assets/Editor, use "Tools/Regenerate asset GUIDs"

    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.IO;
    using UnityEditor;

    namespace UnityGuidRegenerator {
    public class UnityGuidRegeneratorMenu {
    [MenuItem("Tools/Regenerate asset GUIDs")]
    public static void RegenerateGuids() {
    if (EditorUtility.DisplayDialog("GUIDs regeneration",
    "You are going to start the process of GUID regeneration. This may have unexpected results. \n\nMAKE A PROJECT BACKUP BEFORE PROCEEDING!",
    "Regenerate GUIDs", "Cancel")) {
    try {
    AssetDatabase.StartAssetEditing();

    string path = Path.GetFullPath(".") + Path.DirectorySeparatorChar + "Assets";
    UnityGuidRegenerator regenerator = new UnityGuidRegenerator(path);
    regenerator.RegenerateGuids();
    }
    finally {
    AssetDatabase.StopAssetEditing();
    EditorUtility.ClearProgressBar();
    AssetDatabase.Refresh();
    }
    }
    }
    }

    internal class UnityGuidRegenerator {
    private static readonly string[] kDefaultFileExtensions = {
    "*.meta",
    "*.mat",
    "*.anim",
    "*.prefab",
    "*.unity",
    "*.asset"
    };

    private readonly string _assetsPath;

    public UnityGuidRegenerator(string assetsPath) {
    _assetsPath = assetsPath;
    }

    public void RegenerateGuids(string[] regeneratedExtensions = null) {
    if (regeneratedExtensions == null) {
    regeneratedExtensions = kDefaultFileExtensions;
    }

    // Get list of working files
    List<string> filesPaths = new List<string>();
    foreach (string extension in regeneratedExtensions) {
    filesPaths.AddRange(
    Directory.GetFiles(_assetsPath, extension, SearchOption.AllDirectories)
    );
    }

    // Create dictionary to hold old-to-new GUID map
    Dictionary<string, string> guidOldToNewMap = new Dictionary<string, string>();
    Dictionary<string, List<string>> guidsInFileMap = new Dictionary<string, List<string>>();

    // We must only replace GUIDs for Resources present in Assets.
    // Otherwise built-in resources (shader, meshes etc) get overwritten.
    HashSet<string> ownGuids = new HashSet<string>();

    // Traverse all files, remember which GUIDs are in which files and generate new GUIDs
    int counter = 0;
    foreach (string filePath in filesPaths) {
    if (!EditorUtility.DisplayCancelableProgressBar("Scanning Assets folder", MakeRelativePath(_assetsPath, filePath),
    counter / (float) filesPaths.Count)) {
    string contents = File.ReadAllText(filePath);

    IEnumerable<string> guids = GetGuids(contents);
    bool isFirstGuid = true;
    foreach (string oldGuid in guids) {
    // First GUID in .meta file is always the GUID of the asset itself
    if (isFirstGuid && Path.GetExtension(filePath) == ".meta") {
    ownGuids.Add(oldGuid);
    isFirstGuid = false;
    }
    // Generate and save new GUID if we haven't added it before
    if (!guidOldToNewMap.ContainsKey(oldGuid)) {
    string newGuid = Guid.NewGuid().ToString("N");
    guidOldToNewMap.Add(oldGuid, newGuid);
    }

    if (!guidsInFileMap.ContainsKey(filePath))
    guidsInFileMap[filePath] = new List<string>();

    if (!guidsInFileMap[filePath].Contains(oldGuid)) {
    guidsInFileMap[filePath].Add(oldGuid);
    }
    }

    counter++;
    } else {
    UnityEngine.Debug.LogWarning("GUID regeneration canceled");
    return;
    }
    }

    // Traverse the files again and replace the old GUIDs
    counter = -1;
    int guidsInFileMapKeysCount = guidsInFileMap.Keys.Count;
    foreach (string filePath in guidsInFileMap.Keys) {
    EditorUtility.DisplayProgressBar("Regenerating GUIDs", MakeRelativePath(_assetsPath, filePath), counter / (float) guidsInFileMapKeysCount);
    counter++;

    string contents = File.ReadAllText(filePath);
    foreach (string oldGuid in guidsInFileMap[filePath]) {
    if (!ownGuids.Contains(oldGuid))
    continue;

    string newGuid = guidOldToNewMap[oldGuid];
    if (string.IsNullOrEmpty(newGuid))
    throw new NullReferenceException("newGuid == null");

    contents = contents.Replace("guid: " + oldGuid, "guid: " + newGuid);
    }
    File.WriteAllText(filePath, contents);
    }

    EditorUtility.ClearProgressBar();
    }

    private static IEnumerable<string> GetGuids(string text) {
    const string guidStart = "guid: ";
    const int guidLength = 32;
    int textLength = text.Length;
    int guidStartLength = guidStart.Length;
    List<string> guids = new List<string>();

    int index = 0;
    while (index + guidStartLength + guidLength < textLength) {
    index = text.IndexOf(guidStart, index, StringComparison.Ordinal);
    if (index == -1)
    break;

    index += guidStartLength;
    string guid = text.Substring(index, guidLength);
    index += guidLength;

    if (IsGuid(guid)) {
    guids.Add(guid);
    }
    }

    return guids;
    }

    private static bool IsGuid(string text) {
    for (int i = 0; i < text.Length; i++) {
    char c = text[i];
    if (
    !((c >= '0' && c <= '9') ||
    (c >= 'a' && c <= 'z'))
    )
    return false;
    }

    return true;
    }

    private static string MakeRelativePath(string fromPath, string toPath) {
    Uri fromUri = new Uri(fromPath);
    Uri toUri = new Uri(toPath);

    Uri relativeUri = fromUri.MakeRelativeUri(toUri);
    string relativePath = Uri.UnescapeDataString(relativeUri.ToString());

    return relativePath;
    }
    }
    }