ADR-147: Upgrade AB Materials to Unity 2021

More details about this document
Latest published version:
GitHub decentraland/adr (pull requests, new issue, open issues)
Edit this documentation:
GitHub View commits View commits on


An algorithm to manually upgrade materials packed in Asset Bundles made in Unity 2020 is required when using Unity 2021. This document will go into the details of the SRP Batcher optimizations and how to navigate the issues in URP serialization.


All our Asset Bundles (by the time this ADR is written) are converted using Unity 2020. Although the Asset Bundles serialization between both versions has not changed, the URP version has. That means we can reuse the asset bundles but not the materials without manually upgrading them.


Solution Space Exploration

Upgrading materials from 2020 to 2021

Unfortunately, Unity is using the same class to serialize materials from Unity 2020 to Unity 2021, which means that we have no access to anything the new material doesn't provide. That makes finding stuff like the rendering target (Opaque, Alpha Test, Transparency) challenging because the new URP changed the way keywords are serialized.

Luckily the shader properties are still there, so we can gather them to try to find the correct setup for the material. Additionally, we optimize the materials for the SRP Batcher to enhance performance, this optimizations give us some insight into the render target of the original material.

Getting Render target through the SRP Batcher optimizations

SRP Batcher itself is a whole new world that falls outside the scope of this ADR. The minimum we have to know about it is that optimizes draw calls by batching objects being rendered with the same shader variant. A common variant example is having _ALPHATEST_ON enabled or not to clip fragments that are invisible based on an alpha value. One of the optimizations we do is assume every opaque material is alpha tested and set the property _CutOff (the alpha value for clipping) to 0 in the cases we don't want to clip.

The relevant piece that will solve our problem is tied to the Render Queue. If our render queue is displaying something like this:

SRP Batcher won't be able to batch MaterialA_variantA because it has to render MaterialA_variantB in the middle. We try to put materials with the same render target (opaque, alpha tested, transparent) and the same properties (same variant) in the same render queue and we will use this to know more about the original material.

The full details of the algorithm can be found here but the conclusion is that we are gonna have this range of render queues depending on the render target:

Opaque 2000 + crc[0, Permutations of shaderName + keywords]  + queueOffset (150, 300 or 450)

Alpha Test 2600 + crc[0, Permutations of shaderName + keywords]  + queueOffset (150, 300 or 450)

Transparent ALWAYS 3000

That algorithm shows some overlapping in some extreme cases.

So we can effectively use the render queue to spot the render target of the material!


For the serialized properties, we can retrieve anything that was there before due to the nature of serialization. For the render target, we can use the render queue that the SRP Batcher defines to know which kind of material are we dealing with. This will allow us to set the keywords needed for the new URP material.

Future work

Unity can change the Asset Bundle serialization in any new version and in that case, no manual conversion will make it compatible. At the same time, we shouldn't sacrifice potential improvements in performance, new language features, or new systems due to being stuck in an older AB serialization.

At some point, we will need to reconvert the world Asset Bundles and by then we will need versioning, tools to make the process painless, and a smart way of storing the assets in a way that we have the deprecated version as less time as possible.

Currently, we just upgraded to Unity 2021 and it will accompany us for a while, the above scenario is far away from now. Nonetheless, we should start preparing ourselves for it.


Copyright and related rights waived via CC0-1.0. Living