Yes, there are ways, but they are generally more work and will likely end up being more expensive to come close to the same robustness.
For example, there is no built in 'rollercoaster constraint,' but the requirements for such a thing would be:
-1 linear degree of freedom along the direction of the roller coaster path.
-0 angular degrees of freedom; the orientation is parented to the orientation defined by the path.
The orientation can be controlled in the same way as the pure path based approach. The entities, however, are free to move along the path. The trick is to determine exactly where the rollercoaster entity is on the path (1). Once that's available, the whole basis can be computed (forward, side, up) and restrictive velocity changes can be applied (2).
1) One way to determine where to sample the path is to calculate the closest point between the center of the entity and the path. There is no direct support in the library for this. There are quite a lot of ways to approach this subproblem too.
Another approach is to measure progress incrementally by testing the velocity against the current path direction. This isn't usable as a standalone solution since it will encounter significant numerical drift over time, but it might be useful as a supplement to another approach.
2) The orientation can be directly controlled by a SingleEntityAngularMotor whose goal is updated by the path. There is no suitable single constraint to manage the linear component, though.
To start, grab the restricted degrees of freedom. We don't want the roller coaster to jump off the track or fly off to the side. In other words, any linear motion not along the forward/back direction should be removed.
The component of the linear motion that is permitted is that which is aligned with the 'forward' vector along the path:
Code: Select all
var forwardComponent = Vector3.Dot(entity.LinearVelocity, pathForwardDirection) * pathForwardDirection;
So, to find velocity which violates the constraint, subtract the forward component of the velocity:
Code: Select all
var violatingVelocity = entity.LinearVelocity - forwardComponent;
An impulse (equivalently, a velocity change) can then be applied to stop the violation:
Code: Select all
entity.LinearVelocity -= violatingVelocity;
This will run into position drift. Computing the position error (already available if the closest point to the path was computed) and multiplying it by a constant (0.2 works well) and introducing it as an extra modification to the velocity will fix this.
There are also other ways to do it, of course. The carts could roll down the tracks like vehicles with some extra assisting glue forces. A complete physical simulation is also technically possible, if a bit expensive due to the number of time steps per second required for robustness at high speeds. The best implemention depends on your goals
