Line renderer with a smooth scrollable texture

Hi all,

This a little complicated to explain but I will do my best -

I have ships in my game that you can drag out a path for them on a touch device. The drag itself creates a list of Vector2 for the ship to follow.
The paths work as one would expect - The ships travel to a waypoint, sets the next one, and then deletes the previous one to save memory of storying too many points. This all works lovely.

I have created a scrollable shader for the line renderer with small circles to show direction -

Here’s the tricky bit - Due to the nature of the creation of paths, the array of points is constantly changing in the line renderer. Whenever a point is removed or added, the scrollable texture jerks forward. I can only assume a line renderer has 0/1 UV’s for the entire line. It bassically makes it look as if it is lagging, but in reality its removing a quad and recalculating the uv’s to fit again…I think.

Does anyone have any suggestions on either -

Changing the line renderer logic to better fit the scrolling shader? I am using unity’s line renderer - which sadly means I do not have access to the mesh component and therefor the UV’s.

Adding to my shader to have it NOT move when a point is deleted (I am certainly no shader expert here but I can make simple stuff).

Failing this, it looks like I could be building my own line renderer :slight_smile:

Thanks all in advance

For a handful of lines and shapes on screen, a custom shader seems like a lot of over-engineered overkill.

I would just use a tweener and be done with it, something like LeanTween or DOTween. Or just use texture UV animation over the line renderer, sliding it constantly to the destination.

It’s not that hard actually. Procgen in Unity is super easy. I even keep a handy random glob of procgen stuff in my MakeGeo project.

MakeGeo is presently hosted at these locations:

https://bitbucket.org/kurtdekker/makegeo

I would imagine this would yield the same problem, due to UV’s changing when adding or removing points from the line? I am using LeanTween already in the probject so I could give it a go though.

I am currently animating the texture uv’s in the shader with a Time node, which looks great when the line is not being added or removed from.

I have done some procedural generation in Unity before and worked with mesh’s but I will certainly look at your API and see if it could give me a good starting point :slight_smile:

Do you know of any way to view UV’s in Unity? I really want to understand what is happening to UV’s of the line renderer when I am adding and removing points. This way if I build my own I can do the exact opposite lol

Cheers

Check out the “Texture Mode” property of Unity’s LineRenderer in the documentation. You can change how the UVs behave, which may help a lot.

Sadly I have tried the Texture mode options but they all do something under the hood to the uv’s that seems to ‘reset’ them.

I think I will look to build my own line renderer so I can access the mesh, as kurt said it shouldn’t be too hard really.

I agree with Kurt (his first answer), but would honestly do the opposite of his suggestion. Having an over-engineered solution in place gives you a lot of breathing room for these kinds of effect in the long run. In fact, what you want to achieve is so desirable in game dev UIs, it makes sense to make a full general purpose solution just once, because you can easily repurpose it for your next project.

So, yes to shaders. The trick here is to rely on UVs, in particular the U coordinate which you want animated. You can make a repeatable texture that scrolls whatever symbols you need, circles, dots, dashes, crosshatch lines… left to right. Then you make your own line renderer (or try fiddling with LineRenderer, I wouldn’t however) like this: create a simple mesh quad with properly scaled UV coordinates between every two points on your path. For V keep it at 0…1, for U make sure you take the segment distance into account, or else your texture will stretch (or squash) along the segment.

Everything else you can do via shader graph, the animation itself, the parameters of it (anim speed, additional scaling), as well as any secondary effects. Of course you want the shader to compute a modulo of U, so that the texture repeats seamlessly creating the illusion of moving dots (or whatever).

If you want to go down this route, I can help with the steps involved.

Thanks @orionsyndrome for the detailed response, and certainly helps if I do go down building a line renderer myself.

I have actually already built the shader, with scroll speed and everything else. Let me show you guys two short clips to explain the issue perhaps slightly better.

With the scroll speed at 0 on the shader, the texture still moves as seen in the clip below. This is because (I think) the uv’s are again being recalculated to go to 0-1 every time points are removed/added…

This video is of the shader I created with the smooth scrolling effect - great right? You would think so - but when combined with what I am doing above (creating and removing points on the fly) the effect looks tacky and jerky because its getting jilted by what I think is the UV issue.

I have created procedural meshes before but I am not over familier with adjusting UV’s to do exactly what I want them to do in your example Orion. I used to work in 3D so I do have fair understanding of UV’ing in general, for some reason I cannot wrap my head around what exactly the UV’s should look like once created…

Ah sure, I get what’s the problem. I didn’t understand you already did the most of the work.
Yes, the wavy behavior is due to the trapezoidal shapes, it’s because the UVs are tugged between the uneven corners. There are two potential fixes to this problem:

  1. Adjust your UVs to represent non-distorted rectangular shapes (more math), or
  2. Let your quad overlap as strict rectangular shapes (less or similar math but introduces overdraws which isn’t that big of an issue for your case).

–
More information:
Here’s what happens with your segments
image
Here you set the blue point to (0, 0) and green point to (0, 1) but the distribution over the two triangles is uneven.

Here’s what you should do instead (solution #1)
image
The orange point should be (0, 0) and then you extrapolate the blue one (a similar thing should be done for the green point as well).

When I enlarge (and rotate) the small triangle, this is what happens (if I’ve done the math correctly)
image
(angle a here is the angle at the vertex contained by the red path)

Instead of correcting UVs you could instead build a different mesh (solution #2)
image
and stick with the regular UVs: (0, 0), (0, 1) and so on.

I’d say the 2nd one is the easier solution, but slightly less ideal because you also need to include the missing triangle piece and correctly UV that as well. There are tricks you can employ but I can’t pull them off of my head without experimenting a bit.

Hopefully the images make it easy to understand, if not, ask and I’ll try to clarify.

Btw try to make your shader actually render the UV coordinates (as RG) instead of sampling the texture. That’s one sure way to debug wonky rendering issues like the one you’re experiencing. If you do I’m positive you’ll be able to clearly see why your animation is behaving the way it does and what’s going on exactly at the edge between the triangles.

Rendering UVs normally looks like this (for a perfect square quad)

I’ve also just thought of a 3rd solution: split the mesh in two exactly at the path, this will make it work more uniformly where it matters the most. Could be the easiest thing to do. Of course remap the UVs so that the vertices at the middle have their V as 0.5.

Wow thank you for again a very detailed answer and certainly something to get cracking on =)

I should note that this is currently the unity line renderer component, so I will have to build my own so I can access the mesh and uv’s.

I am having an eye operation so it may be a little while before I report back with my findings but I certainly will.

Thank you again for the time you put in to help

No problem.

Regarding the solution #2: Keep in mind that you can generalize the mesh builder a lot if you always assume 1) one quad per segment (or 2 quads if you split at the middle), and 2) depending on the angle between the segments, you let one ear overlap, and fill the other with a triangle face.

It should be two-three days of work at most and pretty much without any trigonometry (you just need to differentiate angles to see where exactly the elbow triangle should land).

Then you can set UVs directly from the mesh object space (in 2D this is practically screen space) if you know exactly where your quads are (and you do since you make them from the path). So it’s relatively easy to find proper UVs because you only really probe the object space coordinates for the actual UVs at the vertices.

Here’s how: You pretend (mathematically) that each quad lies horizontally (X-axis aligned) and begins at origin (that’s the object space), and then you transform the previous quad’s ending vertices to this space. Then you rescale everything by some normalization factors to end up with valid UVs in this space.

You can also find the points between quads where the relevant edges meet (if you go after solution #1) thanks to intersecting lines.

I know it’s a lot of words, and probably seems daunting, but it’s really not that hard. Though it is fiddly, I’ll give you that. But you do it once and pretty much forget about it.

If I find some time, I might make the mesh builder for this (don’t rely on it, I’m pretty busy rn).

In any case, ping me if you need any further assistance.

If I already had something off the shelf and wanted a quick solution, I’d personally go with #1 as with dots the distortion might be small enough not to be noticed, at least if the curves are gentle as in the video. If I wanted to get it polished, and was coding my own solution anyway, then I wouldn’t render a line. And thus…

Solution #4: Just make quads exactly where you want them! You’ll be able to get perfect results with less work.

  • You know the path that the dots need to animate along, so you should be able to get positions on that path pretty easily.
  • Instead of messing with stitching and figuring out UV behaviour, just put a quad at each of the desired positions. It’s just sampled position +/- half of the desired size, with UVs from 0 to 1. Zero distortion, and it won’t even need a shader.

This could still all be done in a shader, but I’d just do it in C# land unless there’s a lot of it going on.

Also, in the first video where the dots are jumping forwards as the path is re-calculated, that cane be solved by flipping the order of the path’s points, so that it is destination-to-origin. That way when it relcalculates it’s doing so from a fixed point rather than a moving point.

3 Likes