How do I synchronize texture offset animation with world movement?

I'm working on a top-down racing game and I'm trying to move the world around the player rather than move the player's car, so I'm animating the ground texture and having obstacles move down the screen towards the player. I'd like to have the movement of the 3D objects match the speed of the "scrolling" ground texture, but I can't find the correct speed factor to get them to sync up. Any advice would be appreciated.

To calculate the speed of your texture scrolling in world coordinates, you need to know the following:

  • The world unit span of your ground.
  • The UV coordinate span of your ground.
  • The tiling of your texture on your ground.
  • The change in offset.

That's kind of a pain to figure out programatically for an arbitrarily shaped ground. Thankfully this is the kind of thing that you really only need to figure out once in advance or at the very least 1/2 of your unknowns can be plugged in beforehand because they shouldn't change at runtime unless you muck around.

If we need to, we can figure out the world unit span of our ground from the the position of the pivot in the object, the scale in the importer and originating program if it was imported, and from the scale in Unity, etc.. Alternatively, you could use the mesh interface and check the verts rather than the originating program/importer. If you would rather do it the simple way, use Unity's vertex snapping and snap some empty GameObjects to your ends (the distance between is your span). But remember that you should only need to do this once before you begin in most cases.

To figure out your UV span, that would depend on your uv coordinates. These can be retrieved from the originating program of your model or the mesh interface if you like. In most cases, this is 1.

The tiling is set on the material. You set and get it in Unity.

The offset is something you change, so you have access to this as well.

Let's assume:

  • your ground is a Unity plane (has a texCoordSpan of 1) with the pivot at the center and a Unity scale of 1 world unit on the y axis.
  • your ground's uvs map the texture from uv coordinate 0,0 in one corner to uv coorinate 1,1 in the opposite.
  • you are setting your tiling on the texture's y to be something like say 0.1, changing the offset on the y by some amount.

The ratio of world units to texture coordinates would be worldUnitSpan / tiling * texCoordSpan. Your positional change in world units would be deltaOffset * worldUnitSpan / tiling * texCoordSpan. In the above example, we can plug in the numbers to get deltaWorldUnits = deltaOffset/0.1f or 10.0f * deltaOffset. If we move an offset of 1.0 texture coordinate (the entire texture), we've moved 10.0f world units along that axis because that texture is tiled across a distance of 10 times the plane's length.