Dead Pedal

- Lead Programmer
- UE5
- Git
- Jenkins
- Google Cloud
Details
As Lead Programmer, I maintained an Unreal CI/CD pipeline, iterated on our car physics, and established the feature timeline for the programming team.
The Game
In Dead Pedal, you play as John D. Pedal in a post-apocalyptic world, fending off ruthless marauders and mutant beasts. Upgrade your car with new weapons and customizations by taking out various factions. When you’re ready, take on THE WORM and bring peace back to the Mojave.
Planned Steam release: May 2023.
Timeline
Development began in September 2022. I worked with a cross-disciplinary team to create Dead Pedal for the Champlain College Game Studio. We chose Unreal Engine 5 to take advantage of Chaos Physics, World Partition, and its rendering pipeline.
Technical Details
Google Cloud
We identified build iteration speed as a risk. To mitigate this, we created a CI/CD build server that made builds more accessible and consistent. This ensured the team had confidence in the current state of the game every week.
Overview
The pipeline consisted of:
- Git repository
- Jenkins server
- Google Cloud build agents
- Google Cloud buckets
- Team notifications via Discord
Jenkins Server
The Jenkins server managed builds, authentication, and artifacts. Anyone on the team could trigger a build, removing bottlenecks.
Build Agents & Buckets
Builds were processed by Google Cloud VMs and uploaded to Cloud Buckets for quick access. The team received notifications once a build was ready.
Conclusion
This build system improved confidence and iteration speed and opened the door for future automation like playtesting and analytics.
Mission System
We designed a scalable, modular mission system using C++ and Blueprint. It allowed designers to create open-world missions without heavy technical support.
Tutorials
I created video walkthroughs to document the setup of mission blueprints and triggers:
Blueprint Mission
Each mission was a Blueprint class inheriting from a common C++ base. Behavior could be overridden for different mission types.
/*
BP_Mission.h
*/
UFUNCTION(BlueprintCallable)
virtual void MissionComplete();
UFUNCTION(BlueprintCallable)
virtual void MissionStart();
/*
BP_Mission.cpp
*/
void ABP_Mission::MissionComplete()
{
// Flag Mission as complete
missionComplete = true;
// Callback to Mission manager
mdOnMissionComplete.Broadcast();
// Unique Mission Callback
OnMissionComplete();
}
void ABP_Mission::MissionStart()
{
// Flag Mission as not complete
missionComplete = false;
// Callback to Mission manager
mdOnMissionStart.Broadcast();
// Unique Mission Callback
OnMissionStart();
}Mission Manager
Managed active missions, UI updates, and completion logic.
/*
BP_MissionManager.cpp
*/
void AMisisonManager::BindMissionToActive(
ABP_Mission* newMission)
{
// Make sure newMission is active
if (newMission == nullptr) {
UE_LOG(LogTemp,
Warning,
TEXT("Failed to bind Mission: Mission active"));
return;
}
// Set Active mission
activeMission = newMission;
// Blueprint implementable callback
activeMission->OnMissionBind((AMisisonManager*)this);
// Bind Active Mission Delegates
activeMission->mdOnMissionComplete.AddDynamic(
this, &AMisisonManager::OnMissionComplete);
activeMission->mdOnMissionStart.AddDynamic(
this, &AMisisonManager::OnMissionStart);
}
void AMisisonManager::UnbindActiveMission()
{
if (activeMission == nullptr) return; // No Mission to unbind
// Unbind Mission Delegates
activeMission->mdOnMissionComplete.RemoveDynamic(
this, &AMisisonManager::OnMissionComplete);
activeMission->mdOnMissionStart.RemoveDynamic(
this, &AMisisonManager::OnMissionStart);
// Blueprint implementable callback
activeMission->OnMissionUnbind((AMisisonManager*)this);
// Set Active Mission to null
activeMission = nullptr;
}Access
If you’re interested in using or learning more about these tools, reach out: