\Perforce // master depo
|
More than 10 years in the industry, of which 4 at
Teams and Projects
Standards
Validation
Compilation
Automation & Testing
Splash Engine & Merges
Share our learnings
from some AAA projects
mostly from prototypes
years of UE4 work
Find your inspiration!
300 employees
Split across multiple ongoing projects
Some projects use Splash Engine
vanilla + own modules and enhancements
\Perforce // master depo
|
├───Project-A // game project
│ ├───docs
│ ├───raw
│ └───ue4
│ ├───Engine
│ └───Project-A
│ ...
│
├───Project-B // another game project
│ ...
│
├───splash-ue4 // Splash Engine
│ ...
We strive to have multiple independent modules (as opposed to 1 monolithic one)
Helps with encapsulation and architecture
Allows faster iteration
linkage improvements
Editor Hot-Reload
Promotes re-use throughout projects
GenerateModule.cmd
Batch file script that produces
folder structure
initial …build.cs file with good defaults for us
Splash values MASTERY especially in C++
We didn’t have an established coding standard
some attempts to document it in wiki’s
Grow big / Hard to navigate
Get out-of-date quickly
In separate location
outside production source code
Only select few modify or improve them
Nobody has time to read documentation! 😛
Standards are source code files 📑
you can break the build messing with the standard!
Created and improved through code reviews
A system for easy reference and searching
2 files
SplashDamageCodingStandard.h
SplashDamageCodingStandard.cpp
Located in the main source code
ue4/Game/Source/Main/…
Open Source
Applied via code reviews
Takes the pressure off from feeling judgemental
The standard itself is changed though reviews sent to the whole team
If enough up-votes → the proposal gets submitted
…
Poor organisation and practices for assets
… compound over time
… waste productivity
… increase cooking and deployment times
UE4 Editor is easy to modify to
improve workflows
enforce good practices
Less confusion and improves searching & browsing
Prefix
uses initialism rules
Same principles as the Coding Standard
Live in Game/Content/Standard/
We have some basic automatic validators
Best gain for us:
enforcing comment nodes
CI (Continuous Integration) support
validation after submit
nightly builds
Naming Validation
Blueprints Validation
Assets Validation
Automated checker / validator
Editor commandlet
Initialism from asset class name
extra JSON file with exceptions
Disallow names like Test
, Prototype
, Error
Intercept new asset creation…
Disallow import from non-versioned paths
Forbidden example:
adding data from own Desktop folder 💀
Editor commandlet
Basic checks
comment nodes present
public functions / vars must have tooltips
no functions / vars with default names
Future work & ideas
leverage the engine Blueprint Compiler
more complex checks
For all content - done in CI system
Check for missing or bad references
Disregard/Disallow Developer
, Test
folders
historically a major pain point for us
How it works
leverage the cooking process
-COOKALL -DUMPALLWARNINGS -WARNINGSASERRORS
Not viable for large projects ⚠️
explore other possibilities
ex: dependency walker via Editor Asset Registry
Everyday work is very CPU intensive
CPU hardware threads
jump from 8 to 16 substantial (2x)
same from 16 to 32
diminishing returns after
Incredibuild for some projects
expensive - needs to be budgeted for
We also tried Fastbuild
free but more difficult to integrate
Different config and layout per project
Best performer machine
AMD Threadripper 1950x (16c/32t)
full Editor rebuild in ~15min
Orchestration
TeamCity - most projects
Jenkins
In the past we used ad-hoc methods that didn’t scale well
Too tight integrated with the CI orchestrator ❌
Too bespoke for a project - cannot reuse ❌
Hard to debug locally ❌
Now leveraging Epic’s own BuildGraph ✅
Alternative to traditional BuildCookRun
batch commands
XML based scripts
Standardized and reusable set of scripts 📑
Unifies all calling paths
Visual Studio
Editor - Hot Reload
command line
CI systems
Powerful out of the box
some good examples in the Engine
We modified it quite a lot
Our most complex use-case:
prepare zipped Editor binaries
We follow "trunk-based-development"
Only one main dev branch (per project)
split off only for major releases
Everybody submits collaboratively
less overhead, fast iteration 👍
breakages have large impact 👎
Effectively 2 systems working together
Frontend
what the devs interact with
Backend
CI / build-machines
Tools that allow indirect submits to main code base
Off-the-shelf
Visual Studio ReSharper Team City plugin
Internally developed
more project specific
written in C# or Python
Personal Build system
starts CI build configuration in isolation
more configurations → better coverage 😊️
more configurations → stress on build farm ☹️
We came up with compile time-saving solution
rebuild all participating configurations nightly
incremental (non-unity) builds throughout the day
Example:
Editor + Game(PC) + Game(PS4)
Overnight: 1.5-2h on fastest machine
Daily: 5-15 min per commit check
Major productivity booster
Pioneered in one project for 1 year
spreading it to others
Not a silver bullet
Perforce Changelist descriptions
Being verbose is very useful but tiring
We developed tools that assist in:
writing title and description
adding tags like [Feature]
[BugFix]
etc
links to code reviews or JIRA
Perforce Submit validation tool
Changelist formatting
Time of day
to allow time for tests
No commits when build is broken
unless special [BuildFix]
token
Testing plain classes and structs or single UObjects
We enhanced UE4’s own framework
follow Given / When / Then structure
separate standards file
integrated with CI (ex: TeamCity)
setup & tear-down support
Blueprint actors in special setup levels to test more complex interactions
Live under Game/Content/Test/…
Named FTEST_
to follow Epic’s convention and for visibility
Not network capable
Look into recent UE4 additions: Gauntlet
Very useful to access private data from equivalent runtime module
Our solution
MODULENAME_TEST_API
extension to API specifier macros
Player\Runtime\Private\Components\SDPlayerCameraTargetComponent.h
UCLASS()
class PLAYER_TEST_API USDPlayerCameraTargetComponent :
public UActorComponent,
public IBICameraTarget
{
...
Player\Test\Private\SDPlayerCameraTargetComponentTest.cpp
IMPLEMENT_MODULE_TEST(FAttachedToPlayer_GettingAttachmentInfo_ReturnsCameraRootW
{
// Given a camera target component attacher to a player with attachment sock
USDPlayerCameraTargetComponent* CameraTargetComponent = Player->CameraTarget
CameraTargetComponent->SetSocketName(SDPlayerCameraTargetComponentTestHelper
...
UnrealGameSync (UGS)
The concept of Last-Known-Good Editor build
Very useful for non-programmers
we stripped out the compilation support
We refactored the packaging script via BuildGraph
more control, adding debug symbols upload
Automation is an worthwhile investment
Must be done early in lifetime of projects
We extract and re-use the UE work across projects into Splash Engine
game-agnostic engine enhancements & fixes gathered across time
UI components library
Audio utilities
Events, Async Tasks library
Rendering features
Tech-Art utilities (instancing, decal manager, etc)
Majority of projects get seeded from Splash Engine
Downstream integrations
"Engine" tends to be at latest UE4 version
projects update at their own pace
Upstream integrations
some projects will bubble-up important features
Updating a game project to latest UE4 version…
/splash-ue4
|
├───/clean
│
│
├───/main
|
|
├───/project-A
├───/project-B
├───...
/splash-ue4 |
| |
├───/clean <---------------' copy latest UE version
│ (allows nice incremental diffs)
│
├───/main
|
|
├───/project-A
├───/project-B
├───...
/splash-ue4
|
├───/clean -----------------.
│ | merge across to main branch
│ | (also update any plugins we use)
├───/main <----------------'
|
|
├───/project-A
├───/project-B
├───...
/splash-ue4
|
├───/clean
│
│
├───/main
|
|
├───/project-A <-----------.
├───/project-B |
├───... | merge from main game repo
| (prepare staging area with latest game advances)
/splash-ue4
|
├───/clean
│
│
├───/main ------------------.
| | merge latest engine to game staging
| | (solve conflicts in isolation from game project)
├───/project-A <------------'
├───/project-B
├───...
/splash-ue4
|
├───/clean
│
│
├───/main
|
|
├───/project-A >-----------.
├───/project-B |
├───... | merge from staging to game project
| (game project now updated to latest UE)
Allows us to have quick integrations
Decouples main game dev work from integration work
Needs dedicated resources otherwise it atrophies
we have small Tech Sharing group
We did the UE4 4.21 integration following all this
…pre-commit everything
…ran all the CI tests
and then when opening the Editor…
@valentin_galea
We’re hiring!
Special thanks to my Core-Tech team and the BM/LV team
All images and material © Splash Damage
"Megaphone" and "Teams" icons by https://www.flaticon.com/authors/eucalyp under Creative Commons BY 3.0