Bane
Bane

Reputation: 341

How can I draw a Line animation to outline various shapes?

I am trying to draw a line animation outline various shapes as in the image below. I am very well aware that it's best practice that I mention what I've been able to achieve to get specific help, but I am not sure where to begin, just that I know that using a Line Renderer could be a good approach to achieving this. That said, how can I achieve this?

enter image description here

UPDATE

I think I didn't explain a few things clearly enough. I am interested in animating the outline of objects without arrows, just a line traced round the outline like the image below:

enter image description here

Upvotes: 1

Views: 313

Answers (2)

CosmicGiant
CosmicGiant

Reputation: 6441

I think a shader with a parameterized radial mask would be the best way to do this. I have never done one myself, so I only have a general idea of how it's done, but here is how it would work AFAIK:

  1. Create some kind of cell shader that can draw the edges of objects.
  2. Create a filter/mask that has an angle shape extruding radially from the center to the edges; you can control the shape/angle using a parameter. Unity already has something similar to this in the Tanks! tutorial - Tank Health lesson.
    • Note: The tutorial might even be exactly this idea, but I don't remember with enough details to confirm; I'll update the answer after I take a look again.
    • The tutorial has the same idea, but it applies it using unity's builtin UI stuff.
  3. Using this mask, only the masked area of the shape's edge will be drawn the screen.
  4. By increasing the angle parameter of the mask over time, you can create the effect of the edge of the object getting revealed radially over time. Which seems to be exactly what you want.

To help visualize, a very professional diagram made in paint:

  • light blue = mask.
  • dark blue = "revealed" part of the mask (angle parameter). Plus how it would behave if the angle is increased (arrow).
  • green = object.
  • black = outline being drawn to the screen.

enter image description here

Upvotes: 1

Majd Akar
Majd Akar

Reputation: 171

I would do the following: (pseudocode, untested)

For every prefab or gameobject, store a List of edges that define your outline. I wouldn't recommend using the mesh's edges, it's probably better to have a specific predefined list of edges per shape to avoid the inner edges of the object. Every entry in the list is defined by two Vector3's which are the two vertices.

List<Vector3[]> outline = new List<Vector3[]>();

Now, you have many ways to actually draw the arrows, like having them as individual gameobjects (probably not a good idea), particle system, or just drawn automatically from the parent objects update function. I would recommend the latter.

Now you would store a bunch of floats that define where your arrows are

public List<float> arrow_locations = new List<float>();

//adding one arrow   
arrow_locations.Add(0.0);

//now in the update function of your parent object, update the arrow locations

private float cycle = 0.0f;
void Update()
{
   float segment_size = 360.0f/outline.Count;
   for(int i=0; i < arrow_locations.Count; i++)
   {
        arrow_locations[i] += 0.05f;  //speed of spinning
        if( arrow_locations[i] >= 360.0f ) arrow_locations[i] = 0;

        //now to get the actual location of the arrow
        int which_edge = Mathf.Floor((arrow_locations[i]/360.0f)*outline.Count);
        //this will give us a number 0..1 telling us where along the edge the arrow is
        float weight_within_edge=(arrow_locations[i] - segment_size*which_edge)/segment_size; 

        //here we lerp between the two vertices of the edge 
        Vector3 new_loc = outline[which_edge][0]*(1.0-weight_within_edge) + outline[which_edge][1]*(weight_within_edge); 

       //now that we have the location of the arrow, draw it
       //note, you can get more efficient if using instancing for all arrows
       //You can also use line drawing, but i wouldn't recommend that. 
       DrawMesh(arrow_mesh, new_loc, Quaternion.identity);

   }

}

Please note, that when you have the positions of the arrows, you can opt to draw them in 2D in the UI by projecting them onto the camera plane. The lines aside from the arrows are themselves static, so you can draw them as part of the mesh very easily. Also note, I make no mention of the objects position, all values should probably be defined in local space, then transformed with the object. You can transform the drawn stuff in the the DrawMesh function by supplying a a transform matrix.

Upvotes: 1

Related Questions