Integration with custom UI types
True Shadow supports most custom UI components. However, it may need some help to achieve the best performance.
Let's say you have a shader for a dissolve effect on your UI. True Shadow will generate the correct shadow for your UI. However, as you change the dissolve amount, the shadow does not update.
This is because True Shadow can cache generated shadow textures, and even share them between identical looking UI elements. Since normal UI don't have a dissolve property, True Shadow doesn't know the UI has changed.
There are 2 ways to solve this:
- Add the
True Shadow Disable Cache
component. This is suitable for effects that update every frame. Or simply if you wish to not do any additional steps. - Give True Shadow a hash of your properties.
Custom Hash
Step 0
If you have a custom component, you'll want to implement the ITrueShadowCustomHashProvider
interface to hide True Shadow warning about unsupported components.
Step 1
Calculate a hash from all your custom properties, and set TrueShadow.CustomHash
void UpdateTrueShadowHash()
{
shadow.CustomHash = HashUtils.CombineHashCodes(
DissolveAmount.GetHashCode(),
DissolveSoftness.GetHashCode()
// ...and more as needed
);
}
Not all properties of the Text need to be included in the hash. If the properties affect the size of the final UI mesh, True Shadow can detect it automatically.
If your have too many properties, or if they're expensive to access, a random hash also works:
shadow.CustomHash = Random.Range(int.MinValue, int.MaxValue);
This make the shadow responds to changes, but prevents reuse of shadow texture between identical copies
Step 2
Update the hash when any of your properties is changed. Some common place are: property setters, OnValidate, custom inspector OnGUI
public float DissolveAmount {
set {
//... Your logic
UpdateTrueShadowHash();
}
}
void OnValidate(){
UpdateTrueShadowHash();
}
void OnGUI(){
if (GUI.changed)
UpdateTrueShadowHash();
}
A complete example
This example uses a separate component to keep it simple
[ExecuteAlways]
[RequireComponent(typeof(TrueShadow))]
class TextHashProvider : MonoBehaviour, ITrueShadowCustomHashProvider
{
TrueShadow shadow;
DissolveEffect fx;
void OnEnable()
{
shadow = GetComponent<TrueShadow>();
fx = GetComponent<DissolveEffect>();
}
void UpdateTrueShadowHash()
{
shadow.CustomHash = HashUtils.CombineHashCodes(
fx.DissolveAmount.GetHashCode(),
fx.DissolveSoftness.GetHashCode()
);
}
void Update(){
fx.DissolveAmount = Time.frameCount * 0.01f;
UpdateTrueShadowHash();
}
}
Use custom vertex data and material properties when rendering shadow
When rendering shadow, True Shadow copies the mesh, vertex data, and material properties from the shadow caster. This will result in the correct shadow in most cases.
In some cases, these data may depend on rendering parameters. For example, you may use the render target size to set a material property. In this case, you must provide True Shadow with the correct property by implementing one of these interfaces.
Note for Asset Store Publishers
If you have an asset that is a custom shader on top of any subclass of UI.Graphic, including builtin UI components like Image, it most likely will work with True Shadow. I'd love to hear about your asset. Contact me at contact at leloctai dot com for any business related queries. I'm happy to provide True Shadow for free to test this out, and potentially showcase your asset on True Shadow store page and website.
True Shadow will define the symbol LETAI_TRUESHADOW
in projects with the asset. You can use this to compile out any code related to True Shadow when your asset is used in a project without it. For example:
void UpdateTrueShadowHash()
{
#if LETAI_TRUESHADOW
shadow.CustomHash = ...
#endif
}
If your asset is a shader without any custom components, users can still benefits from a static method that let them manually update True Shadow when they want to modify the shader properties at runtime:
#if LETAI_TRUESHADOW
public static void UpdateTrueShadowHash(TrueShadow shadow)
{
shadow.CustomHash = ...
}
#endif
Gradual integration
If you have a lot of custom properties, you may think it is too time consuming to integrate with True Shadow. However, you can improve user experience a lot with just 4 extra lines of code:
class YourClass : ..,
ITrueShadowCustomHashProvider // Hide warning
{
// Reference True Shadow
TrueShadow shadow;
void OnEnable(){
// Get it
shadow = GetComponent<TrueShadow>();
}
void OnValidate(){ // Or OnGUI for custom inspector
// Set a random hash
shadow.CustomHash = Random.Range(int.MinValue, int.MaxValue);
}
}
This help True Shadow update as user configure your asset in the inspector. Accurate hash for more efficient caching can be added gradually later.