Train simulator help with some tips and tricks

Hello. It’s my first post here, my english is not very good but I’m trying my best.
Some time ago I completed a mini train simulator and at the time I had a problem that I thought I solved it, and now I’m back at it. Wagon movement after locomotive.

1: I tried using joints, but produced a locomotive glich like a shaking on Z axis, the forward axis.

2: The second and last attempt was with iTween.Path. Placed at each fork in the road a iTween.path depending on the direction chosen by the user, activate the path to be followed by a train. Wagons are moving forward depending on the speed of previous item (locomotive or wagon), and always look at previous element. Issue, as even some more cars to derail the train starts to get out from the road, just in curves.

Maybe some of you with much more experience could give me some advice, tips and tricks. Or where I’m wrong.

Because we have not received any reply I tried a few suggestions found on the internet and I managed to make the locomotive to move much smoother using bezier curves. But the problems continue … Fail to find a solution for wagons to follow previous gameobject (example: vagon_1 → locomotive, vagon2 → vagon_1 etc …) without navigating away from the railway. As I add more cars the more they see how over the last derailed railway. I will post the update function for locomotive, wagon, maybe someone give me a hand.

LOCOMOTIVE

private void Update ()     {
        if(Input.GetKey(KeyCode.UpArrow))
        {
            metersPerSecond += accelerationStep;
        }
        else if(Input.GetKey(KeyCode.DownArrow))
        {
            if(metersPerSecond > 0)
                metersPerSecond -= accelerationStep;
        }        
        this.speedInTime = Time.deltaTime * metersPerSecond;        
        //Debug.Log("Moves with: " + speedInTime + " m/s");
            
        if(Path.Count != 0)
        {
            if(counterNodePath < Path.Count)
            {                    
                Vector3 direction = Path[counterNodePath] - transform.position;
                float distance = direction.magnitude;
                this.speed = this.speedInTime/distance;                
                Quaternion rotation = Quaternion.LookRotation(direction);
                transform.rotation = Quaternion.Slerp(transform.rotation, rotation, this.speed);
                transform.position = Vector3.Lerp(transform.position, Path[counterNodePath], this.speed);
                if(transform.position == Path[counterNodePath])
                    counterNodePath++;                
            }
            if(counterNodePath == Path.Count)
            {
                transform.eulerAngles = new Vector3(transform.eulerAngles.x, yRotLastCurvePoint, transform.eulerAngles.z);
                Path = new List<Vector3>();
                counterNodePath = 0;
            }
        }
        else
            transform.Translate(Vector3.forward * speedInTime);
        this.pointJoint = transform.TransformPoint(-Vector3.forward * DISTANCE_JOINT);
        this.pointDistBetweenObj = transform.TransformPoint(-Vector3.forward * DISTANCE_BETWEEN_OBJECTS);    
    }

WAGON

private void Update() 
    {
        transform.LookAt(previous.pointJoint);
        if((previous.transform.position - transform.position).magnitude >= DISTANCE_BETWEEN_OBJECTS)
            transform.Translate(Vector3.forward * previous.speedInTime);
        
        this.pointJoint = transform.TransformPoint(-Vector3.forward * DISTANCE_JOINT);
        this.pointDistBetweenObj = transform.TransformPoint(-Vector3.forward * DISTANCE_BETWEEN_OBJECTS);
        this.speedInTime = previous.speedInTime;
    }