UnityPackages and the Asset Store

With the recent submission of SabreCSG 1.1 I’ve been looking a lot at the upgrade flow for Asset Store users, I’ve learned some interesting things I’d like to share.

The Problem

I recently launched a Download Centre for SabreCSG allowing existing customers to download beta builds, versions in submission and for completeness the last released version. When a version of SabreCSG is released on the Asset Store I download the unitypackage through the Asset Store and add it to the Download Centre (see here for where Asset Store packages are downloaded). For unreleased builds I create a Unity Package inside Unity (Assets -> Export Package) and add that.

One of the beta users noticed that when you installed the beta over the released version, Unity would print a bunch of exceptions relating to GUID mismatches and would struggle to import correctly. So I began digging into why this was happening.

Store Packages vs Custom Packages

Assets (including scripts and folders) are all given a unique identifier (GUID), which references are bound to. This allows you to rename and move assets and retain the references in your scenes and prefabs. By default Unity generates a meta file for every asset that contains information related to it, including its GUID.

When you import a package Unity will look to see if each file’s GUID already exist, if so it will update those files for you. If there is a file or folder at one of the specified paths in the package already but it has a different GUID then Unity will print a message saying there was a conflict, which can can issues.

By inspecting the GUIDs of the meta files I found that when I imported the custom package into a clean project multiple times all the GUIDs would be consistent and the same each time. When I imported the store package into a clean project multiple times I found that this wasn’t the case. All the files within the root Assets/SabreCSG folder would retain the same GUID, but the SabreCSG folder itself would have a different GUID on import. This was a problem as the custom package would come in with a specific GUID for that folder, causing a conflict.

Digging into the Unity Package Format

After a quick Google I found that a Unity Package is actually just a gzip compressed tar.

I decompressed the Unity Package by using the unix command:

The package extracts into a series of folders, each named with a different GUID. In each folder is a file named pathname that contains the relative path (for package folders this is the only file in the GUID folder). Assets also contain an asset file and an asset.meta file. There may also be a preview image icon too.

Once I had extracted both packages I ran a quick search for the path to the root SabreCSG folder:

As I suspected this returns one result in the custom package I’d produced myself in Unity and no results in the package I’d downloaded from the Asset Store.

Once I’d verified that store packages don’t include a GUID for the root folder but custom exported packages do, the solution was pretty simple – delete the GUID folder from the extracted custom package and repack it.

Once I’d deleted the folder I repacked it using:

I tested it again and hey presto! The custom package now imports correctly over the store package!

 

Ensuring GUID Consistency

That was the main problem I experienced, but I’d like to briefly mention how to ensure your GUIDs are consistent in Unity Packages more generally. If the above fixed all the GUID problems you were seeing you may not need to do the following and may be overkill in many cases.

If you submit to the Asset Store and export from the same project your GUIDs should generally be consistent. But there are certain cases where a GUID may change and it’s important to make sure that a file’s GUID is consistent in all packages to avoid conflicts. If you’re able to import the new package over the old package with no warnings or problems you probably don’t need to do this.

This is the workflow I use to recover GUIDs:

  1. Create a new project
  2. Import the Asset Store package (or last created package)
  3. Close Unity, then recursively delete all non-meta files from Assets

  1. Make a copy of the files I intend to add to the package in a clean folder elsewhere on disk
  2. Delete all the meta files from this duplicate by running

  1. Now copy the duplicate files over the original, this will result in an aggregate of the old package’s meta files matching against the new files.
  2. Now open Unity (it will cleanup any meta files for deleted assets).
  3. At this point you need to export the package, so go to Assets -> Export Package then repeat the instructions at this start of the post to strip out the root folder path.

Gotchas

Some things to remember with this method of recovering a previous package’s GUIDs:

  • New files will lose their GUID by step 5. This isn’t a problem if you use the last package before the new package as your source package each time as future unity packages will recover the new GUID
  • If you move files the meta file will be in the wrong place. Opening Unity will delete the old meta file and create a new one. If you have moved files it’s important to make sure the meta file is matched up before opening Unity again.

Leave a Reply