Between the Folds #012 - Springpeople Rails


Idea

Last time we described our SpringPeople in all their different variations. Since some of them are important for the main story, to guide the player towards important POIs they need to be able to move around the place. To this end, we came up with a rail system. 


Core

We based the SpringPeopleRails on an older system we called ActorFollowSpline, which consists of an actor reference and a spline, along which the actor is moved bit by bit.

For the SpringPeopleRails, we had additional requirements like moving multiple Springies in different directions on one spline. So, we changed the ActorFollowSpline code accordingly and created a BP child-class to handle the specifics for the SpringieRails.

For our additional requirements, we created the struct ActorToMoveData, which consists of an actor-reference, the current distance along the spline, the movement direction and a flag bIsMoving.

(The ActorFollowSpline can move actors of any class along its path.)


Movement

We move all Actors by updating their distance along the spline and then overwriting their position directly each frame. The speed at which the actors should move can be constant or defined through a custom curve in order to allow different velocities at different portions of the spline.

We calculate each actor’s position using the function Spline->GetTransformAtDistanceAlongSpline() and update it directly with Actor->SetActorLocation().

(Code for calculating and updating the next desired position of an actor.)


Inherit Rotation

As shown in the code sample above, we also use the bool bInheritRotation. This flag decides if all actors should always remain upright, or if their rotation should follow the spline they are moving along.

(A Springie hiking up a hill (left) without and (right) with bInheritRotation set.)


Collisions

Whenever multiple actors are on one Rail, they might collide with other actors on or off the rail. We decided that each Blueprint-variant of the ActorFollowSpline should be able to handle this by themselves. For this, we move the actors with sweep enabled in the C++ base-class, which doesn’t advance the actor if it hits something on its way. Then, we fire a BlueprintImplementableEvent OnMovedActorSweepHit to let the BP-implementation handle the details. In the BP_SpringPeopleRail class, we decided that if two Springies hit one another, both should change directions and move away from one another.

(Springies change direction when bumping into one another.)


PathBehaviors

Different splines might require different movement behaviors of the actors on them. For this, we defined four main PathBehaviors that specify how the actors move along them. These PathBehaviors are specified per spline, but can be changed at runtime:

  • GoToEnd: Simply move towards the end of the rail. Once the actor is at the end, they can do one of three things: Stop, move to another rail, or destroy itself.
  • Loop: Continuously move along the spline. If the end is reached, teleport to the start and go around once more.
  • ReverseOnEnd: Continuously move along the spline.Turn around and go back once the actor has reached a spline end.
  • FollowActor: Always move towards the spot that is closest to a specified actor. We use this behavior to have the Springies follow the player around.
(Quick examlpe of the Follow behavior.)

We also implemented functions to move an actor to a specific point. This point can either be on their current spline or on a different specified one, and the actor can be told to move or teleport there.


Visuals

Rails

For the rails, we once again resorted to our trusty friends - Splines and SplineMeshes. The Splines define the shape of the rails and for each segment of the spline, the rail is represented by a SplineMesh.

The setup and construction of the rails works similar to our Splinecart rail system, as described in our third devlog entry.

Decoration

Since the spots where our Springies stop and engage with the player are usually predefined, we allowed our designers to place custom meshes at any given point on the spline to denote those special areas. For performance’s sake, we use InstancedStaticMeshes to render them.

(Final placed rail with decorations at the locations where the Springie can stop.)

With this system we are able to move our Springies (and any other otherwise “static” actors) around! As always, don’t hesitate to ask if you have any more questions!

- Andi, Ralf

Leave a comment

Log in with itch.io to leave a comment.