top of page
Writer's pictureDoğa

Creating Half-Life's "Episode 3" in Unreal Engine: Project Borealis

Updated: Jan 30, 2023

Introduction

On August 25th 2017, a plot synopsis was published on the blog of Half-Life writer Marc Laidlaw, which is now believed to be an overview of the intended plot of the long awaited Half-Life 2: Episode 3.


From the ensuing chaos in the Half-Life community, Project Borealis was formed, and it is now an over 80 person team of developers dedicated to revisiting the Half-Life series with a fresh new episode for fans of the series, old and new, to enjoy.


Project Borealis is being created on Unreal Engine 4 to give it the updated look that Half-Life has deserved after all these years. We're aiming to make the game feel just as familiar as long-term fans will expect it to, while modernising the graphics and technology.

I've joined to the PB team in March 2018, and was an active developer in the team until early 2020. I've worked on lots of gameplay systems, reverse engineered lots of features from Source Engine into Unreal Engine, maintained our own Unreal Engine fork, and also worked on improving the development pipeline for the development team with a CI server & workspace synchronization tools. I also participated in team management related topics as the programming team co-lead for like a year.


Advanced Destruction System

Destruction system was one of the biggest systems I've worked on Project Borealis. It's completely written from scratch, and various hacks & low level implementations were made to get Nvidia APEX destruction plugin under our control. Otherwise, it was not so possible to control how objects are fractured, and more importantly, under which conditions objects can be fractured. After weeks of hard work & incoming feedback from level designers, I've achieved the results on the video below.


At some point on the development, we also experimented with Nvidia's new destruction plugin, and fully switched our system into Blast:



Crowbar

I've also worked on the crowbar, the most iconic weapon in Half-Life arsenal. While implementing this weapon, we wanted to change how it worked previously in Half-Life 2, which was just a ranged weapon with very short fire range, and hits were registered with a single line trace from player camera to the aimed point. Instead of following that path, we wanted to implement it as a proper melee weapon by tracing the tip of crowbar. So that, swinging & hitting the enemies with the crowbar would feel better.


Gravity Gun

Another weapon I've worked on was gravity gun. My main goal with gravity gun was highly optimizing the object pull, punt & object scan features. Since all of those features needs gravity gun to actively tick & scan nearby objects with line tracing, I've utilized async tracers to reduce overhead in main game thread during nearby object scanning.


During the implementation, we wanted to make it feel more powerful during pulling & punting objects around. To achieve that, I've implemented a force field system, which affects other objects around the target object. For example, when you pull an object, the other objects close to the target will move towards to it. Or vice versa, when you punt an object, other objects around will get a slight impact from that. Here is a quick demonstration for that feature:


Another feature we've worked on was the "Vortex Mode", which is a similar to "Super Charged Gravity Gun" on last chapter of Half-Life 2. If gravity gun is switched to that mode, it will be able to pull multiple objects, gather them together, and launch them back towards player's aim direction. We thought this could be an interesting feature for a specific chapter of the game, and developed it further.


The biggest challenge on that feature was keeping it scalable for high amount of objects, to prevent possible performance issues on low-end systems. To achieve that, I've implemented various parallelized code blocks to utilize all threads during required physics calculations to pull/punt multiple objects. Results was satisfying enough, as seen below. We're able to pull around 200-300 physics bodies without any hitches on CPU time.


You can also watch a long gameplay video with gravity gun on our physics update video:


Optimizations... Lots of...

During the development, we always aimed for having a performance optimized source code to target more low-end systems.

One of the most noticiable optimizations I've made was about AI characters. Previously, with about 20 zombies in a same scene, our FPS was dropping around 60, which was not acceptable for scalability of AI count. So that, I've started debugging our source code, and investigate profiler to discover possible bottlenecks.

The biggest bottleneck we had was the cost for simulation of skeletal meshes of zombie characters. So, we've started to research possible solutions to reduce performance cost of simulating our skeletal meshes for enemy characters. The most acceptable solution we've found was optimizing our LOD setup, and utilizing "Update Rate Optimization". Update Rate Optimization was something new during those days, so I had to figure out how to use it myself by checking out engine source code. It was an optimization method, which decreases skeletal mesh tick rate for further characters from the player. After successfully implementing that feature and binding it to LOD levels, we got visible amount of FPS & CPU time boost. A short demonstration can be watched below:


Weapon Camera Lag

Weapon camera lag is a feature I've reverse engineered from Source SDK. After successfully porting required position & rotation calculations into Unreal Engine, results was satisfying enough as seen below.


Bullet Shell Particle Effects

I also had a chance to work with Unreal's new particle simulation module, Niagara. By binding various variables like bullet eject direction, speed etc. into Niagara particle system in C++ code, I was able to achieve some good looking shell eject particle effect as seen below.


Development Pipeline Improvements, CI Server & Engine Maintenance

During the development, I've also helped on improving our pipeline, and maintained our Unreal Engine fork from time to time.

Git was being used as our main source control system, and most of level designers, 3d artists, and animators didn't know how to use Git. Majority of the development team was having problems with syncing their workspaces with latest changes because of that. I've developed a python script to automating synchronization of local workspace & resolve possible merge conflicts during the synchronization. The script is called PBSync, and it's currently open sourced under our Github team account: https://github.com/ProjectBorealis/PBSync

Our Unreal Engine fork can be accessed from https://github.com/ProjectBorealisTeam/UnrealEngine (Unreal Engine repository access is required)

Lastly, I've also built a Continuous Integration server with Team City to automatize our versioning, code quality checks, engine builds, branch synchronization, and playable build deployments:


263 views0 comments

Comentários


bottom of page