VR Hydraulic simulator
Description
Virtual reality prototype simulator of hydraulic circuitry, for a vocational school’s hydraulic curriculum.
Created in Unreal Engine 5, main developer role, 3D modelling and texturing done by a contractor, 20 full days of development.
The main working station was based on the same hydraulic station at the school, where they would do the assemblies and experiments of hydraulic circuits.
Responsibilities
- Project management
- Hydraulic simulation
- Interaction & Locomotion
- Grabbing
- Drawing hoses
- Tutorial
- Level & Environment design
Implementation
Hydraulic simulation
The simulator is based on a simple graph structure and a breath first search analysis and graph construction. The core of the system is written in C++ plugin
- Core classes
- Hydraulic Subsystem - Unreal subsystem that constructs networks and updates individual devices with it’s own update loop.
- Network - simple class that represents a hydraulic circuit network, stores all ports in the network, open ports, ports that stop at a device.
- Device - Actor class that represents a device with ports in the hydraulic circuit, updated by the subsystem.
- Port component - component that makes up the hydraulic circuit network, unique ID, contains it’s neighboring connections.
- Connections - structs of non-directional and uni-directional references to connected ports.
void USDESubsystem::ConstructNetworks()
{
//Clear Networks
Networks.Empty();
//Mark all ports dirty
for(const auto& PortComponent:PortComponents)
{
PortComponent->PortData.bIsDirty = true;
}
TArray<FGuid> Traversed;
TArray<FGuid> Visited;
TArray<FSDEUniConnection> DeadEnds;
//BFS for networks
for (int i = 0; i < OriginPortComponents.Num(); ++i)
{
//check if dirty
if (!Visited.Contains(OriginPortComponents[i]->PortID))
{
TQueue<FSDEUniConnection> Queue;
Visited.Add(OriginPortComponents[i]->PortID);
OriginPortComponents[i]->PortData.bIsDirty = false;
TArray<USDEPortComponent*> ConnectedPorts;
//ConnectedPorts.Add(PortComponent);
Queue.Enqueue(OriginPortComponents[i]->PortID);
while(!Queue.IsEmpty())
{
FSDEUniConnection UniConnection = *Queue.Peek();
Queue.Pop();
Traversed.Push(UniConnection.PortID);
TArray<FSDEUniConnection> PortConnections = PortMap[UniConnection.PortID].connections;
bool deadEnd = true;
for(const auto uniConnection: PortConnections)
{
if(!Visited.Contains(uniConnection.PortID))
{
deadEnd = false;
Visited.Add(uniConnection.PortID);
Queue.Enqueue(uniConnection.PortID);
}
}
if(deadEnd)
DeadEnds.Add(UniConnection);
}
}
USDENetwork* Network = NewObject<USDENetwork>();
for (auto PortID : Traversed)
{
USDEPortComponent* PortComponent = PortMap[PortID].component;
if(PortComponent)
{
Network->PortComponents.Add(PortComponent);
PortComponent->Network = Network;
PortComponent->PortData.bIsDirty = false;
}
}
for (auto UniConnection : DeadEnds)
{
USDEPortComponent* PortComponent = PortMap[UniConnection.PortID].component;
if(PortComponent)
{
Network->PortComponents.Add(PortComponent);
PortComponent->Network = Network;
PortComponent->PortData.bIsDirty = false;
//If connection goes from external to a Device plug, we stopped at a device that is blocking the path
if(UniConnection.ConnectionType == ExternalConnection && PortComponent->PortData.PortType == Device)
Network->DeviceEnds.Add(PortComponent);
//Else we are at a dead end
else
Network->DeadEnds.Add(PortComponent);
}
}
Networks.Add(Network);
}
OnNetworksReconstruct.Broadcast();
}
- Device implementation


-
Debug tooling
Debug tooling and editor scripts were made to accelerate building and testing the simulator codebase in editor and in VR.
Interaction
The interaction system is an extension of the Unreal VR template functionality, support hovering, drawing hoses, gameplay tags, setting active state, etc.
Controller trigger pull interacts with the held component, or a interactable object nearby, else it just notifies any of the VR pawn’s components if they are interested in a trigger pull.
Drawing hoses
The hose drawing component works based on the VR pawn’s interaction events, handling starting drawing, adding points, finishing drawing and cancelling drawing.
Tutorial
A quick tutorial menu was created to introduce the user to the VR controls and how to assemble and use a simple hydraulic circuit. The menu consists of a introduction message, VR controller button scheme and video tutorials for locomotion, interaction and the assembly of a simple hydraulic circuit.
Drawing hoses
The hose drawing component works based on the VR pawn’s interaction events, handling starting drawing, adding points, finishing drawing and cancelling drawing.
Level & Environment design
Left: hydraulic station from the school. Right: digital replica of the hydraulic station
The table and hydraulic component modelling was done by a hired contractor, while the environment was prepared by myself, with Marketplace assets.
The target platform was Meta/Oculus Quest 2, but because of the tight time constraints and shader issues, the final build was on Windows.