Skip to content

Instantly share code, notes, and snippets.

@ZimM-LostPolygon
Last active January 27, 2026 23:42
Show Gist options
  • Select an option

  • Save ZimM-LostPolygon/7e2f8a3e5a1be183ac19 to your computer and use it in GitHub Desktop.

Select an option

Save ZimM-LostPolygon/7e2f8a3e5a1be183ac19 to your computer and use it in GitHub Desktop.
Unity asset GUIDs regenerator
// 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",
"*.guiskin",
"*.fontsettings",
"*.controller",
};
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;
}
}
}
@davidluzgouveia

Copy link
Copy Markdown

Worked perfectly and saved my hide. Thanks a lot!

@makakaorg

Copy link
Copy Markdown

Cool.
But I want to choose target folder.

@SDJdasha

Copy link
Copy Markdown

It works !!!! Thank you !!!

@victorfisac

Copy link
Copy Markdown

It works like a charm! I though it wasn't going to change guids also in .unity data, but it was!
We are merging multiple projects that contains some shared assets with same guids :(

You have saved us tons of hours c211f55b838dbb73

@twobob

twobob commented Mar 3, 2019

Copy link
Copy Markdown

Appreciated. Hacked on it to update UMA Overlay Guids. Very helpful.

@geolands

geolands commented Aug 6, 2019

Copy link
Copy Markdown

I had issues using this with the latest version of Unity on Windows. Unity now marks .meta files as hidden which causes File.WriteAllText to throw an authorization exception when trying to write to them. The solution I found was to use stream writing instead and replace:
File.WriteAllText(filePath, contents);
with:
using (FileStream fs = new FileStream(filePath, FileMode.Open)) { using (TextWriter tw = new StreamWriter(fs, Encoding.UTF8, 1024, true)) { tw.Write(contents); } fs.SetLength(fs.Position); }
(Apologies for terrible formatting)
The issue appears to be that File.WriteAllText performs an implicit File.Exists style check which fails on hidden files. Using streams directly gets around that check.

@thesanketkale

Copy link
Copy Markdown

@ZimM-LostPolygon, thanks for sharing this wonderful and helpful script.

I had issues using this with the latest version of Unity on Windows. Unity now marks .meta files as hidden which causes File.WriteAllText to throw an authorization exception when trying to write to them. The solution I found was to use stream writing instead and replace:
File.WriteAllText(filePath, contents);
with:
using (FileStream fs = new FileStream(filePath, FileMode.Open)) { using (TextWriter tw = new StreamWriter(fs, Encoding.UTF8, 1024, true)) { tw.Write(contents); } fs.SetLength(fs.Position); }
(Apologies for terrible formatting)
The issue appears to be that File.WriteAllText performs an implicit File.Exists style check which fails on hidden files. Using streams directly gets around that check.

@geolands, I faced this same issue and using FileStream solved it. Thanks a ton for sharing the issue and the solution along with it. :)

@mpfaff

mpfaff commented Mar 24, 2020

Copy link
Copy Markdown

I'm facing an issue where after running this script, Unity scenes complain that their scripts cannot be found.

@famotril

Copy link
Copy Markdown

Hi, my projects do not have the route Assets/Editor, where it is supposed to be copied this script into my project?

@MostHated

MostHated commented Jul 27, 2020

Copy link
Copy Markdown

@famo

Hi, my projects do not have the route Assets/Editor, where it is supposed to be copied this script into my project?

You just create the folder if it does not exist and then put it in there. Right-click in the project => Create new folder => name it Editor.

@aakwewaanaqa

aakwewaanaqa commented Oct 27, 2020

Copy link
Copy Markdown

I found my unity project at 2019.4.0f1 Guid didn't have alphabet characters bigger and equal to 'g'.
Maybe it doesn't have to check Guid character from g to z, in the function of IsGuid(string text).

From

        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;
        }

to

        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 <= 'f'))
                    )
                    return false;
            }

            return true;
        }

@inertiave

Copy link
Copy Markdown

need assembly definition implementation. asmdef didn't be replaced to new guid

@onur-bakis

Copy link
Copy Markdown

THAAAAAAAAAAAAAAAAAAANKKSSSSSSSSSSSSSSSSSSSSSSSSSS !!!!!!!!!!!!!!!!!!!

@Devaniti

Devaniti commented Oct 5, 2022

Copy link
Copy Markdown

Still works as expected in Unity 2021 πŸ‘

@UmarHussain149

Copy link
Copy Markdown

I'm facing an issue where after running this script, Unity scenes complain that their scripts cannot be found . Unity version 2021.3.11f

@hoangledev

Copy link
Copy Markdown

Perfect!! It worked for me. Thanks a lot!

@magmukendi

Copy link
Copy Markdown

Thanks for sharing this.

@OskarFreestyle

Copy link
Copy Markdown

Absolutely grateful πŸ‘Œ

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment