Search Unity

2d Circle Arc (Not in UI)

Discussion in '2D' started by chrisparton1991, Feb 28, 2017.

  1. chrisparton1991

    chrisparton1991

    Joined:
    Jul 1, 2016
    Posts:
    14
    Hi there,

    I've been looking for a way to render an animated arc to overlay a sprite. Most of my googling has led me to solutions for doing this in the UI (which makes it super easy), but I want to overlay this on top of another sprite.

    I made spritesheet for an animated arc (I put together a little arc spritesheet generator to do the work for me: http://codepen.io/chrisparton1991/pen/MpwRmv).

    So my question is: Is a spritesheet like this the most efficient way to implement an animated arc like this? I know nothing about shader programming, but if there's something out there that can do this more efficiently I'd be interested in taking a look.

    For clarity, here's the spritesheet (looks a bit dodgy due to resizing).
     
  2. vakabaka

    vakabaka

    Joined:
    Jul 21, 2014
    Posts:
    1,153
    Last edited: Mar 2, 2017
  3. chrisparton1991

    chrisparton1991

    Joined:
    Jul 1, 2016
    Posts:
    14
    Hey vakabaka, thanks for your reply!

    I saw that unity post too, but it only pertains to UI unfortunately.
    The spritesheet method is working fine for me so far, so I think I'll stick with that unless I find it lacking in some way. I can simply control the speed of the animator to speed up or slow down my animation to the duration I want.
     
  4. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    The sprite sheet method is certainly a way to go about it. There are several methods for doing this with shaders, some involving radial gradient textures (cheap, limits you to 256 descrete steps, jagged & aliased edge), analytical radial gradients (relatively expensive compared to the texture approach, but lots of fine control, trivial anti-aliasing, and probably less expensive than your average normal mapped or specular shader), or some mildly more complex methods that are usually cheaper than the analytical gradient, but more expensive than the texture gradient. Then there's the various mesh based methods, like just making a mesh ring and panning a clamped texture across the surface, or generating a mesh with a pie slice cutout from script.

    All of the options work, and all have their strengths and weaknesses. The mesh based methods are likely the cheapest overall, with the ring being the simpliest to implement, but you can't easily control the width of the line if that's something you care about and might need a lot of polygons to look good depending on your use case. The mesh slice is what I think unity's UI systems do internally and are similarly cheap as they require no special shader, but do require some decent knowledge of procedural mesh generation. The shader based methods are usually the most flexible, but of require you learn how to write shaders, or at least find one someone else wrote.

    The sprite method honestly works just about as well as the gradient texture method, and is even cheaper to render, though uses more memory.
     
  5. chrisparton1991

    chrisparton1991

    Joined:
    Jul 1, 2016
    Posts:
    14
    Thanks for the in-depth answer @bgolus! I've deployed my game to an old, slow Android phone I use for testing and it renders fine on that, so I think the performance of my spritesheet is good enough for me.

    The generator I made allows me to change things like diameter, line width, line colour etc., so I can trivially update the look of the arc and I get nice anti-aliasing for "free". However, to limit my texture to 2048x2048 I'm only using 100 discrete steps. Still, it looks fine with that amount.
     
  6. chrisparton1991

    chrisparton1991

    Joined:
    Jul 1, 2016
    Posts:
    14
    I ended up needing a better solution than my spritesheet, as I was rendering arcs at larger sizes than I had previously anticipated.

    I put together a shader that did the trick, but it ran really slow on mobile devices due to all the trig calculations that were required.

    I ended up using a LineRenderer to do the job, and it works really well. I use the following code to precalculate the points in the arc, and simply remove the points to animate the arc from a full circle to nothing:
    Code (CSharp):
    1. if (coordinates == null) {
    2.     coordinates = new Vector3[Segments];
    3.     float angle = 0f;
    4.  
    5.     for (int i = 0; i < Segments; ++i) {
    6.         var x = Mathf.Sin(Mathf.Deg2Rad * angle) * Radius;
    7.         var y = Mathf.Cos(Mathf.Deg2Rad * angle) * Radius;
    8.  
    9.         coordinates[i] = new Vector3(x, y, -1f);
    10.         angle += (360f / (Segments - 1));
    11.     }
    12. }