• Home
  • Store
    Show / Hide Table of Contents

    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.

    • ITrueShadowCasterMeshModifier
    • ITrueShadowCasterMaterialPropertiesModifier

    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.

    In This Article
    Like True Shadow? Your review is greatly appreciated! ⭐⭐⭐⭐⭐ Back to top