Tank tracks

Hey all, I have an idea for doing tank tracks, graphically that is, not a physics simulation of that.

I’ve been working on the next iteration of my tank models for the game i’m making(time to take a bigger leap out of greyboxing), I was wondering how best to get the appearance of the tracks moving, at first I was considering using one of them skinned mesh renderers, but then I had an idea - why not just make the texture go round and round with the shader? sounds like a lot less overhead, and now thanks to shader graph it’s trivial task. :slight_smile:

What I’ve done so far is make a “model” tank for testing purposes where the area where the tracks is just flat and inside shader graph make the seamless texture loop in regards to the speed of the tank, couldn’t be simpler - knocked out everything from idea to prototype in less then 10 minutes, yay me.
*video to show what I did at the end of the post

now i’m facing a few problems, the first I have an idea on how to deal with but would like a better suggestion.

  1. we have two tracks, each with it’s own speed (unless the tank is going in a straight line or is stopped) - how would I achieve that with the same material? I believe i can use one side for each track and let them behave differently with masks and all that jazz but it’s a little more then i’m comfortable with shader at the moment.
    I can get around it with two materials (one for each track), but I don’t like slapping on extra materials(or extra anything) where not needed, which is what I think I’m gonna do…

  2. how to actually know how fast to loop it? it’s gonna depend on variables like the length of the track (if we assume tracks are covering the entire length or width of the UV), one loop can equate to different distances.
    The track length is not a really problematic, can just feed each tank a value at editor time, just an example.

what I’m really stumped (that somewhat relates to the loop speed) with is how to derive/extrapolate the difference in speed for each track from the speed of the tank, the tanks are moved kinematiclly by me so I have all the needed information and then some - but what’s the equation?

I think all I need is ‘currentSpeed’ (the speed the tank is moving, -maxSpeed to maxSpeed), ‘currentTurn’( -1 to 1, how “hard” are we turning to what side - feel free to suggest a better name, haha) and just apply to each track (ignoring the first problem atm) individually using somekind of dot product to modify them.
But I’m just dumb struck with this.

The distance of 7.4922 I have Is from the edge length blender gave me, it’s almost perfect.
One other thing I don’t know how to deal with is the “tearing” I get when I change value, I know it’s caused by multiplying time with moveSpeed, but how am I to deal with it, do it differently or add somekind of filter to it?

Thanks for the read.

*some tearing on the tracks from face to face, It’s just the quick and sloppy modelling & UV. I hope, heh…

Neat! I got lazy and did this with just separate materials on each and changing the mainTextureOffset.

As for how much to move each tank tread’s offset, I just cheesed mine to the individual engine controls for each side: my controls are like BattleZone: up down on left, up down on right.

HOWEVER, I think you could calculate how much distance each side moved by putting a dummy transform in the middle of each tread, offset outwards to the edge of the tank, at the red dots in this picture:

4734407--448601--tank_treads.png

Then each frame you would take the vector of that transform’s movement compared to the previous frame, and dot-product it with the transform.forward of the tank, which would give you a scalar according to how much the point in question moved with respect to the longitudinal axis of the tank.

After that I think it is just some constant scaling according to the size of your model, the rate of UV unwrap (distance around tread, etc.) and that would be set on a per-tank-model basis.

Another thing to remember is to modulo your UV offsets to within 1.0f or so of zero: depending on device and platform, if you make your UVs get really huge (far away from -1.0 to 1.0f), it will clip or just turn off the UV mapping.

1 Like

hummm…

Maybe just sampling the position is enough, and it’s really quite simple.
although if I’m using 2 “whole” materials per tank just for the tanks i don’t wanna clutter it with extra game objects too.
Let’s give it a try…

15 minutes later

alright, we’ve got something here.

using UnityEngine;

public class Tank : MonoBehaviour {

    public Material leftTracks, rightTracks;
    public float speed, turn, offset;
    Vector3 leftLast, rightLast;

    void Update() {

        transform.position += transform.forward * speed * Input.GetAxis("Vertical") * Time.deltaTime;
        transform.Rotate(0f, turn * Input.GetAxis("Horizontal"), 0f);

        Vector3 tmp = transform.TransformPoint(Vector3.left * offset);
        Vector3 dir = tmp - leftLast;
        float spd = dir.magnitude / Time.deltaTime;
        if (Vector3.Dot(transform.forward, dir) < 0.0f)
            spd *= -1;
        leftTracks.SetFloat("_MoveSpeed", spd);
        leftLast = tmp;

        tmp = transform.TransformPoint(Vector3.right * offset);
        dir = tmp - rightLast;
        spd = dir.magnitude / Time.deltaTime;
        if (Vector3.Dot(transform.forward, dir) < 0.0f)
            spd *= -1;
        rightTracks.SetFloat("_MoveSpeed", spd);
        rightLast = tmp;

    }

}

What I really don’t like about this is all the math operations, I’m sure there’s a simpler way to derive this like I said in the OP.

anyways, it works, but it behaves a little weird on the corners.

One big issue still remaining is the fact it’s snapping the UVs on value change instead of just accelerating the movement - how do I deal with this?

Thanks a lot dude, great input. (;

Tired of making videos, if you wanna try (and maybe fiddle around with it) it here’s a package with it. (exported from 2019.1.7f with HDRP 5.7.2, everything in project settings is what the default HDRP project comes with)
http://s000.tinyupload.com/index.php?file_id=71643646913617313926

Uhhh… what?
sorry, if you can explain a little more about this it’ll be great.
you mean just moving the uv offset from ###.2 to .2 , right?
will adding a modulo node with the value of 1 connecting the divide node to the multiply node(only 1 of each in the shader, you can see it in the video) do it?, do I have that correct?

SHIP IT! :slight_smile:

I mean the UV offsets that you put into the material, but I don’t think that applies to your case since you are setting a special property in your custom shader.

If you were using a material and just changing the Y offset by adding to it, if your tank was primarily going forward, that number would get larger and larger ceaselessly.

Eventually it gets large enough to have problems in the graphics card. What I have found is to just modulo the UV offsets with 1.0f before assigning it. That way it loops from zero to 1 over and over, not growing boundlessly.

Either way, the bigger a floating point number is the less accurate it is, but some graphics hardware will show problems much earlier.

1 Like

Already “greenlit” this design into the next iteration of models, artist me has a lot of work to do, haha
Just gotta work out one thing before shipping, when the speed changes the UVs snap to a new location and carry on with the new speed from there, it’s really visual when accelerating and especially when turning - it just goes berserk.

The problem is that I’m offseting (and now also modulating (; ) by time * moveSpeed, I don’t see any obvious way to do “bookkeeping” like you would in a plain old C# script (IE have a ‘offset’ variable and add to it by deltaTime * moveSpeed)


but as I write this post I’m just thinking why not use the script we already have to control the speed do that.

problem solved I guess.

still would like a less mathy way to do the calculation, 30-40 of these in the scene in a “worst case scenario” and I already have a lot of ballistics calculations going on and i’d like to give them all the resolution possible.

4734827--448649--upload_2019-7-11_8-36-10.jpeg

4734827--448649--upload_2019-7-11_8-36-10.jpeg

1 Like

Very nice Sparrow! Now… go get some good tank blasting combat going!

1 Like

May I see what code you use for last?

I am trying something similar and every time I start moving… is super quick and then it slows