Monday, March 25, 2019

Custom Local Packages - Unity Package Manager


At Taqtile we are big proponents of re-using our code base across multiple projects.  In the past I wrote about how to share code between Unity projects via SymLinks.  The main problem with that solution to sharing code is that it is not supported by Unity.  It works fairly well for code but issues can arise when you try to share prefabs/assets as guids can conflict across projects.  We put up with it though because it was the best solution we could find to bring in external code. Until now that this is!

Unity 2018.3 and 2019.1 are bringing big changes to how Packages work in Unity.  I currently have a use case of needing to bring in an extension from the Mixed Reality Toolkit (MRTK).  Currently extensions reside in a sub directory within the MRTK library.  I haven't ported our projects over to MRTK yet so I don't want to bring in the entire library into my project; therefore, in this blog post I'll be exploring how to bring just the extension into my project using local Packages rather than symlinks.

Benefits
The main benefit of using packages instead of symlinks is that it is supported by Unity.  In theory, you should be able to bring in all types of assets without guid conflicts.

The main benefit of using packages instead of asset bundles is that you do not need to export the code.  You set it up once and then all future changes should be handled by the package manager.


Unity 2018.3 Solution
The ability to bringing in custom local packages was added in 2018.3, but it has limitations and is not documented.

The best documentation I could find for it can be found in this forum thread.  It goes into further detail than I will here but it states the package manager supports bringing in packages directly from git, the web, and local files.



Git is very interesting but it currently does not cache results and each time a change is made you would have to re-clone the entire library.  That is a deal breaker for me as speed during development is important. I'm also curious if git support would allow pulling in sub directories like my current use case or if I would have to pull in the entire MRTK.

For my immediate use case, I'll be focusing on the file scheme.  To get the file scheme to work you need to do two things:

1. Create a package.json in the directory you would like to share.  The package.json should have the following format:

{
 "name": "com.mrtk.webrtc",
    "displayName": "MRTK WebRTC Extension",
    "version": "0.0.1",
    "unity": "2018.3",
    "description": "Add description here",
    "keywords": ["key X", "key Y", "key Z"],
    "category": "MRTK Extension",
    "dependencies": {
    }

}

In my use case I placed the package in the following directory:
MixedRealityToolkit-Unity-WebRTC\Assets\MixedRealityToolkit.Extensions\Webrtc


2. Add a link to that package as a dependency in your manifest.json of the project you would like import the code into. The manifest.json can be found in the Packages folder of your project. Here is an example:

{
  "dependencies": {
    "com.mrtk.webrtc": "file:../../MixedRealityToolkit-Unity-WebRTC/Assets/MixedRealityToolkit.Extensions/Webrtc"
   }
}

Each entry is "package name": "path".  Note the "file:../../".  This allows everyone at Taqtile to use this solution without requiring each PC to have the same file structure.

There is also a button in the package manager that allows you to select your local package.json and import it directly to your manifest.json.  I thought this was only a Unity 2019.1 feature as I saw no mention of it in the forums but I noticed it while taking comparison screenshots.

If you use the + symbol in the UI to import your package then you may need to check the manifest.json after doing so because the path it filled in was absolute for me.




Unity 2019.1 UI Improvements
Note the new placement of the plus button:








The Future and Beyond
It appears Unity is going to continue adding features to the package manager to make this more robust and user friendly. The ability to select/manage local versions as well as nuget integration were the two most exciting offerings I saw mentioned as possible road map features.  No promises though.