Search Unity

Custom Shaders and Asset Bundles on iOS

Discussion in 'Scripting' started by IainStanford, Jul 17, 2012.

  1. IainStanford

    IainStanford

    Joined:
    Aug 18, 2010
    Posts:
    28
    Hi,

    I've googled around and I know roughly what goes on with bundled materials that use custom shaders, but I still have issues with then rendering properly once unbundled.

    I understand that shaders are *not* included inside asset bundles...but I'm still confused as to how they actual hook up once they are unbundled, I'm under the impression they just reference the shader in the project but I'm getting some odd behaviour.

    For example,

    I have an object with a custom shader, called CustomShader for example and this is bundled into an AssetBundle. I have this shader also in my Resources/Shaders folder to ensure it gets built/compiled. When I unbundle an object the object (this is on iOS), I can see that the material does indeed have "CustomShader" as its shader....but its not displaying correctly.

    If I then go to "Edit" the current shader, it only gives me an option to "Open compiled shader". If however I pick "CustomShader" from the drop down list, it then displays correctly and when I click "Edit" it open up in Visual Studio as expected.

    So...whats going on here? Why does it display differently when I select the same shader from the drop down box? I was under the impression if I included the shaders in Resources, then the bundle will reference these. This doesn't appear to be the case, especially as it only lets me edit the compiled shader. Also my shaders usually display the "Shader might be expensive on this platform" warning, but not on the ones in the bundle. Again if I select *the same shader* from the drop down, it then displays correctly and I again get the expensive shader warning.

    Is there anything else I can do to ensure the bundled materials display correctly? I tried creating a game object in the scene with all the material attached to it to see if that forced it to work, but again no luck.

    What I can resort to is, after unbundling the asset, going through ALL renderers->materials and doing a "Get shader name" and then setting it to be the same shader (basically, doing the equivalent of selecting the same shader from the drop down box).

    Again, this only appears to happen in iOS mode, windows mode (and windows bundles) seem to work ok.

    Hope that made some sense to someone.


    EDIT: When I say it renders wrong, it looks like it *might* just be going to the Diffuse fallback shader in the compiled version (referenced by the AssetBundle), but when selecting it from the drop down menu it runs fine.
     
    Last edited: Jul 17, 2012
  2. Dreamora

    Dreamora

    Joined:
    Apr 5, 2008
    Posts:
    26,601
    Shaders must be part of the project using them or they won't work.
    Shader, like normal programming code, is not transfered through Asset Bundles. Only their respective asset id is part of the asset bundle

    That being said from what you mention it theoretically should work so there is an additional thing in the mix here.
     
    Last edited: Jul 17, 2012
  3. IainStanford

    IainStanford

    Joined:
    Aug 18, 2010
    Posts:
    28
    I know, what I'm pointing out is that I have included the shaders, but they are just falling back to diffuse. However if I then pick the shader from the drop down after the asset is instantiated out of the bundle...it renders fine.
     
  4. Dreamora

    Dreamora

    Joined:
    Apr 5, 2008
    Posts:
    26,601
    I think your conclusion has a problem and that is if you do the dropdown in unity then it will always work if it is in the project as the project looks at the whole set of project resources (not even limited to Resources.

    So lets check a relevant matter:
    Are you testing on iOS and not only the editor?
    I ask this to ensure that you not by error are using an AssetBundle that is build for Windows (or anything but iOS). These would fail on the device and more relevant: the shaders they contain are incompatible with iOS and would hence lead to a diffuse fallback (the shader emulation in the editor might then show a behavior as described)

    Are you doing anything different than for example the Asset Bundle demo does or the Character Customization instantiation wise?
     
  5. IainStanford

    IainStanford

    Joined:
    Aug 18, 2010
    Posts:
    28
    All shaders in the main project are in the Resources folder.

    We have Windows, iOS and Android bundles, I am definitely loading in the correct ones.

    This is running in iOS mode within the Editor, but it looks fine when running in Windows mode.

    This is a *very* large project (also hence why I can't go into too much specific detail with confidentiality and the like), but we are just instantiating "mainAsset" once the bundle is loaded.

    One thing I have noticed (and this is probably somewhat unrelated), but when we alter a script in the main project, if the bundle was bundled before this change we can't instantiate assets from the bundle (Unity complains with the hashes of the script in the project and the reference in the asset bundle being different), meaning when we change the code in a script we have to rebundle on iOS (which is a bit of a pain if all they are doing is referencing). Is this similar with shaders?

    (We have mutliple projects with assets bundled in one project and loaded in another, we sync scripts+shaders between these)
     
  6. IainStanford

    IainStanford

    Joined:
    Aug 18, 2010
    Posts:
    28
    Another strange outcome.

    When compiling to iPad 2, the shaders now work, but appear to be an older compiled version (we have a cginc that has been altered, so the shaders in the resource folder on Mac render correctly, but in the build they are renderering how they did before the change)
     
  7. Dreamora

    Dreamora

    Joined:
    Apr 5, 2008
    Posts:
    26,601
    Its similar for shaders yes as they are editor time compiles too in case of iOS if I recall right.

    No idea on the strange outcome with this amount of informations at least.
    did the build process run through normally, opening xcode etc?
     
  8. IainStanford

    IainStanford

    Joined:
    Aug 18, 2010
    Posts:
    28
    Ok, I have sat down with our main graphics programmer and we've found out some interesting behaviours.

    The idea that AssetBundles "just contain a reference to the script or shader you are using" is actually false.

    They contain the compiled scripts and shaders. You can see this by looking at the compiled shaders used by materials instantiated from a bundle.

    The reason they appeared different on Mac as opposed to iPad is because the compiled shaders in the asset bundle only included the GLES shaders for iPad and not for Mac Desktop (so in the Editor they just used their Fallback shaders), this is why when I then selected the shader from the drop down, it would switch to using the compiled shader in the project which IS compiled for Mac Desktop and would then work.

    This is also why if you alter a script that is used by an AssetBundle, when you try and unload that bundle it will complain that the script hash values have changed, because the compiled script in the AssetBundle is now different to the compiled script in the project.

    This is also why when it ran on iPad i was seeing an old version of the shaders, because thats what they looked like when the asset bundle was created and that was the compiled version in the bundle.

    So. Yes you need shaders in the Resource folder (this is also because they need to be there for Fallbacks), but if you make changes to them there you HAVE to rebundle, because the bundles contain the compiled code, and this is why some shaders in bundles just use their Fallback shaders when running in the editor, because the compiled shader is compiled for iOS devices only and not Mac Standalone.


    Hope that all makes sense?
     
    Last edited: Jul 17, 2012
    junk1er likes this.
  9. unimechanic

    unimechanic

    Joined:
    Jan 9, 2013
    Posts:
    155
    This thread is a little old, but I'm posting information in related threads of our community, to clarify how Shaders and Asset Bundles work together, and how to avoid some conflicts. The shader's code is included with the asset bundle, whenever shaders are directly referenced as parameters in BuildPipeline.BuildAssetBundle(), or indirectly with option BuildAssetBundleOptions.CollectDependencies. This could cause a problem if you use BuildAssetBundle alone to create several asset bundles, since referenced shaders will be included in every generated bundle. There could be conflicts, i.e. when you mix different versions of a shader, so you will have to rebuild all your bundles for any modification. This also increases the size of bundles. To avoid these problems you can use BuildPipeline.PushAssetDependencies() to separate shaders in a single bundle, and that will allow you to update the shader bundle only. We are adding a page to the manual with more information on this topic and examples of the workflow to build a shader bundle.
     
  10. Cascho01

    Cascho01

    Joined:
    Mar 19, 2010
    Posts:
    1,347
    @unimechanic:
    I´ve followed the manualpage "Managing asset Dependencies" - but how can I put shaders to the ShadersList-Prefab? Do I have to download and replace the builtin Unity-Shaders so that I can drag them into the list?
    What would I do to make my assetbundles also use referenced textures and materials? Make new prefabs called MaterialsList/TexturesList and do it the same way as with the shaders? What would then the correct download-order be?

    1. Download TexturesPrefab?
    2. Download ShadersPrefab?
    3. Downlaod MaterialsPrefab???
    4. Download 3D-ObjectPrefab?

    I tried without success :(

    Please help me here - thanks!
    Carsten
     
    Last edited: Aug 20, 2013