Author Topic: [BUG] Substance Plugin errors when exiting Play mode in Unity Editor  (Read 2200 times)

With version 2.4.4 of the Substance Unity plugin and Unity 2019.3.1f1, I am receiving the following error in the editor console upon exit from Play mode:

NullReferenceException: Object reference not set to an instance of an object
Substance.Editor.EntryPoint.NeedsReImport (System.String pPath) (at <c84dad347d4b4c7c97bcf77c1e11b982>:0)
Substance.Editor.EntryPoint.HandleAssignedTextures () (at <c84dad347d4b4c7c97bcf77c1e11b982>:0)
Substance.Editor.EntryPoint.StateChange (UnityEditor.PlayModeStateChange state) (at <c84dad347d4b4c7c97bcf77c1e11b982>:0)
UnityEditor.EditorApplication.Internal_PlayModeStateChanged (UnityEditor.PlayModeStateChange state) (at <c10752821eec4acbb89ccd53fbbc5e27>:0)


Double-clicking the message does not link to anything in the hierarchy or project tabs, so this seems to be something global to the plugin rather than triggered by a specific object. All of my materials seem to be unaffected by the error, so if it's trying to tell me one of them needs to be reimported, I am not sure which one.

same for me

NullReferenceException: Object reference not set to an instance of an object
Substance.Editor.EntryPoint.NeedsReImport (System.String pPath) (at <c84dad347d4b4c7c97bcf77c1e11b982>:0)
Substance.Editor.EntryPoint.HandleAssignedTextures () (at <c84dad347d4b4c7c97bcf77c1e11b982>:0)
Substance.Editor.EntryPoint.StateChange (UnityEditor.PlayModeStateChange state) (at <c84dad347d4b4c7c97bcf77c1e11b982>:0)
UnityEditor.EditorApplication.Internal_PlayModeStateChanged (UnityEditor.PlayModeStateChange state) (at <9a184ab867bb42c296d20ace04f48df3>:0)

Got it too. Won't bother posting a log because it's identical to the other two posts above.

With version 2.4.4 of the Substance Unity plugin and Unity 2019.3.1f1, I am receiving the following error in the editor console upon exit from Play mode:

NullReferenceException: Object reference not set to an instance of an object
Substance.Editor.EntryPoint.NeedsReImport (System.String pPath) (at <c84dad347d4b4c7c97bcf77c1e11b982>:0)
Substance.Editor.EntryPoint.HandleAssignedTextures () (at <c84dad347d4b4c7c97bcf77c1e11b982>:0)
Substance.Editor.EntryPoint.StateChange (UnityEditor.PlayModeStateChange state) (at <c84dad347d4b4c7c97bcf77c1e11b982>:0)
UnityEditor.EditorApplication.Internal_PlayModeStateChanged (UnityEditor.PlayModeStateChange state) (at <c10752821eec4acbb89ccd53fbbc5e27>:0)


Double-clicking the message does not link to anything in the hierarchy or project tabs, so this seems to be something global to the plugin rather than triggered by a specific object. All of my materials seem to be unaffected by the error, so if it's trying to tell me one of them needs to be reimported, I am not sure which one.

Hey guys, this is a known issue related to Unity changing stuff within 2019.3. We have a ticket in for this. It is an annoying error but shouldn't affect anything with using the plugin. Sorry for the inconvenience. :(

hi @keston ,
any info on this bug ?

 still occurs with :
Version 2.4.5(current)
Released: Apr 6, 2020

it does have an impact for us, as we also use the PlayModeStateChanged event from Unity and because substance is raising an exception, our code does not get called :p

hi @keston ,
any info on this bug ?

 still occurs with :
Version 2.4.5(current)
Released: Apr 6, 2020

it does have an impact for us, as we also use the PlayModeStateChanged event from Unity and because substance is raising an exception, our code does not get called :p

@Gilles Boulard 0 ,

Hmm really? What version of Unity are you using? Not seeing it on my end, can you provide more info on the project/substance files you are using? :)

using Unity 2019.3.6f1

just installed the substance unity plugin, without any substance file yet (starting project ;) )

using Unity 2019.3.6f1

just installed the substance unity plugin, without any substance file yet (starting project ;) )

@Gilles Boulard 0 ,

Ok, thanks for the info! Will look into this and enter a ticket. Sorry for the inconvenience in the meantime. :(

Hey @keston , is there any eta on when you'd expect this to be fixed?

Cheers

Hey @keston , is there any eta on when you'd expect this to be fixed?

Cheers

@cconlan ,

no ETA at the moment. :( but it is in our ticket system, and the devs are aware of it.

Mine shows some buildslave folder level, I had emailed support on this but they said to use the forums, found this thread, so at least I know its not just me with this problem.

NullReferenceException: Object reference not set to an instance of an object
Substance.Editor.EntryPoint.NeedsReImport (System.String pPath) (at <6eb3a9c8c00040b3b2268174f75d20ae>:0)
Substance.Editor.EntryPoint.HandleAssignedTextures () (at <6eb3a9c8c00040b3b2268174f75d20ae>:0)
Substance.Editor.EntryPoint.StateChange (UnityEditor.PlayModeStateChange state) (at <6eb3a9c8c00040b3b2268174f75d20ae>:0)
UnityEditor.EditorApplication.Internal_PlayModeStateChanged (UnityEditor.PlayModeStateChange state) (at
C:/buildslave/unity/build/Editor/Mono/EditorApplication.cs:405)

Also have this issue.  It's unfortunately preventing the editor from running my own code when PlayMode is stopped - ie. restoring my scene/hierarchy to the state it was in before I hit play.  This is pretty frustrating.


So did some debugging, it doesn't seem hard to fix...

The issue is in this code snippet of Substance.Editor.EntryPoint:

Code: [Select]
    public static void HandleAssignedTextures()
    {
      foreach (Material material in Resources.FindObjectsOfTypeAll<Material>())
      {
        string assetPath = AssetDatabase.GetAssetPath((UnityEngine.Object) material);
        if (assetPath != "" && assetPath != "Resources/unity_builtin_extra" && (assetPath != "Library/unity default resources" && assetPath != "Library/unity editor resources") && (!assetPath.ToLower().EndsWith(".sbsar") && EntryPoint.NeedsReImport(assetPath)))
        {
          Debug.Log((object) ("Importing: " + assetPath));
          EditorUtility.SetDirty((UnityEngine.Object) material);
          AssetDatabase.ImportAsset(assetPath);
        }
      }
    }

The root problem lies in the objects that get returned for:
Code: [Select]
Resources.FindObjectsOfTypeAll<Material>())

The issue is that for whatever reason, Unity is returning back not just materials (.mat) but also (.asset) files. 
In my particular case, it's returning back  "Assets/TextMesh Pro/Resources/Fonts & Materials/LiberationSans SDF.asset".

Therefore, when the code tries to run the EntryPoint.NeedsReImport(assetPath) on the .asset file:
Code: [Select]
    public static bool NeedsReImport(string pPath)
    {
      bool flag = false;
      Material material = AssetDatabase.LoadMainAssetAtPath(pPath) as Material;
      for (int propertyIdx = 0; propertyIdx < ShaderUtil.GetPropertyCount(material.shader); ++propertyIdx)
      {
        if (ShaderUtil.GetPropertyType(material.shader, propertyIdx) == ShaderUtil.ShaderPropertyType.TexEnv)
        {
          string propertyName = ShaderUtil.GetPropertyName(material.shader, propertyIdx);
          Texture texture = material.GetTexture(propertyName);
          if (!((UnityEngine.Object) texture == (UnityEngine.Object) null) && AssetDatabase.GetAssetPath((UnityEngine.Object) texture).ToLower().EndsWith(".sbsar"))
          {
            flag = true;
            break;
          }
        }
      }
      return flag;
    }

Because the asset is not a Material, it dies trying to access the material.shader property.

The simplest thing to do is to check the objects that get returned from Resources.FindObjectsOfTypeAll<Material>() to filter out objects that do not belong to the Material type.   Seems a bit redundant as I'm not sure why TMP_FontAssets are even coming back when it's not a Material.  It looks to be a ScriptableObject ultimately.






For people who don't want to wait for a fix... as it seems like it's been months for nothing to happen when it's literally a couple of lines to fix.

You can apply a Harmony patch:
* Download Harmony (really cool tool!) - https://harmony.pardeike.net/#documentation
* Copy the following code to your Unity project and it will load automatically:

Code: [Select]
     [InitializeOnLoad]
    public class SubstancePatchLoader {
        static SubstancePatchLoader() {
            var harmony = new Harmony("SubstancePatches");
            harmony.PatchAll();

            Debug.Log("Loaded Substance Patches.");
        }
    }

    [HarmonyPatch(typeof(EntryPoint), "NeedsReImport")]
    class SubstanceEntryPointPatch {
        static bool Prefix(ref bool __result, string pPath) {
            var obj = AssetDatabase.LoadMainAssetAtPath(pPath);

            if (obj is Material) {
                return true;
            }

            __result = false;
            return false;

        }
    }

The patch is simple - it adds a Prefix method (basically a method that gets run before the actual method gets run) and uses the path string passed into the original method and loads the Asset.

If the loaded object is a Material object, it will allow the actual method to run as normal.
If the loaded object is not a Material object, it will prevent the original method from running (the return false does this) and it will return back a false value back to the caller.  (The thinking being, if it's not a Material object then it doesn't need to be reimported).

Hope it helps other people.

I also patched the Substance.MaterialEditor issue where it spews console log errors when trying to access the Material/Shader properties of code-instantiated materials (ie. not saved as an asset in the file system).  If you want that one, I can also share it.




For people who don't want to wait for a fix... as it seems like it's been months for nothing to happen when it's literally a couple of lines to fix.

You can apply a Harmony patch:
* Download Harmony (really cool tool!) - https://harmony.pardeike.net/#documentation
* Copy the following code to your Unity project and it will load automatically:

Code: [Select]
     [InitializeOnLoad]
    public class SubstancePatchLoader {
        static SubstancePatchLoader() {
            var harmony = new Harmony("SubstancePatches");
            harmony.PatchAll();

            Debug.Log("Loaded Substance Patches.");
        }
    }

    [HarmonyPatch(typeof(EntryPoint), "NeedsReImport")]
    class SubstanceEntryPointPatch {
        static bool Prefix(ref bool __result, string pPath) {
            var obj = AssetDatabase.LoadMainAssetAtPath(pPath);

            if (obj is Material) {
                return true;
            }

            __result = false;
            return false;

        }
    }

The patch is simple - it adds a Prefix method (basically a method that gets run before the actual method gets run) and uses the path string passed into the original method and loads the Asset.

If the loaded object is a Material object, it will allow the actual method to run as normal.
If the loaded object is not a Material object, it will prevent the original method from running (the return false does this) and it will return back a false value back to the caller.  (The thinking being, if it's not a Material object then it doesn't need to be reimported).

Hope it helps other people.

I also patched the Substance.MaterialEditor issue where it spews console log errors when trying to access the Material/Shader properties of code-instantiated materials (ie. not saved as an asset in the file system).  If you want that one, I can also share it.

Hi Integrations PM here! This is an interesting suggestion but one we would not recommend as it would disable our team to assess and repro bugs that would be reported with the externally altered code.

I'm sorry its taken some time to resolve the bug - we do have the fix in for our upcoming release (v. 2.5.2) which is in QA now and then will be with beta testers for about a week.

We do not have a quick release cycle at the moment and we are taking steps to give patches faster. Our team is small and managing the release process as it is today, along with shifting to a new one has been a challenge. For now, look for the new drop (2.5.2) to be on the asset store by end of next week but if you'd like to be a part of the beta group please reach out to me.
Substance Integrations Product Manager