Coding Standard
We follow the published Epic C++ Coding Standard wherever possible. There are some minor cases where we will diverge with an opinionated purpose, with inspirations from Michael Allar’s UE5 Style Guide as well.
Included with the project is an EditorConfig which attempts to enforce our coding standard while working on the TestProject.
File Layout
Every C++ source file (.h / .cpp) starts with the standard two-line header — the EditorConfig file_header_template enforces this, and the SonarQube job will flag headers that drift from it:
// Copyright dotBunny Inc. All Rights Reserved.
// See the LICENSE file at the repository root for more information.
Headers use #pragma once rather than include guards, and module APIs follow Unreal's standard Public/ / Private/ split. Inside Public/, headers are organized into themed subfolders that mirror their logical grouping — for example, Math/, Types/, Macros/, and Developer/ under NexusCore. New plugins should follow the same shape; the documentation site mirrors it under types/<subfolder>/.
Every plugin exposes a single-namespace minimal header (e.g. NActorPoolsMinimal.h) and a public log category declared with <MODULE>_API DECLARE_LOG_CATEGORY_EXTERN(LogNexus<Module>, …). Module classes are FN<Name>Module and use the N_IMPLEMENT_MODULE macro from NModuleMacros.h.
Naming Conventions
NEXUS-owned types insert an N after the standard Unreal type prefix so they are immediately distinguishable from engine and project types in editor browsers, autocomplete, and stack traces:
| Kind | Prefix | Example |
|---|---|---|
UCLASS (UObject-derived) | UN | UNActorPoolSubsystem |
UCLASS (Actor-derived) | AN | ANKillZoneActor |
USTRUCT | FN | FNPositionRotation |
UENUM | EN | ENCardinalDirection |
UINTERFACE | IN / UN | INActorPoolItem / UNActorPoolItem |
| Module class | FN…Module | FNCoreModule |
Other rules:
- Macros are prefixed
N_(e.g.N_WORLD_SUBSYSTEM,N_TEST_SMOKE,N_TRUE_FALSE). Reserve all-capsN_identifiers for macros. - Namespaces for compile-time constants and lightweight helpers nest under
NEXUS::<Subsystem>::<Group>— seeNEXUS::VersionandNEXUS::Core::CardinalDirection. - Log categories follow
LogNexus<Module>(e.g.LogNexusCore,LogNexusActorPools). - Booleans use the
bprefix on locals, parameters, and fields (bIsAttachedToActorPool) — enforced by EditorConfig. - Prefer
int32overintto remove ambiguity between 32-bit and 64-bit values.
Formatting
The EditorConfig is the source of truth, but in summary:
- Tabs for indentation (width 4); access specifiers are not indented relative to the class brace.
- Allman braces — opening brace on its own line for namespaces, types, and functions.
- Max line length of 150 characters.
- Pointer/reference alignment is left (
Type* Name, notType *Name).
Comments
Unreal Engine implements a Javadoc-style parsing system, which supports some of the tags of the typical Doxygen spec.
| Tag | Outcome | Description |
|---|---|---|
@param | Parsed | |
@note | Parsed | Converted to "Notes:" inside of tooltips. |
@brief | Passthrough | |
@remark | Passthrough | |
@see | Passthrough | |
@warning | Ignored | |
@return | Parsed |
Any @tag marked as Passthrough will show up in tooltips as-is.
Macros & Boilerplate
Common patterns are wrapped in macros under Public/Macros/. Prefer using these over hand-rolled boilerplate so behavior stays consistent across plugins:
- Module declaration —
N_IMPLEMENT_MODULEinside anFN<Name>Moduleclass body. - World subsystems —
N_WORLD_SUBSYSTEM,N_WORLD_SUBSYSTEM_GAME_ONLY, and theN_TICKABLE_WORLD_SUBSYSTEM_*family inject the standardGet(World)accessors, stat IDs, andShouldCreateSubsystemgating. - Tests —
N_TESTplus its priority/filter variants (N_TEST_SMOKE_HIGH,N_TEST_PERF_CRITICAL, etc.) auto-tag tests with[NEXUS]and the appropriate filter so they show up correctly in Automation. - General helpers —
NGeneralMacros.hprovides small utilities likeN_TRUE_FALSE,N_STRINGIFY, andN_CONCATfor log/format expressions.
When a public UCLASS, USTRUCT, UINTERFACE, or UENUM is documented on this site, link back to its page from the header's Doxygen comment using @see so the type's tooltip points users at the live documentation:
/**
* ...
* @see <a href="https://nexus-framework.com/docs/plugins/<plugin>/types/<type>/">UNExampleType</a>
*/
Choices
- Prefer to use
int32overintto match typedef and remove any ambiguity between 32-bit and 64-bit values. - Prefer
using enum E…;insideswitch/lookup blocks to keep enumerator references readable — seeFNCardinalDirectionUtilsfor the pattern. - Prefer
FORCEINLINEaccessors on subsystemGethelpers and other one-line wrappers; the subsystem macros already do this.
ReSharper Warnings
We disable warnings which are considered expected behaviour.
Potential GC Of Private Raw Pointers
// ReSharper disable once CppUE4ProbableMemoryIssuesWithUObjectsInContainer
Enumeration Naming
// ReSharper disable IdentifierTypo, CppUE4CodingStandardNamingViolationWarning
...
// ReSharper enable IdentifierTypo, CppUE4CodingStandardNamingViolationWarning
SonarQube Analysis
A special thanks to the folks at SonarSource for the free static analysis of the framework, on every commit. ❤️
Tags
We primarily are using a tag based exclusion method when a rule needs to be violated.
// #SONARQUBE-DISABLE-<LANGUAGE>_<RULE> <reason>
...
// #SONARQUBE-ENABLE
Source File Exclusions
.github/**SourceAssets/****/NexusPicker/Private/N*Picker.cpp
Ignore Issues on Multiple Criteria
| Rule Key Pattern | File Path Pattern | Choice |
|---|---|---|
cpp:S3471, cpp:S3576 | ** | This is a developer choice; where the override and virtual specifiers are used easily identify methods being replaced from the Super. This also matches the practice done in the Unreal Engine codebase. |