├── LICENSE └── README.md /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Daedalic Entertainment 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Unreal 4 Coding Conventions 1.0 2 | 3 | This document summarizes the high-level coding conventions for writing Unreal 4 client code at Daedalic Entertainment. They are based on the official Unreal Coding Standard: 4 | 5 | * https://docs.unrealengine.com/latest/INT/Programming/Development/CodingStandard/index.html 6 | 7 | The goal is to make it easier to work in similar teams inside and outside the company, as well as have client code blend in with other code of the Unreal API. We are providing a complete summary here in order to allow people to understand the conventions at a glance, instead of having to open multiple documents. Our coding conventions are numbered, which makes it easier to refer to them in code reviews. 8 | 9 | In case we've missed recent changes to the official Unreal Coding Standard, or you can spot any other issue, please [create a pull request](https://help.github.com/articles/creating-a-pull-request/). 10 | 11 | 12 | ## 1. Namespaces 13 | 14 | 1.1. __DO NOT__ use namespaces to organize your game classes. Namespaces are not supported by UnrealHeaderTool, so they can't be used when defining `UCLASS`es, `USTRUCT`s etc., and we don't want to put half of our game code in a namespace and the other half in global scope. 15 | 16 | 1.2. __DO__ add a prefix to all class and struct names, based on your project name. 17 | 18 | 19 | ## 2. Files 20 | 21 | 2.1. __DO__ use PascalCase for file names, with the project name prefix, but without the type prefix (e.g. `AHOATCharacter` goes into `HOATCharacter.h`). 22 | 23 | 2.2. __DO__ write header files with the following structure: 24 | 25 | * `#pragma once` 26 | * `#include` of the pre-compiled header, if any (e.g. `#include "HOATPCH.h"`) 27 | * `#include` of the base class header, if any (e.g. `#include "GameFramework/Character.h"`) 28 | * `#include` of the generated class header (e.g. `#include "HOATCharacter.generated.h"`) 29 | * delegate declarations 30 | * forward declarations for any referenced engine or game types 31 | * type definition 32 | 33 | 2.3. __DO__ define classes with the following structure: 34 | 35 | * constructors 36 | * destructor 37 | * public `override` functions (e.g. `BeginPlay`, `Tick`, `GetLifetimeReplicatedProps`) 38 | * public functions 39 | * public event handlers 40 | * `virtual void Notify...` functions 41 | * `UFUNCTION(BlueprintImplementableEvent) void Receive...` functions 42 | * `UPROPERTY(BlueprintAssignable)` delegate properties 43 | * operators 44 | * public constants 45 | * public `UPROPERTY`s 46 | * protected `override` functions 47 | * protected functions 48 | * protected constants 49 | * protected fields 50 | * private functions 51 | * private constants 52 | * private fields 53 | 54 | Within each of these groups, order members by name or logical groups. 55 | 56 | 2.4. __DO NOT__ cover more than a single feature in each file. Don't define more than one public type per file. 57 | 58 | 2.5. __DO__ leave a blank line at the end of the file to play nice with gcc. 59 | 60 | 61 | ## 3. Includes 62 | 63 | 3.1. __DO NOT__ include unused headers. This will generally help reduce the compilation time, especially for developers when just one header has been modified. It may also avoid errors that can be caused by conflicts between headers. If an object in the class is only used by pointer or by reference, it is not required to include the header for that object. Instead, just add a forward declaration before the class. 64 | 65 | 3.2. __DO NOT__ rely on a header that is included indirectly by another header you include. 66 | 67 | 68 | ## 4. Classes & Structs 69 | 70 | 4.1. __DO__ use PascalCase for class names, e.g. `AHOATCharacter`. 71 | 72 | 4.2. __DO__ add type prefixes to class names to distinguish them from variable names. For example, `FSkin` is a type name, and `Skin` is an instance of a `FSkin`. UnrealHeaderTool requires the correct prefixes in most cases, so it's important to provide them. 73 | 74 | * Template classes are prefixed by `T`. 75 | * Classes that inherit from `UObject` are prefixed by `U`. 76 | * Classes that inherit from `AActor` are prefixed by `A`. 77 | * Classes that inherit from `SWidget `are prefixed by `S`. 78 | * Classes that are abstract interfaces are prefixed by `I`. 79 | * Enums are prefixed by `E`. 80 | * Most other classes are prefixed by `F`, though some subsystems use other letters. 81 | 82 | 4.3. __DO__ prefix boolean variables by `b` (e.g. `bPendingDestruction` or `bHasFadedIn`). 83 | 84 | 4.4. __DO__ uppercase the first letter of acronyms, only, e.g. `FHOATXmlStreamReader`, not `FHOATXMLStreamReader`. 85 | 86 | 4.5. __DO__ add a virtual destructor to classes with virtual member functions. 87 | 88 | 4.6. __DO__ mark classes that are not meant to be derived from as `final`. This should be the default for non-interface classes. Care has to be taken when removing the `final` keyword from a class when inheritance is required. Classes that are already derived don't need to be marked as `final` by default: In the most common case there is no reason to prevent further inheritance. 89 | 90 | 4.7. __DO__ use a non-virtual destructor in `final` classes unless they are already derived. 91 | 92 | 4.8. __DO__ use `struct`s for data containers, only. They shouldn't contain any business logic beyond simple validation or need any destructors. 93 | 94 | 95 | ## 5. Constructors 96 | 97 | 5.1. __DO__ mark each constructor that takes exactly one argument as `explicit`, unless it's a copy constructor or the whole point of the constructor is to allow implicit casting. This minimizes wrong use of the constructor. 98 | 99 | 100 | ## 6. Functions 101 | 102 | 6.1. __DO__ use PascalCase for functions names. 103 | 104 | 6.2. __DO NOT__ add a space between function name and parameter list: 105 | 106 | // Right: 107 | void Tick(float DeltaSeconds); 108 | 109 | // Wrong: 110 | void Tick (float DeltaSeconds); 111 | 112 | 6.3. __DO__ pass each object parameter that is not a basic type (`int`, `float`, `bool`, `enum`, or pointers) by reference-to-const. This is faster, because it is not required to do a copy of the object. Also, this is required for exposing the property in blueprints: 113 | 114 | bool GetObjectsAtWorldPosition(const FVector& WorldPositionXY, TArray& OutHitResults); 115 | 116 | 6.4. __DO__ prefix function parameter names with `Out` if they are passed by reference and the function is expected to write to that value. This makes it obvious that the value passed in this argument will be replaced by the function. If an `Out` parameter is also a boolean, put the `b` before the `Out` prefix, e.g. `bOutResult`. 117 | 118 | 6.5. __DO__ flag methods as `const` if they do not modify the object. 119 | 120 | 6.6. __CONSIDER__ writing functions with six parameters or less. For passing more arguments, try and use `structs` instead, and/or refactor your function. 121 | 122 | 6.7. __CONSIDER__ using enum values instead of boolean function parameters. 123 | 124 | // Right: 125 | ShowMessageBox(TEXT("Nice Title"), TEXT("Nice Text"), MessageBox::MESSAGEBOX_BUTTONS_OK); 126 | 127 | // Wrong: Meaning of third parameter is not immediately obvious. 128 | ShowMessageBox(TEXT("Nice Title"), TEXT("Nice Text"), false); 129 | 130 | 6.8. __AVOID__ providing function implementations in header files. Use inline functions judiciously, as they force rebuilds even in files which don't use them. Inlining should only be used for trivial accessors and when profiling shows there is a benefit to doing so. Be even more conservative in the use of FORCEINLINE. All code and local variables will be expanded out into the calling function and will cause the same build time problems caused by large functions. Don't use inlining or templates for functions which are likely to change over a hot reload. 131 | 132 | 133 | ## 7. Variables 134 | 135 | 7.1. __DO__ use PascalCase for variable names. 136 | 137 | 7.2. __AVOID__ short or meaningless names (e.g. `A`, `Rbarr`, `Nughdeget`). Single character variable names are only okay for counters and temporaries, where the purpose of the variable is obvious. 138 | 139 | 7.3. __DO NOT__ use negative names for boolean variables. 140 | 141 | // Right: 142 | if (bVisible) 143 | 144 | // Wrong: Double negation is hard to read. 145 | if (!bInvisible) 146 | 147 | 7.4. __DO__ declare each variable on a separate line so that a comment on the meaning of the variable can be provided. Also, the JavaDoc style requires it. 148 | 149 | 7.5. __DO__ use portable aliases for basic C++ types: 150 | 151 | * `bool` for boolean values (_never_ assume the size of `bool`). `BOOL` will not compile. 152 | * `TCHAR` for a character (_never_ assume the size of `TCHAR`). 153 | * `uint8` for unsigned bytes (1 byte). 154 | * `int8` for signed bytes (1 byte). 155 | * `uint16` for unsigned "shorts" (2 bytes). 156 | * `int1` for signed "shorts" (2 bytes). 157 | * `uint32` for unsigned ints (4 bytes). 158 | * `int32` for signed ints (4 bytes). 159 | * `uint64` for unsigned "quad words" (8 bytes). 160 | * `int64` for signed "quad words" (8 bytes). 161 | * `float` for single precision floating point (4 bytes). 162 | * `double` for double precision floating point (8 bytes). 163 | * `PTRINT` for an integer that may hold a pointer (_never_ assume the size of `PTRINT`). 164 | 165 | 7.6. __DO__ put a single space between the `*` or `&` and the variable name for pointers or references, and don't put a space between the type and `*` or `&`. For us, the fact that we are declaring a pointer or reference variable here much more belongs to the type of the variable than to its name: 166 | 167 | AController* Instigator 168 | const FDamageEvent& DamageEvent 169 | 170 | 7.7. __DO__ test whether a pointer is valid before dereferencing it. `nullptr` should be used instead of the C-style `NULL` macro in all cases. If the pointer points to any `UOBJECT`, use `IsValid` to ensures the pointer is not null and the referenced object is not marked for destruction. 171 | 172 | 173 | ## 8. Enums & Constants 174 | 175 | 8.1. __CONSIDER__ using `enum class` over `static constexpr` over `static const` variables over `#define` when defining constants. 176 | 177 | 8.2. __DO__ use ALL_CAPS with underscores between words for constant names. 178 | 179 | 180 | ## 9. Indentation & Whitespaces 181 | 182 | 9.1. __DO__ use four spaces for indentation. 183 | 184 | 9.2. __DO__ use a single space after a keyword and before a parenthesis. 185 | 186 | // Right: 187 | if (bVisible) 188 | { 189 | } 190 | 191 | // Wrong: 192 | if(bVisible) 193 | { 194 | } 195 | 196 | 9.3. __DO__ surround binary operators with spaces. 197 | 198 | 9.4. __DO NOT__ put multiple statements on one line. 199 | 200 | 201 | ## 10. Line Breaks 202 | 203 | 10.1. __CONSIDER__ keeping lines shorter than 100 characters; wrap if necessary. 204 | 205 | 10.2. __DO__ use a new line for the body of a control flow statement: 206 | 207 | // Right: 208 | if (bVisible) 209 | { 210 | Hide(); 211 | } 212 | 213 | // Wrong: 214 | if (bVisible) Hide(); 215 | 216 | 10.3. __DO__ start operators at the beginning of the new lines. 217 | 218 | // Right: 219 | if (longExpression 220 | + otherLongExpression 221 | + otherOtherLongExpression) 222 | { 223 | } 224 | 225 | // Wrong: Operator at the end of the line is easy to miss if the editor is too narrow. 226 | if (longExpression + 227 | otherLongExpression + 228 | otherOtherLongExpression) 229 | { 230 | } 231 | 232 | 233 | ## 11. Braces 234 | 235 | 11.1. __DO__ put opening braces on their own lines: 236 | 237 | // Right: 238 | if (bVisible) 239 | { 240 | } 241 | else 242 | { 243 | } 244 | 245 | // Wrong: 246 | if (bVisible) { 247 | } else { 248 | } 249 | 250 | 11.2. __DO__ have the left brace on the start of a line for class declarations and function definitions: 251 | 252 | void AHOATCharacter::Tick(float DeltaSeconds) 253 | { 254 | } 255 | 256 | class Moo 257 | { 258 | }; 259 | 260 | 11.3. __DO__ use curly braces, even if the body of a conditional statement contains just one line: 261 | 262 | // Right: 263 | if (bVisible) 264 | { 265 | Hide(); 266 | } 267 | 268 | // Wrong: Can lead to subtle bugs in the future, if the body is extended to span multiple statements. 269 | if (bVisible) 270 | Hide(); 271 | 272 | 273 | ## 12. Parentheses 274 | 275 | 12.1. __DO__ use parentheses to group expressions: 276 | 277 | // Right: 278 | if ((a && b) || c) 279 | 280 | // Wrong: Operator precedence is not immediately clear. 281 | if (a && b || c) 282 | 283 | 12.3. __DO NOT__ use spaces after parentheses: 284 | 285 | // Right: 286 | if ((a && b) || c) 287 | 288 | // Wrong: 289 | if ( ( a && b ) || c ) 290 | 291 | 292 | ## 13. Control Flow 293 | 294 | 13.1. __DO__ add a `break` (or `return`) statement at the end of every `case`, or a comment to indicate that there's intentionally no `break`, unless another `case` follows immediately within switch statements 295 | 296 | switch (MyEnumValue) 297 | { 298 | case Value1: 299 | DoSomething(); 300 | break; 301 | 302 | case Value2: 303 | case Value3: 304 | DoSomethingElse(); 305 | // Fall through. 306 | 307 | default: 308 | DefaultHandling(); 309 | break; 310 | } 311 | 312 | 13.2. __DO NOT__ put `else` after jump statements: 313 | 314 | // Right: 315 | if (ThisOrThat) 316 | { 317 | return; 318 | } 319 | 320 | SomethingElse(); 321 | 322 | 323 | // Wrong: Causes unnecessary indentation of the whole else block. 324 | if (ThisOrThat) 325 | { 326 | return; 327 | } 328 | else 329 | { 330 | SomethingElse(); 331 | } 332 | 333 | 334 | 13.3. __DO NOT__ mix const and non-const iterators. 335 | 336 | // Right: 337 | for (Container::const_iterator it = c.cbegin(); it != c.cend(); ++it) 338 | 339 | // Wrong: Crashes on some compilers. 340 | for (Container::const_iterator it = c.begin(); it != c.end(); ++it) 341 | 342 | 343 | ## 14. Language Features 344 | 345 | 14.1. __CONSIDER__ using the `auto` keyword when it avoids repetition of a type in the same statement, or when assigning iterator types. If in doubt, for example if using `auto` could make the code less readable, do not use `auto`. 346 | 347 | auto* HealthComponent = FindComponentByClass(); 348 | 349 | 14.2. __DO__ use `auto*` for auto pointers, to be consistent with references, and to add additional guidance for the reader. 350 | 351 | 14.3. __DO__ use proprietary types, such as `TArray` or `TMap` where possible. This avoids unnecessary and repeated type conversion while interacting with the Unreal Engine APIs. 352 | 353 | 14.4. __DO__ use the `TEXT()` macro around string literals. Without it, code which constructs `FString`s from literals will cause an undesirable string conversion process. 354 | 355 | ## 15. Events & Delegates 356 | 357 | 15.1. __CONSIDER__ exposing meaningful events to subclasses and/or other interested listeners by defining virtual functions and/or multicast delegates. 358 | 359 | 15.2. __DO__ define two functions when exposing an event to a subclass. The first function should be virtual and its name should begin with `Notify`. The second function should be a `BlueprintImplementableEvent UFUNCTION` and its name should begin with `Receive`. The default implementation of the virtual function should be to call the `BlueprintImplementableEvent` function (see `AActor::NotifyActorBeginOverlap` and `AActor::ReceiveActorBeginOverlap` for example). 360 | 361 | 15.3. __DO__ call the virtual function before broadcasting the event, if both are defined (see `UPrimitiveComponent::BeginComponentOverlap` for example). 362 | 363 | Example: 364 | 365 | DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(FHoatActorGraphConnectivityChangedSignature, AActor*, Source, AActor*, Target, float, Distance); 366 | 367 | /** Event when the connectivity of an observed source vertex has changed. */ 368 | virtual void NotifyOnConnectivityChanged(AActor* Source, AActor* Target, float Distance); 369 | 370 | /** Event when the connectivity of an observed source vertex has changed. */ 371 | UFUNCTION(BlueprintImplementableEvent, Category = Graph, meta = (DisplayName = "OnConnectivityChanged")) 372 | void ReceiveOnConnectivityChanged(AActor* Source, AActor* Target, float Distance); 373 | 374 | /** Event when the connectivity of an observed source vertex has changed. */ 375 | UPROPERTY(BlueprintAssignable) 376 | FHoatActorGraphConnectivityChangedSignature OnConnectivityChanged; 377 | 378 | 379 | void AHoatActorGraph::NotifyOnConnectivityChanged(AActor* Source, AActor* Target, float Distance) 380 | { 381 | ReceiveOnConnectivityChanged(Source, Target, Distance); 382 | OnConnectivityChanged.Broadcast(Source, Target, Distance); 383 | 384 | HOAT_LOG(hoat, Log, TEXT("%s changed the connectivity of vertex %s: Distance to target %s changed to %f."), 385 | *GetName(), *Source->GetName(), *Target->GetName(), Distance); 386 | } 387 | 388 | ## 16. Comments 389 | 390 | 16.1. __DO__ add a space after `//`. 391 | 392 | 16.2. __DO__ place the comment on a separate line, not at the end of a line of code. 393 | 394 | 16.3. __DO__ write API documentation with [Javadoc comments](https://docs.unrealengine.com/latest/INT/Programming/Development/CodingStandard/index.html#exampleformatting). 395 | 396 | 397 | ## 17. Additional Naming Conventions 398 | 399 | 17.1. __DO NOT__ use any swearing in symbol names, comments or log output. 400 | --------------------------------------------------------------------------------