I have a beam mesh (a cylinder) that lengths and shortens at times via the BP. Is there a way to make the tiling on the cylinder consistent so it doesn't tile too much when it's short and too little when it's long?

Hi, so as the title says, I have a cylinder that can change length based on the BP. I have a texture on it that right now tiles too much when the length of the cylinder is too small and too little when the length of it it too large. Ideally I’m looking for a way, similarly to Niagara’s tube ribbon tiling that stays consistent regardless of the length of the cylinder. I can’t use world space alignment because the beam can move in space and it looks off/noisy with WS UVs. Any advice or tips please?

I have a setup for this that I did a while back. Give me a few to find it :slight_smile:

2 Likes

You can use the ObjectScale node to scale the UV depends on the UV mapping of your cylinder and which axis you scale your cylinder:

So this is how I have mine set up:

  1. The Absolute and Object Position subtract creates an object orientation locked set of values (that is later divided to created a 0-1 gradient in WS that stays local to the object)
  2. Since I’m only care about the texture staying the same size as I adjust my cylinder’s scale on X, I multiply by the ObjectScale so that it self adjusts
  3. That goes into an Fmod node* along with the parameter input for scaling my texture on X for the cylinder (along it’s length that I’m adjusting, for me)
  4. Which I then divide by that same parameter that I’m using for texture scale on X. This makes the 0-1 gradient on X/U, and also causes the gradient to repeat/tile over every number of world space units that I’m determining with that X tile param.
  5. I have the “starting end” of my cylinder and its origin/pivot point on 0.0 of the X axis, I’m adding half of the ObjectScale X value after so that the texture will always begin at that starting point regardless of how much I’m scaling the object or texture.
  6. After that I mask off the Red value, because I’m using this world space repeating gradient as the X texture coordinate gradient for my UVs
  7. I input the Y texture tiling param in and multiply it by the green channel (Y tex coord) of my TexCoord UV input like you normally would. This will just tile my texture on Y like you would normally expect.
  8. I append the R and G channels together, and that’s my final UV output that I input into my texture node’s UVs

This setup gives me the functionality of a texture that will always start at my cylinder’s origin, be locked to its orientation so I can rotate it and move it around while the texture stays in place like you’d expect with a normal UV setup, and my texture will tile/repeat on X every input number of Unreal units regardless of how far I’m scaling my cylinder up or down on X. So if I used 500 for my Tile_X param value, the texture will begin to repeat after 500 units. If my cylinder ends are between 0 and 1000 units, the texture will tile twice. If my cylinder ends are between 0 and 250 units, only half of the texture will be displayed. If you are dynamically scaling this cylinder up and down, the texture will never move or squash/stretch as your mesh shrinks and grows on the local X axis.

Does that make sense?

You can do any manual texture offsets or use a panner node after this setup, and it will function normally. Pan speed should stay the same regardless of the cylinder’s scale on X.

*Fmod: Math Expressions | Unreal Engine 4.27 Documentation

Big shout out to @tharlevfx for the video on Object Space Gradients that was immensely helpful when working this out.

1 Like

I just want to reiterate that this setup has the X tiling parameter working a little differently than a typical texture tile setup. With this your X tiling param needs to be set to the distance of Unreal units you want the texture to begin tiling on X. If you put in 2.0 for Tile_X, the texture will repeat every 2 Unreal units, not twice. If you want it to stretch and cover twice the distance, you’ll need to double your original Tile_X value, not halve it.

This is perfect thank you guys! It’s working nicely now!

1 Like