I want to make a train go round a track using physics?


I want to create a train and carriages (all independent when needed),I want the physics engine to move them round a track so I can stop start unlink so friction slows them down.

The track will run through a game environment curved and straight sections.

I thought about importing animation ,but the physics engine would give me more control

I need a simple physics model (sphere say) that is given a force along direction but is also fixed in a rail

any ideas?

Seems to me like you could do this the same way a train works (well in a fashion).

Creating your track with collision then create your train model with wheels that would enclose around the track.

Now you could use physics to control your train; keeping gravity and mass on your train will keep it on the track, then applying a force to your train engine over a fixed update until you reach your max desired speed.

The phsyics would then propel your train along the track as long as it wasn't going to fast as if the speed increased to much your train would be removed from the track.

I made a generic little object to play around with that worked fairly well (very rough of course)

alt text

This would be a very 'basic' way to do it and is far from the end all of awesome train mechanics. ;)

The way I would probably approach this is to use ConfigurableJoints to connect the carriages to each other, and a custom script to simulate the forces from the wheel to keeping the train on the track. A bit similar to using custom scripted wheel collider in the advanced car physics model in this sample: http://blogs.unity3d.com/2010/04/24/car-tutorial/

But unlike those, the script would calculate the track position (for example from a spline), and apply very strong horizontal forces to keep the wheels in the track.

You could treat the track segments like tunnels and forgo any complications of trying to add physics to your wheels.

Create frictionless colliders to the left and right of the tracks to make walls. Use several colliders along curved section of track to form curved walls. Apply some friction to the bottom of the track. You may want to lock some axis depending on if you want the train to bank or not, or if the surface will be flat or curved.

Then, if you put the train in the tunnel, and give it a push, it should stay within the boundaries of the tunnel and move along the track.

As for the other cars There are many suggestions here already so I won’t add more.

Maybe you could use an Animation Clip to set the x,y,z values for Rigidbody.AddForce or Rigidbody.AddRelativeForce.

Hm, that is an interesting problem. I guess if your railroad is a straight linee, you could use a ConfigurableJoint allowing a linear motion along one of the axis. However, this is most certainly too restrictive.

Now, you would like to have a curved track and allow linear motion along the track. I wonder if you could create a ConfigurableJoint for each car. Then, at each `FixedUpdate()`, find the position on the track closest to the current position of the car, and move the ConfigurableJoint to that posisiton, and rotate it such that the allowed axis of movement is parallel to the track at that point. That way you should get local linear movement along the track at all times without doing any animation trickery.

I don't know how detailed you will get in modeling your physics, but if you are including the wheels a track and some corners, the shape of the wheel is important.

Train Wheel Shape and Why

If you need the train to move along a fixed path you can write a waypoint or path follow script using Rigidbody.MovePosition to change the position of the cars. If two cars need to link, simply reparent them to a single object. To slow a car down add a fractional multiplier to the speed that lerps from it's current speed to zero

  var speed = Vector3 (waypoint position);
        function FixedUpdate () {
        //move to waypoint
            rigidbody.MovePosition(rigidbody.position + speed * Time.deltaTime);
       // slow down
        rigidbody.MovePosition(rigidbody.position + speed * Time.deltaTime *Vector3.Lerp(speed, 0, time););