2
\$\begingroup\$

I would like to animate a line around an image, starting from the top right going clockwise around the image and then show the check mark.

  • The animation should be possibel to stop and restart.
  • There are multiple images with two different shapes.

Because I'm a developer and not designer. The first thought I had was do it with a LineRenderer using the corners of the RecktTransform and DOTween but it is a bit ugly and gets complicated when I want to fine-tune the animation.

Now I'm thinking doing a sprite animation on top of the original image. I would have to do it for each shape.

Before I'm starting this I wanted to ask if there might be another better option I'm overlooking.

Start and end of animation

\$\endgroup\$

2 Answers 2

2
\$\begingroup\$

One way may be to create a simple mesh around the image and with some clever placement of the UVs, you could make a shader that appears to gradually fade in the line.

So the two vertices in the top-right corner would have the coordinates U coordinate 0.0, bottm-right 0.25, bottom-left 0.5, top-left 0.75, and finally circle back to top-right with 1.0. The V coordinate can stay at 0.0 for all vertices.

Then in a shader, you can the create a 0 to 1 gradient by lerping the saturated U value (so it stays between 0 and 1). By offsetting (adding/subtracting) the result, you can sort of fill-in the shape. If you want a sharp edge, you can use a cutout shader which will clip certain pixels below a specified opacity threshold.

Here's an example surface shader:

Shader "UV Progress"
{
    Properties
    {
        _Color("Color", Color) = (1,1,1,1)
        _Progress("Progress", Range( 0 , 1)) = 0
        
        [HideInInspector] _Cutoff( "Mask Clip Value", Float ) = 0.5
        [HideInInspector] _texcoord( "", 2D ) = "white" {}
    }

    SubShader
    {
        Tags
        {
            "RenderType" = "TransparentCutout" 
            "Queue" = "AlphaTest+0"
        }
        
        Cull Back
        
        CGPROGRAM
        
        #pragma target 3.0
        #pragma surface surf Unlit

        struct Input
        {
            float2 uv_texcoord;
        };

        float4 _Color;
        float _Progress;
        float _Cutoff = 0.5;

        inline half4 LightingUnlit(SurfaceOutput s, half3 lightDir, half atten)
        {
            return half4(0, 0, 0, s.Alpha);
        }

        void surf(Input i, inout SurfaceOutput o)
        {
            o.Emission = _Color.rgb;
            o.Alpha = saturate(i.uv_texcoord.x - 0.5 + _Progress);
            
            clip(o.Alpha - _Cutoff);
        }
        
        ENDCG
    }
}

Demo of the shader on a simple quad while adjusting the _Progress property of the shader:

Shader demo

\$\endgroup\$
6
  • 3
    \$\begingroup\$ Using a UI image's Fill settings will let you do something similar out of the box. \$\endgroup\$
    – DMGregory
    Commented Jun 3, 2022 at 16:44
  • \$\begingroup\$ Nice tip! Never used the UI components much. \$\endgroup\$
    – Morten
    Commented Jun 3, 2022 at 17:03
  • \$\begingroup\$ I suppose the radial fill mode could then also be used to achieve the desired effect on a separate "border" sprite layered on top of the image? \$\endgroup\$
    – Morten
    Commented Jun 3, 2022 at 17:06
  • \$\begingroup\$ @DMGregory that's a nice tip, indeed. Combined with rotating the border image (answers.unity.com/questions/1668484/…) it is actually possibel to achieve what I want with very little effort. I will see if the quality will not surfer from the Rotation. \$\endgroup\$
    – Markus
    Commented Jun 7, 2022 at 7:16
  • 1
    \$\begingroup\$ If you find the image fill solves your problem, I recommend writing up your own answer showing how you used it in your solution. \$\endgroup\$
    – DMGregory
    Commented Jun 7, 2022 at 11:40
2
\$\begingroup\$

In the end, the solution for me was to use the UI image's Fill settings with a separate green border image as suggested by DMGregory.

To start the animation in the top right corner, I rotated the border image by 45° and rotated it back in Unity as suggested here.

To run the animation and add the checkmark I used DoTween:

Sequence mySequence = DOTween.Sequence();
mySequence.Append(_border.DOFillAmount(1, _borderAnimationDuration).SetEase(Ease.Linear));
mySequence.Append(_checkMark.DOFade(1, _checkAnimationDuration).SetEase(Ease.Linear));
\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .