Author Topic: ProceduralMaterial.isProcessing always returns true Unity 5.3.5  (Read 4010 times)

I'm having some frustration with isProcessing always returning true.
I think the issue occurred after the Unity 5.3.3p3 updates.

Is anyone else experiencing similar issues?
I read a similar thread from October last year but apparently this bug was resolved?
Has there been a relapse or is my project special :).

Really appreciate any help. Currently using some dodgy code to patch the leak.

Hey,

There have indeed been a few isProcessing issues fixed recently; Could you please provide some details:
  • What version of Unity you are using?
  • Does it occur in the editor, in a built player, or both?
  • A stripped down repro case

If a repro project is not an option, please provide at least snipplets of substance related code (RebuildTextures, SetProcedural*, ...) and most importantly the dodgy code used to patch the issue. This way we can try to reproduce the issue on our side.

Best,
Camille


Hi Camille,

As per the title I'm using 5.3.5, but I can confirm the issue was introduced for me with the changes made in 5.3.3p3 and remains all the way through to 5.3.5p3, everything works fine in 5.3.3p2.

I can't give you repro case scene but I can give you some code snippets.

IEnumerator UpdateMaterial()
    {
        while (true)
        {
        if (changesMade)
       {
                     ProceduralBody.RebuildTextures();

                     while (ProceduralBody.isProcessing)
                     {
                          yield return null;
                     }
                     changesMade = false;
                    ApplyLODTextures();
               }
           }
     }

So I have quite a few procedural material instances in the scene and I need to wait for isProcessing to finish before assigning them.
The above code works on PC both in editor and in built form in 5.3.5 (in spite of isProcessing always returning true, which is strange) however it fails on iOS.
So for now I'm using 5.3.3p2 for my iOS builds.

Hope you can help.

Thanks

I forgot to say my dodgy fix was to use "yield return new WaitForSeconds (0.8f);" intsead of isProcessing, alas this is of course not satisfactory as you have to set the delay to match your slowest supported device. Not to mention if you generate multiple instances at once textures invariably get assigned long before processing is finished, which makes for some very strange looking models.
Last Edit: June 14, 2016, 02:06:16 am

Thanks for the details.

I'll try to craft a repro project on my end and we will see how it goes. I have a few more questions:

  • Are there several MonoBehaviours with this coroutine running every frame? If so, how many?
  • How long does it typically takes fer the textures to be rebuilt?
  • How frequently is changesMade true? Would it happen to be true several frames in a row?
  • May I see what's inside ApplyLODTextures()? The important parts are how the material is accessed (renderer.sharedMaterial or renderer.material) and how the textures are set
  • What's the load behavior(s) ("Build on level load", "Bake and keep", ...) of your substance assets?

The reason it seems to work despite isProcessing being clumsy could be that once procedural textures are set to a material, when RebuildTextures() is done, textures already assigned to materials will be automatically updated.

Best,
Camille

I'll do my best to answer your questions.

1/ There are currently never more than 12 instances at one time, the co-routine only ever runs once on startup (so can run simultaneously for up to 12 instances) and then after that only if modifications are made by the player which can only ever effect one instance at a time.
2/One instance takes less than 0.2sec on a mediocre PC, but up to 1.5 sec on an iPhone 5S, or thereabouts.
3/As mentioned in the first answer, up to 12 simultaneously on start, and no more than once when players make changes after.
4/ I never use sharedMaterial as I want to keep the instances unique. Although I do use renderer.materials [] as there are more than one material ID that I'm applying to.

void ApplyLODTextures()
    {
        Texture SpecTrans = ProceduralBody.GetGeneratedTexture("Substance1_Specular");
        Texture Diffuse = ProceduralBody.GetGeneratedTexture("Substance1_Diffuse");
        Texture Normal = ProceduralBody.GetGeneratedTexture("Substance1_Normal");

        for (int i = 0; i < 4; i++)
        {
            if (i > 0)
            {
                LODs.materials[0].SetTexture("_Diffuse", Diffuse);   
                LODs.materials[0].SetTexture("_Normal", Normal);
            }
            if (i != 3)
            {
                LODs.materials[1].SetTexture("_SpecTrans", SpecTrans);   
                LODs.materials[1].SetTexture("_Diffuse", Diffuse);
               
            }
        }
    }

5/ My substances are set to "Build on level load and cache".

Hope that helps, thanks.
 

Thanks for all the details. I might have found your problem, but without a repro case I can't be sure.

To confirm this is the same problem, could you please try the following workaround? The idea is to create a clone of the ProceduralMaterial and then use only the clone for every other operations.

I edited your snippet to show how it is done:
Code: [Select]
    IEnumerator UpdateMaterial()
    {
        // Create a ProceduralMaterial instance. To do this properly we need a renderer in the scene.

        // Create a dummy gameobject and add a renderer to it
        GameObject go = new GameObject("Dummy renderer");
        MeshRenderer renderer = go.AddComponent<MeshRenderer>();

        // Assign ProceduralBody to material and access it to get a cloned ProceduralMaterial
        renderer.material = ProceduralBody;
        ProceduralMaterial ProceduralBodyInstance = renderer.material as ProceduralMaterial;

        // From now on, ProceduralBody is the original ProceduralMaterial, ProceduralBodyInstance the cloned one.
        // For the workaround to work, we want to use only the cloned one. Force this here:
        ProceduralBody = ProceduralBodyInstance;

        // Destroy the dummy renderer as we do not need it anymore
        Destroy(go);
       
        while (true)
        {
            if (changesMade)
            {
                Debug.Log("Changes made. Regenerating textures...");
                ProceduralBody.RebuildTextures();

                while (ProceduralBody.isProcessing)
                {
                    Debug.Log("wait...");
                    yield return null;
                }
                changesMade = false;

                Debug.Log("Is processing is now false!");
                // Assign textures here
            }
            else
                yield return null; // Don't forget to wait one frame if no change made
        }
    }

Best,
Camille

Thank you Camille, I'll give your code a go as soon as I get a chance and let you know how it goes.

And let me add, excellent support so far  ;D

Ok, so I've tried it and it almost works. The instance does finish processing and changes now update correctly but only for my material ID 1.
Material ID 0 does not update, I haven't had time to do more research, but presumably this is because Material ID 0 is still the original procedural material? No idea why the textures are not updating? Do you have any suggestions?
Out of interest, would you be able to clarify if this is a bug that will be fixed or is the workaround likely to be a safer more permanent solution?
Currently I'm happy to continue to use 5.3.3p2 since there are no new features or bug fixes that I need in later versions. However I'm sure this will change in the non too distant future.
Last Edit: June 16, 2016, 06:42:53 am

Thanks for the update!

Without the exact project this is hard to tell why only one material is updated; the most obvious things would be you are not using the cloned ProceduralMaterial either when rebuilding textures or when assigning them to your target material. An easy way to find this out would be to Debug.Log the ProceduralMaterial name. The cloned name should have a " (Instance)" suffix.

This is indeed a bug on our side. Without any repro case, I needed you to test the workaround to confirm we are experiencing the same issue.

This is by no means a permanent solution. We will fix this and it will eventually land in a future patch update. If 5.3.3p2 works for you, keep using it!

Best,
Camille

Thanks Camille, really appreciate the support. I know this stuff is difficult to estimate, but do you think a fix will make it in the next couple of weeks or are we looking at a month +.

Thanks again.

Hey,

I takes quite some time for fixes to land in public releases. I cannot give you any ETA, however to answer your question it probably won't take less than a month.
I'll keep this post updated!

Best,
Camille