Shader Includes for Package Manager

So sometimes it is necessary to include a shader cginc from a package, e.g. when duplicating a shader that I want to make slight adjustments to.

Using #include pragma, when a “Package” was living in the project, it was possible to reference the relative path of that cginc file, like this:

#include "UnityCG.cginc"
#include "UnityUI.cginc" 
#include "../../../Plugins/TextMesh Pro/Resources/Shaders/TMPro_Properties.cginc"

(this is from a custom TextMeshPro shader in our project).

Now, with TMPro being a “package”, I can’t get that include line to work anymore.
I tried #include "TMPro_Properties.cginc" in the hope that somehow Unity is doing the same as for its internal shader includes for packages as well, but no luck.

So what is the recommended way to get my custom shader to work again? The TextMeshPro package is installed somewhere on the system, depending on user settings, etc., so what am I supposed to include so this shader works on any machine like before?

A workaround is to either:

  1. Install TMP from the asset store.
  2. Copy the shader and include it in your project files. Not 100% sure, but the shader compiler first looks for the include files in the location of the shader. Either way, if you’re using a custom .cginc you would have to include it in your assets, as any updates to the package would overwrite it.
  3. Wait until they implement package embedding:

Hi @fherbst ,

This is possible but this is yet to be documented. You have an example in the postprocessing package:

So the gist of it is to create a static function that adds new include paths for the shader compiler using the ShaderIncludePath attribute:

using System.Linq;
using UnityEngine;
using System.IO;

namespace YourNamespace
{
    static class TmpShaderIncludePath
    {
        [ShaderIncludePath]
        public static string[] GetPaths()
        {
            // This will add the text mesh pro package root path to the list of
            // shader compiler include paths. Adapt to go deeper in the package
            // folder tree.
            return new string [] {Path.GetFullPath("Packages/com.unity.textmeshpro")};
        }
    }
}

I’ve reached the TextMeshPro team so they add the shader include path automatically without users having to do it themselves.

Hope it helps,

Pascal

1 Like

@tswierkot

  1. Yes, we had the TMP package in the project before, but since Unity is moving in that “package management for everything” direction I’d rather give input on things that are tricky now than just work around :wink:
  2. unfortunately that only works with the simplest of shaders, since usually cgincs contain more necessary cgincs. So we’re back to (1) with that
  3. again, this goes kinda against the idea of the whole Package Manager for something where I want to extend, not replace, existing functionality

@okcompute_unity Thanks! That sounds great and very useful. Then how would I, without knowing where TMPro lives on disk, find the right include pathes? For me, the com.unity.textmeshpro folder in Packages does contain some folders, but all are empty. Is there some softlink magic going on internally?

@fherbst Yes, the package manager sits on top of a virtual file system that resolved the correct absolute path internally. This rule apply to any assets located in a package. You can reach for anything inside a package though the logical /Packages/<package name> root path.

Ok, that is very good to know!
Last question, I think then everything is covered: where on disk can I find these installed packages?

Packages are physically located in a global cache on your system.

On macOS, this is in /Users/<your usrname>/Library/Unity/cache/packages
On Windows, this is in C:\ProgramData\Unity\cache\packages

Note: this paths can change over time as we improve the system

I posted a related request here:

The Package Manager is a very useful tool that can provide even more future interesting features like dependency control but it would be great if it could follow a more transparent approach when deploying packages.

Hi @Kronnect ,

See @elbows answers in the thread you linked. They are all valid.

Unity’s goal is to be as much transparent as we can. For 2018.2, you’ll have the option to browse packages content/source directly from Unity.

Regards,

Pascal