Search Unity

Issue with Substance materials in WebGL

Discussion in 'Web' started by ypoeymirou, Jan 20, 2017.

  1. ypoeymirou

    ypoeymirou

    Joined:
    Jul 31, 2015
    Posts:
    54
    Hi,

    I am developing a 3D Asset viewer in WebGL.
    Aiming the tiniest possible size for my plugin, I do not put any data into it (except some small icons).
    I am using AssetBundles to download substance materials afterward, from a data server.

    Unity strips its unnecessary engine code when building the WebGL plugin.
    The tricky part is that Substance materials (class UnityEngine.ProceduralMaterial) are not “explicitly” supported in WebGL plugin, but are prebaked in some kind of “basic” material in WebGL context.
    So I have, in the code, to forbid myself to use UnityEngine.ProceduralMaterial class, only refer them as UnityEngine.Material class (would not compile in WebGL context).
    As side effect, when Unity strips the code at export, it does not keep anything from UnityEngine.ProceduralMaterial.

    And unfortunately, some code of it seems to be needed, because when loading a Substance material from an asset bundle, I get this error:

    Could not produce class with ID 0.
    This could be caused by a class being stripped from the build even though it is needed. Try disabling 'Strip Engine Code' in Player Settings.
    UnityEngine.AssetBundle:LoadAssetWithSubAssets_Internal(String, Type)
    UnityEngine.AssetBundle:LoadAllAssets(Type)
    UnityEngine.AssetBundle:LoadAllAssets()
    <LoadAssetCoroutine>c__Iterator0:MoveNext()
    UnityEngine.SetupCoroutine:InvokeMoveNext(IEnumerator, IntPtr)
    [/Users/builduser/buildslave/unity/build/Runtime/Serialize/PersistentManager.cpp line 1323]
    (Filename: /Users/builduser/buildslave/unity/build/Runtime/Serialize/PersistentManager.cpp Line: 1323)


    While UnityEngine.Material seems sufficient to set a pointer on the material, this only class is not enough to un-serialize the Substance material from the Asset Bundle.

    I tested 2 workarounds :

    1. Use link.xml approach ( “Issues with code stripping” section at https://docs.unity3d.com/Manual/webgl-building.html) to “preserve” the ProceduralMaterial classes when building the WebGL plugin:

    <linker>
    <assembly fullname="UnityEngine">
    <type fullname="UnityEngine.ProceduralMaterial" preserve="all"/>
    <type fullname="UnityEngine.ProceduralTexture" preserve="all"/>
    <type fullname="UnityEditor.SubstanceArchive" preserve="all"/>
    // Not sure it makes any sense as this is an Editor class which make no sense in WebGL plugin. Just tested with/without with pure irrational hope :)
    </assembly>
    </linker>


    Unfortunately, this specifically does not work on Substance materials classes.

    Also note that since 5.5.0, Unity seems able to bypass this file and deduce the needed classes by looking the assets bundles present in your project when building.

    Again, even with this approach, Substance materials classes are still not well preserved (while there is Asset Bundles with it in my project).​

    2. Keep a reference on a dummy Substance procedural material somewhere in the code.

    It works ! Code is not stripped during the plugin export.

    However, this causes an important issue, as the dummy material is a big offender for our core plugin size:

    1mb Assets/Materials/DummyProceduralMaterial.sbsar
    132.1 kb Resources/unity_builtin_extra
    64.6 kb Assets/Textures/UI/Icons/SampleModels/SampleModel_HalfSphere.png
    64.6 kb Assets/Textures/UI/Icons/SampleModels/SampleModel_Teapot.png
    64.6 kb Assets/Textures/UI/Icons/SampleModels/SampleModel_Sphere.png
    64.6 kb Assets/Textures/UI/Icons/SampleModels/SampleModel_Plane.png
    64.6 kb Assets/Textures/UI/Icons/SampleModels/SampleModel_Cube.png
    … and the scripts files …

    Most of data size (90% ?) is from the dummy material.​

    Does unity has plan to fix that ?

    Thanks by advance,

    Yvan
     
  2. Keston-Allegorithmic

    Keston-Allegorithmic

    Joined:
    Feb 21, 2017
    Posts:
    1
    Hey Yvan!

    I attempted to reproduce your issue but was unable to. Would you be able to send me a version of your project so I can take a closer look at it?

    Thanks,

    Keston
     
  3. jonas-echterhoff

    jonas-echterhoff

    Unity Technologies

    Joined:
    Aug 18, 2005
    Posts:
    1,666
    I think the problem here is that the SubstanceArchive class does not have a proper representation in managed UnityEngine code (since there is no runtime API to interact with it). Since the link.xml works on the managed code, it has nothing to whitelist the class on.

    But the proper solution here should be to use https://docs.unity3d.com/ScriptReference/BuildPlayerOptions-assetBundleManifestPath.html. You can pass a path to the asset bundle manifest in your build command, and then the build pipeline will make sure to include all classes needed by your asset bundles in the build.
     
  4. ypoeymirou

    ypoeymirou

    Joined:
    Jul 31, 2015
    Posts:
    54
    Thank you for your answer.

    Unfortunately your proposition does not fit our context as we don't have a manifest for asset bundles.

    We create and update via our cloud a huge library of asset bundles (15000+, growing every day), and we don't have a manifest.

    The viewer is independent of these bundles at build time.

    Of course, I can create a fake manifest including a dummy asset bundle with a substance material, and provide it at build time.

    Which is almost equivalent to the trick I do (assign a dummy substance material to a variable of my scene).

    The second one thought includes the dummy substance material asset in the build. As I reduced its size drastically, it does not really make a difference now.

    So at the end, the issue is no more relevant for us, we can live with the workaround.

    For the sake of the holy perfection :), this is just too bad to not be able to pilot it properly with link.xml, without using one of the 2 tricks.

    Thanks,

    Yvan