Christopher Jones, Games Development
  • Portfolio
    • Unity
    • 2D Games
    • Old Work
    • Source Engine
  • About Me / Contact
  • Blog

Custom Image / RenderTexture effects and Unity

12/2/2013

0 Comments

 
So I recently got shot in the foot by an unexpected issue; custom render effects that work just fine in the Unity Editor, but mysteriously disappear when you run them in a standalone build - with a special thanks to Mark Backler for helping catch the issue (which should teach me to test a build before sending it off for someone to look at, even if it's only been in development a week...).

Doubly troublesome in my case given one of the effects (2D lighting) had core gameplay implications, but fortunately it proved easy enough to track. When a build is produced, amongst other things it creates a new folder <build_name>, containing various files. Key amongst them; a build log.

Popping open mine highlighted this little error:
NullReferenceException
  at (wrapper managed-to-native) UnityEngine.Material:Internal_CreateWithShader (UnityEngine.Material,UnityEngine.Shader)

  at UnityEngine.Material..ctor (UnityEngine.Shader shader) [0x00000] in <filename unknown>:0

  at SFXPass.get_mat () [0x00000] in <filename unknown>:0

  at PathfinderDoomFX.Awake () [0x00000] in <filename unknown>:0
Some quick googling later highlighted the culprit; Shader.Find(). Long story short, when Unity builds a project, it strips out content it believes isn't being used. In the case of shaders, it will strip out anything that does not meet the following criteria: 'It is used in a material that is used in a scene'. Guess what falls out those bounds? Shaders referenced only in scripts; for example, for image effects.

So. How to dodge around this little conundrum? Fairly simple really; stick your custom image effects shaders in a Resource folder. Ordinarily of course, assets are either loaded via the Resources.Load method or by being assigned in the Inspector. Unity can scan through the latter case and pick out any asset that's being used and thus needs including in the project, and it handles the former case by just automatically including everything in Resource folders blindly. Shader.Find() is one of those odd methods out that can reference things the above techniques would miss, and hence - whilst it will work in the Editor where the game has access to all the assets, even the non-final ones - fail in a full, leaner, standalone build.

Finally, there's also the 'Always Included Shaders' array in the Project Settings > Graphics rollout. This can be useful if, like me, you're re-using some of the Image Effects shaders but not the components themselves (you have to write your own scripts if you want them to run their calculations on a rendertexture rather than the screen) and don't want to touch or rearrange the Standard Assets themselves, which obviously rules out sticking them in a Resource folder. For your own custom Image Effect shaders though I would recommend the Resource folder option over the Always Included array; with Resource, they automatically get included simply by being there, making things much easier to maintain.

0 Comments



Leave a Reply.

    Author

    A UK-based amateur game developer.

    Archives

    May 2017
    May 2016
    April 2016
    October 2014
    December 2013
    November 2013

    Categories

    All
    Scripting And Theory
    Shaders Are Fun
    Shaders Are Hilarious
    Unity 4

    RSS Feed

Powered by Create your own unique website with customizable templates.