Basically I’m in a situation where I have several projects which need to be merged into one, and the problem I have is that they share GUIDs between objects that are in fact unique to each project.
This is because when created, each project was copied from the last (along with the meta files), and then all the assets were then manipulated to suit that project.
I realise this pretty much goes against the whole purpose of GUIDs, but is there any way to force a GUID to be regenerated for a file while maintaining references to it? Even if I had to write a script that skimmed each scene file and manipulated the asset database I’d still be willing to try it.
Just faced the same problem and wrote my own tool to regenerate the GUIDs. It works from Unity Editor itself and replaces all GUIDs to random ones. It also takes care of not replacing GUIDs for built-in resources. I does not requires any additional files, so it is pretty much a one click tool.
To use it, call “Tools/Regenerate asset GUIDs” menu item. Of course, it requires Asset Serialization to be set to Force Text.
Hopefully this’ll come in use for somebody.
I followed the method Bunny83 recommended in the comments and wrote this C# program that will go through and regenerate all the GUID’s in a project and I successfully got it to work! (note, this is not a Unity script. I built and ran it through monodevelop on its own. I predict bad things might happen if you tried to modify the GUIDs while Unity is open and running)
Prerequisites:
Unity Pro is required, since this will only work if you set Asset Serialization to Force-Text and use visible .meta files.
Make sure there aren’t any folders with spaces in the name (such as Assets/Standard Assets/… you’ll have to replace the spaces with underscores or something). Filenames with spaces in them are OK.
I used grep and sort -u to get a list of all the GUIDs in my project. DO NOT mess with GUIDs that look like “0000000000000000e000000000000000” (the 17th character might be anything from 1-f). These do not refer to files in your project. It appears they refer to built-in unity assets or something like that.
BACK UP YOUR PROJECT
Be sure to delete the “Library” folder in your project before running
You might also want to close Unity before running this
using System;
using System.IO;
using System.Collections.Generic;
namespace UnityGUIDReplacer
{
class MainClass
{
public static void Main (string[] args)
{
MainClass m = new MainClass();
m.replaceGUID();
}
public void replaceGUID() {
//path to list of old GUIDs
string oldGUIDsPath = "/GUIDsUniq.txt";
//path to list of new GUIDs. You can generate them easily with System.Guid.NewGuid().ToString("N")
string newGUIDsPath = "/newGUIDs.txt";
//path to the list of files in which we want to alter GUIDs. These include all .meta, .mat, .prefab, and .unity files
string fileListPath = "/listOfFiles.txt";
//path to project
string pathPrefix = "/Users/.../UnityProjectFolder";
//build a dictionary out of the GUIDs
string[] oldGUIDsList = File.ReadAllLines(pathPrefix + oldGUIDsPath);
string[] newGUIDsList = File.ReadAllLines(pathPrefix + newGUIDsPath);
Dictionary<string, string> GUIDDict = new Dictionary<string, string>();
for(int i = 0; i < oldGUIDsList.Length; i++) {
GUIDDict.Add(oldGUIDsList_, newGUIDsList*);*_
* }* * //Get the list of files to modify* * string[] fileList = File.ReadAllLines(pathPrefix + fileListPath);* * foreach (string f in fileList) {* * string[] fileLines = File.ReadAllLines(pathPrefix + f);*
* for(int i = 0; i < fileLines.Length; i++) {* * //find all instances of the string "guid: " and grab the next 32 characters as the old GUID* _ if(fileLines*.Contains("guid: ")) { int index = fileLines.IndexOf("guid: ") + 6; string oldGUID = fileLines.Substring(index, 32); //use that as a key to the dictionary and find the value* * //replace those 32 characters with the new GUID value* * if(GUIDDict.ContainsKey(oldGUID)) {_ fileLines _= fileLines.Replace(oldGUID, GUIDDict[oldGUID]); Console.WriteLine(“replaced "” + oldGUID + “" with "” + GUIDDict[oldGUID] + "" in file " + f); } else Console.WriteLine("GUIDDict did not contain the key " + oldGUID); } } //Write the lines back to the file* * File.WriteAllLines(pathPrefix + f, fileLines); } } } }* After running, open Unity back up and it will reimport all of your assets. If everything worked properly, there shouldn’t be any broken prefabs and there won’t be any clashes between GUIDs from different projects that you are trying to merge. I ran it on a project with about 2000 files and it finished in a couple of minutes. Hopefully this is useful for somebody!_
I’ve done some additional modifications to the tool written by @ZimM to make it more generally useful.
It’ll now prompt for the folder or file with assets you want to regenerate, print out new guids in the logs, and prompt you before finally applying those modifications along with the number of files that will be regenerated.
Ok thanks to TonyLi and ricardo_arango it looks like packages are my best bet. In my head I was confusing packages with bundles, but they are indeed the best option here. Thanks!
Here is another submission for a workaround. It’s for *nix and Mac only though (unless you have cygwin on Windows).
You can find, replace, or generate randomGUIDs in your project.
Recommended usage is:
Generate random (./guid.sh random)
Verify it’s unique with find (./guid.sh find YOUR_NEW_RANDOM_GUID"
Replace existing GUID with newly generated random GUID (./guid.sh replace YOUR_CURRENT_GUID YOUR_NEW_RANDOM_GUID)
Like all the others here you need force text serialisation on your project and visible meta files.
Contents of guid.sh:
#!/bin/bash
find(){
if [ -z "$1" ]; then
help
exit 1;
fi
echo "Searching for GUID references..."
numFound=$(grep -rl $1 Assets | wc -l)
if [ $numFound -gt 0 ]; then
echo "Found $numFound matches for that GUID"
else
echo "GUID not found"
fi
}
replace(){
if [ -z "$1" ]; then
help
exit 1;
fi
if [ -z "$2" ]; then
help
exit 1;
fi
current=$1
new=$2
grep -rl --null $1 Assets | xargs -0 sed -i '' "s/$current/$new/g"
if [ $? -ne 0 ]; then
echo "There was a problem, consider rolling back."
else
echo "Your GUID has been replaced, restart Unity."
fi
}
random(){
# we sleep here because we can only use seconds on mac
# this helps keep it unique
sleep 1
echo $(md5 -qs "$(date +%s)")
}
# usage information
help(){
echo "GUID helper"
echo "This script can help find and replace GUIDs"
echo "as well as generate a random GUID"
echo
echo "WARNING: this can really mess with your project"
echo "make sure you have a backup"
echo "Before running replace make sure your new guid"
echo "does not already exist with the find funciton."
echo "Make sure that this script is run from the"
echo "project root!"
echo
echo "Functions: find, replace, random"
echo "Usage of find: ./guid.sh find YOUR_GUID"
echo "Usage of replace: ./guid.sh replace YOUR_CURRENT_GUID YOUR_NEW_GUID"
echo "Usage of random: ./guid.sh random"
}
# if no arguments passed then show help
if [ ! $1 ]; then
help
exit 1
fi
# call arguments verbatim
$@
Just put that in a file named guid.sh in your project root and march it as executable with