Transportation System

I built this transportation system in C++ to convey users in cable cars between locations in a mountainous area. I originally built the system using Blueprints, however this was not performant, lacked flexibility and had runtime glitches.

I created the below scene from scratch using Blender and Houdini to demonstrate the system’s capability. As the scene was created for personal use, it also serves as a laboratory to test out new features in UE5.

Plugin Authoring

To make the code as reusable and portable as possible, I packaged all the required C++ classes, Blueprint classes, float curves, geometry and materials etc. into an Unreal Engine plugin. Now every time I open Unreal, with my plugin activated, I have a base layout of a simple cable car system that can be used for a multitude of different purposes.

What’s even more interesting is this system isn’t limited to just cable cars. Any mode of transport that operates on a cable or rail could be animated with this system (trams, trains, cable cars etc.).

System Variables

I developed the system to have numerous variables so artists can easily configure the desired setup. When the ‘Number of Cars’ input is changed, the system spawns the corresponding number of cars, equally distributing them on the spline.

If the velocity profile of the cars needs to be changed, this can be achieved by altering the graph in the ‘Movement Curve’.

Code Base Structure

The following diagram shows the signal flow and interaction between the relevant classes. It’s good practice to create Blueprint children of C++ classes so visual elements such as meshes, materials, animations etc. can be easily viewed and configured by artists. I have used a game instance to communicate between the different classes allowing me to set numerous important float and boolean variables when required. This is more elegant than casting, because it has a lower memory footprint. There are 6 different location types in which the player (VR Pawn) can be, which are denoted by the (+) sign below. The 3 different booleans work together to discern where the player is, thus allowing the relevant downstream logic to occur.

Float Curve

The position of each spawned cable car follows the graph in the below screen shot. The x-axis is time, and the y-axis is the position along the spline. Each car has an offset in time which depends on the number of cable cars on the loop. If many cars are spawned, the time offset will be lower. Likewise fewer cars, results in a greater offset. This gives the resultant effect whereby cars group closer together inside the stations, but move further apart between stations, like in real life. This happens because the change in position is much greater per unit time between stations compared to inside the stations - the gradient is larger between stations. This is seen below; Δp changes, but Δt remains constant.

Cable Car Speed

The global speed of the entire system can also be changed to suit the project’s requirements. This parameter became essential when tuning the car speed inside the stations because passengers of all ages need to walk into the moving car. I found it especially useful using a third person character to help me tune the car speed as I could clearly see the normal walking speed of the character in relation to the cars.

Virtual Reality

To enable the system to function in VR I added a box collision volume to the individual cable car and a capsule to the VR pawn. This meant whenever the VR pawn overlapped the box collision of a car I could set a boolean to either ‘Boarded’ or ‘Not Boarded’. When the boolean was ‘Boarded’ and when the user was inside a station, the location of the VR pawn would equal the location of the moving cable car. When the user is outside the bounds of a station, teleportation is disabled so that users can’t eject themselves out of the car between stations.

Cable Car Actor

This is the individual cable car actor that is spawned into the main system. This includes the box collision that allows the boolean to be set to ‘Boarded’ or ‘Not Boarded’. There is also a float curve which drives the animation of the doors. Using a C++ game instance, I can access variables from this actor in the main system, for example door opening speed and distance. This means all variables can be accessed and refined in one place, making it easy for artists to configure.

Door Opening Parameters

I made the system flexible such that when different cable cars are used, the artist can easily specify the opening distance and speed at which the doors open.

A volume is placed at each station and when each cable car overlaps this volume it triggers the door opening animation, the opposite is true when the cars leave the station. If the artist wishes to change the point at which the doors open, they can easily re-size the volume.

AI Non-Playable Characters

Using Chat-GPT, it’s possible to have real-world conversations with NPCs. After writing background information for the character, they are able to give unique and insightful responses in real time, specifically tailored to the players speech.

Runtime Actions

The NPC is also aware of different locations in the scene. When asked to get a ticket from the ticket booth, they can navigate to the booth and then back to the player; they can even follow them should the player change location.

Lower Station

After collecting many references of mountainous cable car stations, I built all the station geometry from scratch in Blender. The mountains were created using procedural nodes in Houdini.

I textured the scene using quixel materials and applied many decals, some of which were custom made in Photoshop, to add as much realism as possible to the scene.

I overlayed 3 layers of procedural noise on the floor material to add micro and macro variations to the base colour, roughness and normal channels. This prevented any tiling, increasing the scene’s realism.

Nanite Experiments

As an experiment, I duplicated the project and enabled Nanite on all the static meshes. Interestingly, I observed there to be no change in the frame rate. Both projects run at 30 fps which is the lower limit I work to for a third person real-time scene like this.

Performance

The largest computational load in the scene are the animated MetaHumans walking along a spline. I therefore reduced the maximum texture resolution on the MetaHumans to 1K and forced them to remain on LOD 5 out of 8. From my experiments I found the MetaHumans to be more performant by forcing them to stay on one LOD, rather than dynamically changing.

Although there were many decals and at times up to 100 cable cars, I found both of these factors to have an insignificant impact on the frame rate compared to the MetaHumans. I therefore reduced the number of MetaHumans in the scene to re-gain the frame rate. It’s worth noting that only approximately one third of the characters in the scene are MetaHumans, the others were sourced elsewhere because I needed some more lightweight characters.

Modelling

This clip shows a car slowing down as it approaches the second station.

I modelled the cable car poles, mechanisms and pulleys from scratch using Blender. I tried to model as much detail as possible to increase the realism of the scene.

Houdini Geometry

I created the mountains in Houdini by procedurally displacing a grid of vertices. After tuning the amplitude, frequency, and harmonics of the noise I added two layers of distortion to create a more realistic, high fidelity mesh. The first distortion layer had a low amplitude and a higher frequency, the second layer had a higher amplitude, but a lower frequency. I did this to add fine detail, but also broader irregularities to the geometry.

Blender Geometry

Animated Station Sign

To create the animated station sign above the cable cars, I made an image texture using Photoshop with the text I required. I then wrote a Blueprint to animate the texture so it would move horizontally in a linear fashion across the mesh. I ensured I uv unwrapped the geometry such that the screen was one uv island so the texture would appear correctly.

I used a low resolution for the texture to replicate the pixels of screens found in stations. I then applied a material with a small emissivity to produce a subtle orange glow from the text.

This clip shows the descent back down the mountain toward the first station.

Next
Next

Unreal Engine Editor Plugins