Search Unity

TMP breaks and appears like white text on mobile ? (loaded from bundles)

Discussion in 'UGUI & TextMesh Pro' started by JonnyHilly, Aug 16, 2018.

  1. JonnyHilly

    JonnyHilly

    Joined:
    Sep 4, 2009
    Posts:
    749
    Have been using TMP for a while... works great.... except when loading prefabs from Asset bundles that use TMP distance field with multiple features enabled.

    For iOS and Android... Bundles are built per platform. Unity 5.6.3p4 pro
    Aim is to have a Distance Field font with outline and yellow/brown texture gradient.

    for the test font/material... DistanceField shader, with texture gradient, and outline....
    if not loaded from bundle.... works fine on mobile devices
    if loaded from bundle.... text is readable.... but appears flat white, with no gradient visible

    Have tried hack fix script to get shader name from material, search for shader and re-apply it... this fix works in one loaded bundle, but not in another loaded bundle.

    Its still rendering semi ok with some kind of TMP shader... as you can still see the text.... its not a white or pink box.... but not fully working either. it appears as flat white text.
    DF shader has a fallback to DF mobile... so tried mobile version instead...
    Tried using DistanceField "mobile" shader.... With Color gradient instead of texture gradient, same result... text appears white, but the color gradient is still applied (assume this is just vertex color on the mesh, so it still works)

    Tried including the shader, material, gradient texture in the bundle..... still doesn't work.
    Tried forcing DF and DF-mobile shaders to be included with the build... still doesn't work
    Tried a shaderVariantCollection still doesn't work.

    One other strange thing.... using same shader, without outline, but with shadow.... renders partially properly with the gradient, but the shadow is missing.

    One more test.... loaded the bundle that does show the text properly with the hack fix script FIRST. then loaded the bundle with the broken un-fixable text, (to possibly help unity find the shader...) and the rendering got worse... it turned from white text, into pink squares.

    I'm out of ideas... has anyone else seen this ?
    How do I get DF shader to work on mobile from a bundle.... with both outline and gradient please ?
    Is it still rending with a TMP shader, or some unity fallback that can still render a DF font ?

    Help appreciated, Cheers in advance
     
    Last edited: Aug 16, 2018
  2. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    Most likely this is the result of the shader keywords / features being disabled. Based on user feedback, it appears best to not include the shaders in the bundle and to reconnect / re-assign the appropriate shader when the bundles are loaded. See the following post and linked thread.

    The white blocks of text are usually a sign of the scale of the text object not being uniformed (x, y, z) using same value or the scale X and Y in the debug section of the material inspector being something other than 1. The scale x and y being wrong in on the material is potentially related to the shader re-assignment as noted above.

    By the way, white squares is indicative of scaling issue with regards to the object uniform scale or scale X and Y on the material / shader. Pink squares indicates a shader error / issue (ie. not just some wrong values).
     
  3. JonnyHilly

    JonnyHilly

    Joined:
    Sep 4, 2009
    Posts:
    749
    Hi Stephan, thanks much for your reply.
    We are mostly actually not getting white or pink squares... the main problem is what looks like TMP text, its still readable text, but loses most of the desired features, and turns into plain white TMP text. For example, the gradient texture, stroke, and shadow will all disappear (or be flat white... everything is flat white)
    I am thinking along the same lines as you at the moment, about enabling and disabling shader keywords.
    I've tried re-applying shader, after searching for shader by name from the information in the material, but suspect there may be more than one shader with the same name... due to the conditional shader keywords... so the fix script can't always find the right shader.... just a guess.
    Still trying....
    Cheers!
     
  4. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    When the prefab is loaded from the bundle, just check what shader and material is assigned to it. You should be able to inspect that object / material to see whether or not the shader keywords / features are enabled. If you set the inspector to debug mode, you can see what shader keywords are enabled on the material.
     
  5. JonnyHilly

    JonnyHilly

    Joined:
    Sep 4, 2009
    Posts:
    749
    Thanks, I may have to add a bunch of logging.... everything works fine in editor, its on iOS and droid devices that it breaks... and I can never connect to device with debugger...

    I tried copying the TMP shader to a new shader, removing all the keywords and optional parts... just keeping the features I wanted built-in and hard coded turned on.... With a different unique shader name.... added this to the bundle also, and also to a shderVariantCollection(also added to bundle) but still same result.... works in editor, broken on device. sigh....
     
  6. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    What shader are you using in the Editor?
     
  7. JonnyHilly

    JonnyHilly

    Joined:
    Sep 4, 2009
    Posts:
    749
    TMP Distance field. or TMP Distance_field_mobile
    if I add color with vertex color it works fine on device.
    if I add vertex gradient, that works fine.

    If I add drop shadow... the vertex gradient appears ok, but with no drop shadow on device.
    If I add texture gradient and stroke... neither appear on device, just plain white.

    So I can make it look ok on device. but the art team wants that shadow and stroke...

    The new (hacked) shader I made, was a copy of TMP Distance Field , with all the #if's removed. built-in shadow and stroke.
    With TMP_UGUI script

    If it helps this is across all devices... high to low spec, unity 5.6.3p3 , iOS and droid
     
  8. JonnyHilly

    JonnyHilly

    Joined:
    Sep 4, 2009
    Posts:
    749
    maybe its the material ? if the same material is used in different bundles... but in the other bundle it has different TMP settings.... does TMP re-compile the shader ?... or something weird like that. maybe unique materials would help. will try that. (though my hacked shader should have prevented this possibility somewhat) maybe sharing materials across bundles is a bad idea.. unity gets confused with refs or something ? though again.... everything else seems to work except this TMP shader with certain features enabled. hmmm
     
  9. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    You should not have to create / hack a shader. The existing TMP shaders should work fine.

    To rule out any potential shader issues, create some test scene using one of your font asset with material presets but without the use of Asset Bundle. Make sure this works as expected with all the visual effects you need.

    If this works then the issue is solely related to Asset Bundles and having the appropriate material / shader assigned to your text objects.

    When you create these bundles, do not include the shaders. You can re-assign the appropriate material and shader once the bundles are loaded.
     
  10. JonnyHilly

    JonnyHilly

    Joined:
    Sep 4, 2009
    Posts:
    749
    Hi Stephan, thanks for your reply, yes we have already done most of those things.

    The shaders work fine in editor, and on devices as long as they are not in a bundle.

    If TMP is in a bundle that is included with the build they also work fine.

    But...If they are in a bundle that is 'downloaded' to device, then the problems occur.

    Initially we did all this without doing anything special with the bundles... (shaders were not included with any of the bundles when the problems occurred, we are only trying including them within the bundle as a possible solution.

    We saw others had similar problems on the forums and that possible solution was to use shader name to re-apply the shader at run time. Though note... the shader is already there... its not a white or pink square... its still rendering as some kind of depth field TMP text shader. Text is still readable, just plain white

    We already had problems with TMP from other bundles and fixed those issues using a runtime script that searched for shader by name, from the material info, re-applied the shader. This worked in one bundle.

    In the current new bundle, that script does not work to fix the problem. So we tried solutions suggested by unity docs and by others in forums.... such as including shaders in bundles or shader variant library, or forcing shader to be included in the build etc.... but shader seems to be there, just wrong features or confused settings.

    There is one thing you said in that last sentence we have not tried yet, which is to re-apply the 'material'. We have only tried re-applying the shader, after looking through the renderers for shader names. We will try making the material unique to that one test Text/Ui re-bundle and re-build.... I'll post results later..... will take a while. Thanks much for the help
     
    Last edited: Aug 19, 2018
  11. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    Let me know if it does look like the correct material is assigned via the bundles.

    If the issue is only related to shader keywords, these can be re-enabled manually as the resources are loaded.
     
  12. JonnyHilly

    JonnyHilly

    Joined:
    Sep 4, 2009
    Posts:
    749
    ok from the logs.... it looks like the material I assign onto TextMeshProUgui script... is not the one found on the Renderers on the same object when trying to run the fixit script, to re-assign shaders...

    In Editor....
    TextMeshProUgui has an exposed variable "Material" I assign my test material..... AdventuringLatinSDF_WhiteWOpaqueGreenShadowTEST
    In inspector debug mode, there is also another slot called Shared Material... Which for some Text seems to be different from the assigned material. I have assigned to to my same material AdventuringLatinSDF_WhiteWOpaqueGreenShadowTEST.
    This material I also have a custom (altered version of the TMP DistanceField shader with a Unique name_ 'DF_underlay')

    On Device
    The Fix it script (that searches for renderers and canvas Renderers, on this same text object to re-assign missing shaders) is where I added logs.
    It prints the object name, the name of materials it finds, and the shader name this it tries to replace/swap out. So I'm expecting it to find my material and shader mentioned above...
    However what it logs for the material and shader is the material that is in the Font Asset, and shader Tmpro_DistanceField.
    So I'm not sure exactly how this is supposed to work. But there seem to be 3 material slots and 2 shaders at play, where I am expecting 1 material and 1 shader.
    Does TextMeshProUgui copy the material and shader from the font, and replace what is assigned ? maybe this is the problem ?
    Should I make a Unique font asset per bundle... something sketchy going on here
     
  13. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    As per a long established convention in Unity, accessing / assigning a material to the .material property will result in an instance of that material being created. Whereas using shared material, will simply assign / use the same material which might be shared between several objects.

    As such you want to make sure you are assigning your material presets to the shared material property otherwise, you are getting new instances of material on each text object.

    This is the result of your assignment of the material via the .material property.
     
  14. JonnyHilly

    JonnyHilly

    Joined:
    Sep 4, 2009
    Posts:
    749
    Thanks again for response,
    yes I understand material and shared material, but why does fixit script find the material from the font asset? And not the .material or .sharedMaterial on the object’s renderer.
    And does that explain why it is white?

    ...at a guess... its not using the preset material, it is just using the base material built into the font asset, which is of course... all plain white....
    ...also guessing the fixit script, then does nothing.... as it just finds the font asset's material and shader on the renderer... which are already working just fine in this case. So searching and replacing and renderer.material.shader does nothing.

    So coming full circle maybe... though with a bit more understanding than when I started... looks like a problem with the preset, when coming from bundle, either not being used, or getting lost... My fixit script doesn't account for this possibility or log anything from tmp script.... (it searches renderers on the object and canvas) So I'll add some more logging specific to the preset material and TMPugui
     
    Last edited: Aug 20, 2018
  15. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    JonnyHilly likes this.
  16. JonnyHilly

    JonnyHilly

    Joined:
    Sep 4, 2009
    Posts:
    749
    Thanks, yes the fixit script only reads from "SharedMaterials" found in any Renderers on the text gameObject
    However it does also try to fix material from CanvasRenderer which doesn;t have a "sharedMaterial" property, only a
    Material mat = canvasRenderer.GetMaterial(i);
    Would this cause problems ?

    But even so, wouldn't explain why its broken when no fixit script is present.

    Is potential soln here, just to make more unique FontAssets, instead of applying presets on the TMPugui script ?
    ...I'll answer my own question.... looks like a No. the asset includes the atlas, so would waste a bunch of space.

    Is there anything I can do with Material / SharedMaterial slots to make sure they are correct? Should I set them both to none, then drag in the preset just into the Material slot ?
     
    Last edited: Aug 20, 2018
  17. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    Any chance you can provide me with a simple repro project that would enable me to reproduce the issue you are running into? See if you can reproduce this in a new project with a single text object in a bundle.

    I'll be more than happy to take a look as I think the scanning process / fix might be introducing additional issues.
     
  18. JonnyHilly

    JonnyHilly

    Joined:
    Sep 4, 2009
    Posts:
    749
    ok got some useful info....

    Note:- in this version the fixIt script is disabled. All it does is log information. It doesn't try to replace any shaders.

    So in editor, all the logs look as expected.... preset material is in the TMPugui->material slot. and the preset material is also the material on the Renderer.
    (the shader is TextMeshPro/DistanceField)

    Once loaded from a bundle, (currently testing on iOS device), on a broken font object. The correct material is still there in the preset slot, but the material's shader's name is now "Hidden/InternalErrorShader"
    also the material on the Renderer has changed to the Font Asset's material. not the preset material.


    So it looks like the Preset material loses the shader... From there, I'm guessing TMP detects this problem and replaces the renderer with the Font Asset's renderer (or maybe its there as a default)
    Hidden/InternalErrorShader
    My FixitScript can't fix the missing shader material on that renderer, as the Material on it is not the broken one.
    Plus even if the correct material was there.... the original shader name is gone, and replaced with "Hidden/InternalErrorShader" which I can;t search for and find....

    So making some progress.... Still not sure what breaks things... apart from guessing still to do with unity referencing issues across multiple bundles. and no easy clear fix script if the shader name is gone.

    Might be able to have a public field with string for desired shader to search for, but not too clean, and shader still might not be find-able...


    this sounds similar... but specified fix (put shaders in /resources/ folder) is already setup that way for TMP's shaders
    https://github.com/jonlab/NewAtlantis/wiki/Shader-included-in-an-AssetBundle
     
    Last edited: Aug 20, 2018
  19. JonnyHilly

    JonnyHilly

    Joined:
    Sep 4, 2009
    Posts:
    749
    I'm pretty sure its not the scanning/fix process as we implemented that after the problem started. The problem started after we started moving parts of the project over to loading from asset bundles.

    I'll chat with the guys here, but building a project to send might be hard to manage at the moment. Thanks for all your help and for offering to look though.
     
  20. JonnyHilly

    JonnyHilly

    Joined:
    Sep 4, 2009
    Posts:
    749
    One other thing I noticed... might not be relevant... I previously manually added TMP shaders into our Core Bundle that is included with the build.... I just tried removing them all again. but asset bundle manager auto puts them back again with an exclamation mark... and lists all the other bundles that it is duplicated in. Warning us that there will be asset duplication. so for example TMPro_SSDF is in 6 bundles... plus also in the TMPro/resources folder. I think this is expected unity behaviour, but could be a source of some troubles
     
    Last edited: Aug 21, 2018
  21. JonnyHilly

    JonnyHilly

    Joined:
    Sep 4, 2009
    Posts:
    749
    Note:- I can detect when the desired renderer material is wrong, but I cant find easy way to set material back into TMPugui... seems to be read only getter and complex generation of material or fallback beneath the scenes. ? any suggestions ?
     
  22. JonnyHilly

    JonnyHilly

    Joined:
    Sep 4, 2009
    Posts:
    749
    maybe useful to some http://digitalnativestudios.com/forum/index.php?topic=878.msg11814#msg11814

    is there a way to call into a function in TMPugui script... to set the Preset Material and/or Render material at run time ? Material property seems read only in the source code, there is only a getter, no setter ?

    If I can do this, I can maybe find the material and shader in separate script and pass in correct material. The usual method of searching renderers for shader from material.shader.name doesn't work, due to TMP changing the material to the base material in the font asset.
     
  23. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    You should not have to do any of that.

    Each text object has a reference to a font asset and fontMaterial (which will create an instance) and fontSharedMaterial. So when loading the bundle, the only property that should need to be re-assigned (and only if the connection was broken) is the fontSharedMaterial.

    What references on the objects being loaded via bundles are getting lost? Is it the reference to the material or the shader used by that material?
     
  24. JonnyHilly

    JonnyHilly

    Joined:
    Sep 4, 2009
    Posts:
    749
    Thanks again...
    I'll give tmp.fontSharedMaterial a go

    From logs it looks like the preset material's shader name is "Hidden/InternalErrorShader" and the Render Material, is no longer matching the expected preset material (like it does in editor), but the material from the FontAsset

    Pretty much it has the assigned preset material, but not the DF shader in the Preset.
    Even if I find and fix the missing shader and assign it back to the preset, it happens too late I think. it makes no difference to what TMP is using to render by this point TMP has built its fallback material. and uses that.

    please see post above on Monday 10:41pm. for a bit more info.
     
  25. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    I think the quickest way to get this resolved would be for you to provide me with some repro project of this.

    I think the issue is a simple shader assignment which needs to be done as the bundles are loaded. As you load these prefabs from the bundle, you should be able to iterate over each text object and fontSharedMaterial they reference and re-assign the correct shader from the project to them.

    The project should already contain your modified shader or the TMP shader so just forget about the shader(s) in the bundle and re-assign the one that is known to work in the project. if the material properties are fine then re-assigning the correct shader should make everything work. You should not need to look at any of the Renderers or any of that.
     
  26. JonnyHilly

    JonnyHilly

    Joined:
    Sep 4, 2009
    Posts:
    749
    ok found a workaround....

    Usual fix for this type if issue is to search for the missing shader by name, then re-apply to the material. For the "TMPugui loaded from bundles" case, I had to do something a bit different...

    1) made a FixMaterial helper script in the main/base project scene, that is not loaded from bundles, and have an array of materials on there, place in here the Text Mesh Pro font materials (that lose their shader at run time). That script then has a "findMaterialByName(srting materialSearchName)" public function.

    2) Second part of the fix is a script that goes on the same gameObject as the TMPugui script, with a ref to theTMPugui component, and "public string materialNameString", with the "material name" from the broken ugui text. Manually enter this.
    Then OnEnable for that object, it calls into the FixMaterial.instance.findMaterialByName(materialNameString);
    Then sets the returned material into the TMPugui.sharedMaterial variable.

    The trick is having the missing material or shader references/array stored in a non-bundled part of the project, and make your own quick search function.
    Using UNity's findShaderbyname, or referencing materials stored in the bundle doesn't always work. and can sometimes work, then break later (if you load a different bundle using the same material or shader, (vice versa, it can start off broken, then work later after opening other bundled or non bundled ui utilizing the same materials/shaders)
    Unity just has a problem with bundled shader/material refs (at least in UNity 5.6)

    The trick is to re-assign them when broken, and store the material/shader refs to re-assign, in a non bundled part of the project.
     
  27. Menion-Leah

    Menion-Leah

    Joined:
    Nov 5, 2014
    Posts:
    189
    I'm facing exactly the same issue since I updated TMP to 1.5.0-preview.2 (and also 1.5.0-preview.3 doesn't solve the issue).
    Unity 2018.4.12f1.

    Everything was working properly before the update; now text on some prefabs loaded from AssetBundles lose its additional effects such as Outline, Underlay, Lighting, Glow.

    The problem only affects mobile builds.

    After updating TMP I also recreated the Font Altas, tweaking its properties since the old ones were giving unwanted results on smaller texts.


    EDIT: SOLVED
    Sorry, this issue was due to a third party plugin, "Soft Mask", as explained here.
     
    Last edited: Jan 16, 2020
    VadimWG likes this.