VIRTUOS_Docs/_site/sites/styleguide.html

2892 lines
No EOL
136 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"><head>
<meta charset="utf-8">
<meta name="generator" content="quarto-1.6.43">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
<title>Styleguide DOCS</title>
<style>
code{white-space: pre-wrap;}
span.smallcaps{font-variant: small-caps;}
div.columns{display: flex; gap: min(4vw, 1.5em);}
div.column{flex: auto; overflow-x: auto;}
div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
ul.task-list{list-style: none;}
ul.task-list li input[type="checkbox"] {
width: 0.8em;
margin: 0 0.8em 0.2em -1em; /* quarto-specific, see https://github.com/quarto-dev/quarto-cli/issues/4556 */
vertical-align: middle;
}
</style>
<script src="../site_libs/quarto-nav/quarto-nav.js"></script>
<script src="../site_libs/quarto-nav/headroom.min.js"></script>
<script src="../site_libs/clipboard/clipboard.min.js"></script>
<script src="../site_libs/quarto-search/autocomplete.umd.js"></script>
<script src="../site_libs/quarto-search/fuse.min.js"></script>
<script src="../site_libs/quarto-search/quarto-search.js"></script>
<meta name="quarto:offset" content="../">
<script src="../site_libs/quarto-html/quarto.js"></script>
<script src="../site_libs/quarto-html/popper.min.js"></script>
<script src="../site_libs/quarto-html/tippy.umd.min.js"></script>
<script src="../site_libs/quarto-html/anchor.min.js"></script>
<link href="../site_libs/quarto-html/tippy.css" rel="stylesheet">
<link href="../site_libs/quarto-html/quarto-syntax-highlighting-d4d76bf8491c20bad77d141916dc28e1.css" rel="stylesheet" id="quarto-text-highlighting-styles">
<script src="../site_libs/bootstrap/bootstrap.min.js"></script>
<link href="../site_libs/bootstrap/bootstrap-icons.css" rel="stylesheet">
<link href="../site_libs/bootstrap/bootstrap-96f0ff77f429b54fb9fb81a812e140da.min.css" rel="stylesheet" append-hash="true" id="quarto-bootstrap" data-mode="light">
<script id="quarto-search-options" type="application/json">{
"location": "navbar",
"copy-button": false,
"collapse-after": 3,
"panel-placement": "end",
"type": "overlay",
"limit": 50,
"keyboard-shortcut": [
"f",
"/",
"s"
],
"show-item-context": false,
"language": {
"search-no-results-text": "No results",
"search-matching-documents-text": "matching documents",
"search-copy-link-title": "Copy link to search",
"search-hide-matches-text": "Hide additional matches",
"search-more-match-text": "more match in this document",
"search-more-matches-text": "more matches in this document",
"search-clear-button-title": "Clear",
"search-text-placeholder": "",
"search-detached-cancel-button-title": "Cancel",
"search-submit-button-title": "Submit",
"search-label": "Search"
}
}</script>
</head>
<body class="nav-sidebar docked nav-fixed">
<div id="quarto-search-results"></div>
<header id="quarto-header" class="headroom fixed-top">
<nav class="navbar navbar-expand-lg " data-bs-theme="dark">
<div class="navbar-container container-fluid">
<div class="navbar-brand-container mx-auto">
<a class="navbar-brand" href="../index.html">
<span class="navbar-title">DOCS</span>
</a>
</div>
<div id="quarto-search" class="" title="Search"></div>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarCollapse" aria-controls="navbarCollapse" role="menu" aria-expanded="false" aria-label="Toggle navigation" onclick="if (window.quartoToggleHeadroom) { window.quartoToggleHeadroom(); }">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarCollapse">
<ul class="navbar-nav navbar-nav-scroll me-auto">
<li class="nav-item">
<a class="nav-link" href="https://virtuos.world">
<span class="menu-text">Homepage</span></a>
</li>
</ul>
</div> <!-- /navcollapse -->
<div class="quarto-navbar-tools">
<a href="" class="quarto-reader-toggle quarto-navigation-tool px-1" onclick="window.quartoToggleReader(); return false;" title="Toggle reader mode">
<div class="quarto-reader-toggle-btn">
<i class="bi"></i>
</div>
</a>
</div>
</div> <!-- /container-fluid -->
</nav>
<nav class="quarto-secondary-nav">
<div class="container-fluid d-flex">
<button type="button" class="quarto-btn-toggle btn" data-bs-toggle="collapse" role="button" data-bs-target=".quarto-sidebar-collapse-item" aria-controls="quarto-sidebar" aria-expanded="false" aria-label="Toggle sidebar navigation" onclick="if (window.quartoToggleHeadroom) { window.quartoToggleHeadroom(); }">
<i class="bi bi-layout-text-sidebar-reverse"></i>
</button>
<nav class="quarto-page-breadcrumbs" aria-label="breadcrumb"><ol class="breadcrumb"><li class="breadcrumb-item"><a href="../sites/styleguide.html">Styleguide</a></li></ol></nav>
<a class="flex-grow-1" role="navigation" data-bs-toggle="collapse" data-bs-target=".quarto-sidebar-collapse-item" aria-controls="quarto-sidebar" aria-expanded="false" aria-label="Toggle sidebar navigation" onclick="if (window.quartoToggleHeadroom) { window.quartoToggleHeadroom(); }">
</a>
<button type="button" class="btn quarto-search-button" aria-label="Search" onclick="window.quartoOpenSearch();">
<i class="bi bi-search"></i>
</button>
</div>
</nav>
</header>
<!-- content -->
<div id="quarto-content" class="quarto-container page-columns page-rows-contents page-layout-article page-navbar">
<!-- sidebar -->
<nav id="quarto-sidebar" class="sidebar collapse collapse-horizontal quarto-sidebar-collapse-item sidebar-navigation docked overflow-auto">
<div class="mt-2 flex-shrink-0 align-items-center">
<div class="sidebar-search">
<div id="quarto-search" class="" title="Search"></div>
</div>
</div>
<div class="sidebar-menu-container">
<ul class="list-unstyled mt-1">
<li class="sidebar-item sidebar-item-section">
<span class="sidebar-item-text sidebar-link text-start">
<span class="menu-text">Overview</span></span>
</li>
<li class="sidebar-item sidebar-item-section">
<div class="sidebar-item-container">
<a href="../sites/styleguide.html" class="sidebar-item-text sidebar-link active">
<span class="menu-text">Styleguide</span></a>
<a class="sidebar-item-toggle text-start" data-bs-toggle="collapse" data-bs-target="#quarto-sidebar-section-2" role="navigation" aria-expanded="true" aria-label="Toggle section">
<i class="bi bi-chevron-right ms-2"></i>
</a>
</div>
<ul id="quarto-sidebar-section-2" class="collapse list-unstyled sidebar-section depth1 show">
<li class="sidebar-item">
<span class="menu-text">layout.qmd</span>
</li>
<li class="sidebar-item">
<span class="menu-text">layout-knitr.qmd</span>
</li>
<li class="sidebar-item">
<span class="menu-text">layout-jupyter.qmd</span>
</li>
</ul>
</li>
<li class="sidebar-item sidebar-item-section">
<div class="sidebar-item-container">
<a href="../sites/webservices.html" class="sidebar-item-text sidebar-link">
<span class="menu-text">Webservices</span></a>
<a class="sidebar-item-toggle text-start" data-bs-toggle="collapse" data-bs-target="#quarto-sidebar-section-3" role="navigation" aria-expanded="true" aria-label="Toggle section">
<i class="bi bi-chevron-right ms-2"></i>
</a>
</div>
<ul id="quarto-sidebar-section-3" class="collapse list-unstyled sidebar-section depth1 show">
<li class="sidebar-item">
<span class="menu-text">layout.qmd</span>
</li>
<li class="sidebar-item">
<span class="menu-text">layout-knitr.qmd</span>
</li>
<li class="sidebar-item">
<span class="menu-text">layout-jupyter.qmd</span>
</li>
</ul>
</li>
<li class="sidebar-item sidebar-item-section">
<span class="sidebar-item-text sidebar-link text-start">
<span class="menu-text">Getting Started</span></span>
</li>
</ul>
</div>
</nav>
<div id="quarto-sidebar-glass" class="quarto-sidebar-collapse-item" data-bs-toggle="collapse" data-bs-target=".quarto-sidebar-collapse-item"></div>
<!-- margin-sidebar -->
<div id="quarto-margin-sidebar" class="sidebar margin-sidebar">
<nav id="TOC" role="doc-toc" class="toc-active">
<h2 id="toc-title">On this page</h2>
<ul>
<li><a href="#important-terminology" id="toc-important-terminology" class="nav-link active" data-scroll-target="#important-terminology">Important Terminology</a></li>
<li><a href="#principles" id="toc-principles" class="nav-link" data-scroll-target="#principles">0. Principles</a>
<ul class="collapse">
<li><a href="#if-your-ue4-project-already-has-a-style-guide-you-should-follow-it." id="toc-if-your-ue4-project-already-has-a-style-guide-you-should-follow-it." class="nav-link" data-scroll-target="#if-your-ue4-project-already-has-a-style-guide-you-should-follow-it.">0.1 If your UE4 project already has a style guide, you should follow it.</a></li>
<li><a href="#all-structure-assets-and-code-in-any-unreal-engine-4-project-should-look-like-a-single-person-created-it-no-matter-how-many-people-contributed." id="toc-all-structure-assets-and-code-in-any-unreal-engine-4-project-should-look-like-a-single-person-created-it-no-matter-how-many-people-contributed." class="nav-link" data-scroll-target="#all-structure-assets-and-code-in-any-unreal-engine-4-project-should-look-like-a-single-person-created-it-no-matter-how-many-people-contributed.">0.2 All structure, assets, and code in any Unreal Engine 4 project should look like a single person created it, no matter how many people contributed.</a></li>
<li><a href="#friends-do-not-let-friends-have-bad-style." id="toc-friends-do-not-let-friends-have-bad-style." class="nav-link" data-scroll-target="#friends-do-not-let-friends-have-bad-style.">0.3 Friends do not let friends have bad style.</a></li>
<li><a href="#a-team-without-a-style-guide-is-no-team-of-mine." id="toc-a-team-without-a-style-guide-is-no-team-of-mine." class="nav-link" data-scroll-target="#a-team-without-a-style-guide-is-no-team-of-mine.">0.4 A team without a style guide is no team of mine.</a></li>
<li><a href="#dont-break-the-law" id="toc-dont-break-the-law" class="nav-link" data-scroll-target="#dont-break-the-law">0.5 Dont Break The Law</a></li>
</ul></li>
<li><a href="#globally-enforced-opinions" id="toc-globally-enforced-opinions" class="nav-link" data-scroll-target="#globally-enforced-opinions">00. Globally Enforced Opinions</a>
<ul class="collapse">
<li><a href="#forbidden-characters" id="toc-forbidden-characters" class="nav-link" data-scroll-target="#forbidden-characters">00.1 Forbidden Characters</a></li>
</ul></li>
<li><a href="#table-of-contents" id="toc-table-of-contents" class="nav-link" data-scroll-target="#table-of-contents">Table of Contents</a></li>
<li><a href="#asset-naming-conventions" id="toc-asset-naming-conventions" class="nav-link" data-scroll-target="#asset-naming-conventions">1. Asset Naming Conventions</a>
<ul class="collapse">
<li><a href="#base-asset-name---prefix_baseassetname_variant_suffix" id="toc-base-asset-name---prefix_baseassetname_variant_suffix" class="nav-link" data-scroll-target="#base-asset-name---prefix_baseassetname_variant_suffix">1.1 Base Asset Name - <code>Prefix_BaseAssetName_Variant_Suffix</code></a></li>
<li><a href="#asset-name-modifiers" id="toc-asset-name-modifiers" class="nav-link" data-scroll-target="#asset-name-modifiers">1.2 Asset Name Modifiers</a></li>
<li><a href="#artificial-intelligence" id="toc-artificial-intelligence" class="nav-link" data-scroll-target="#artificial-intelligence">1.2.3 Artificial Intelligence</a></li>
<li><a href="#blueprints" id="toc-blueprints" class="nav-link" data-scroll-target="#blueprints">1.2.4 Blueprints</a></li>
<li><a href="#materials" id="toc-materials" class="nav-link" data-scroll-target="#materials">1.2.5 Materials</a></li>
<li><a href="#textures" id="toc-textures" class="nav-link" data-scroll-target="#textures">1.2.6 Textures</a></li>
<li><a href="#miscellaneous" id="toc-miscellaneous" class="nav-link" data-scroll-target="#miscellaneous">1.2.7 Miscellaneous</a></li>
<li><a href="#paper-2d" id="toc-paper-2d" class="nav-link" data-scroll-target="#paper-2d">1.2.8 Paper 2D</a></li>
<li><a href="#physics" id="toc-physics" class="nav-link" data-scroll-target="#physics">1.2.9 Physics</a></li>
<li><a href="#sounds" id="toc-sounds" class="nav-link" data-scroll-target="#sounds">1.2.10 Sounds</a></li>
<li><a href="#user-interface" id="toc-user-interface" class="nav-link" data-scroll-target="#user-interface">1.2.11 User Interface</a></li>
<li><a href="#effects" id="toc-effects" class="nav-link" data-scroll-target="#effects">1.2.12 Effects</a></li>
</ul></li>
<li><a href="#content-directory-structure" id="toc-content-directory-structure" class="nav-link" data-scroll-target="#content-directory-structure">2. Content Directory Structure</a>
<ul class="collapse">
<li><a href="#sections-1" id="toc-sections-1" class="nav-link" data-scroll-target="#sections-1">Sections</a></li>
<li><a href="#use-developers-folder-for-local-testing" id="toc-use-developers-folder-for-local-testing" class="nav-link" data-scroll-target="#use-developers-folder-for-local-testing">2.3 Use Developers Folder For Local Testing</a></li>
<li><a href="#all-map-files-belong-in-a-folder-called-maps" id="toc-all-map-files-belong-in-a-folder-called-maps" class="nav-link" data-scroll-target="#all-map-files-belong-in-a-folder-called-maps">2.4 All Map<sup>*</sup> Files Belong In A Folder Called Maps</a></li>
<li><a href="#use-a-core-folder-for-critical-blueprints-and-other-assets" id="toc-use-a-core-folder-for-critical-blueprints-and-other-assets" class="nav-link" data-scroll-target="#use-a-core-folder-for-critical-blueprints-and-other-assets">2.5 Use A <code>Core</code> Folder For Critical Blueprints And Other Assets</a></li>
<li><a href="#do-not-create-folders-called-assets-or-assettypes" id="toc-do-not-create-folders-called-assets-or-assettypes" class="nav-link" data-scroll-target="#do-not-create-folders-called-assets-or-assettypes">2.6 Do Not Create Folders Called <code>Assets</code> or <code>AssetTypes</code></a></li>
<li><a href="#very-large-asset-sets-get-their-own-folder-layout" id="toc-very-large-asset-sets-get-their-own-folder-layout" class="nav-link" data-scroll-target="#very-large-asset-sets-get-their-own-folder-layout">2.7 Very Large Asset Sets Get Their Own Folder Layout</a></li>
<li><a href="#materiallibrary" id="toc-materiallibrary" class="nav-link" data-scroll-target="#materiallibrary">2.8 <code>MaterialLibrary</code></a></li>
<li><a href="#no-empty-folders" id="toc-no-empty-folders" class="nav-link" data-scroll-target="#no-empty-folders">2.9 No Empty Folders</a></li>
</ul></li>
<li><a href="#blueprints-1" id="toc-blueprints-1" class="nav-link" data-scroll-target="#blueprints-1">3. Blueprints</a>
<ul class="collapse">
<li><a href="#sections-2" id="toc-sections-2" class="nav-link" data-scroll-target="#sections-2">Sections</a></li>
<li><a href="#compiling" id="toc-compiling" class="nav-link" data-scroll-target="#compiling">3.1 Compiling</a></li>
<li><a href="#variables" id="toc-variables" class="nav-link" data-scroll-target="#variables">3.2 Variables</a></li>
<li><a href="#functions-events-and-event-dispatchers" id="toc-functions-events-and-event-dispatchers" class="nav-link" data-scroll-target="#functions-events-and-event-dispatchers">3.3 Functions, Events, and Event Dispatchers</a></li>
<li><a href="#blueprint-graphs" id="toc-blueprint-graphs" class="nav-link" data-scroll-target="#blueprint-graphs">3.4 Blueprint Graphs</a></li>
</ul></li>
<li><a href="#static-meshes" id="toc-static-meshes" class="nav-link" data-scroll-target="#static-meshes">4. Static Meshes</a>
<ul class="collapse">
<li><a href="#sections-4" id="toc-sections-4" class="nav-link" data-scroll-target="#sections-4">Sections</a></li>
<li><a href="#static-mesh-uvs" id="toc-static-mesh-uvs" class="nav-link" data-scroll-target="#static-mesh-uvs">4.1 Static Mesh UVs</a></li>
<li><a href="#lods-should-be-set-up-correctly" id="toc-lods-should-be-set-up-correctly" class="nav-link" data-scroll-target="#lods-should-be-set-up-correctly">4.2 LODs Should Be Set Up Correctly</a></li>
<li><a href="#modular-socketless-assets-should-snap-to-the-grid-cleanly" id="toc-modular-socketless-assets-should-snap-to-the-grid-cleanly" class="nav-link" data-scroll-target="#modular-socketless-assets-should-snap-to-the-grid-cleanly">4.3 Modular Socketless Assets Should Snap To The Grid Cleanly</a></li>
<li><a href="#all-meshes-must-have-collision" id="toc-all-meshes-must-have-collision" class="nav-link" data-scroll-target="#all-meshes-must-have-collision">4.4 All Meshes Must Have Collision</a></li>
<li><a href="#all-meshes-should-be-scaled-correctly" id="toc-all-meshes-should-be-scaled-correctly" class="nav-link" data-scroll-target="#all-meshes-should-be-scaled-correctly">4.5 All Meshes Should Be Scaled Correctly</a></li>
</ul></li>
<li><a href="#niagara" id="toc-niagara" class="nav-link" data-scroll-target="#niagara">5. Niagara</a>
<ul class="collapse">
<li><a href="#sections-5" id="toc-sections-5" class="nav-link" data-scroll-target="#sections-5">Sections</a></li>
<li><a href="#no-spaces-ever" id="toc-no-spaces-ever" class="nav-link" data-scroll-target="#no-spaces-ever">5.1 No Spaces, Ever</a></li>
</ul></li>
<li><a href="#levels-maps" id="toc-levels-maps" class="nav-link" data-scroll-target="#levels-maps">6. Levels / Maps</a>
<ul class="collapse">
<li><a href="#sections-6" id="toc-sections-6" class="nav-link" data-scroll-target="#sections-6">Sections</a></li>
<li><a href="#no-errors-or-warnings" id="toc-no-errors-or-warnings" class="nav-link" data-scroll-target="#no-errors-or-warnings">6.1 No Errors Or Warnings</a></li>
<li><a href="#lighting-should-be-built" id="toc-lighting-should-be-built" class="nav-link" data-scroll-target="#lighting-should-be-built">6.2 Lighting Should Be Built</a></li>
<li><a href="#no-player-visible-z-fighting" id="toc-no-player-visible-z-fighting" class="nav-link" data-scroll-target="#no-player-visible-z-fighting">6.3 No Player Visible Z Fighting</a></li>
<li><a href="#marketplace-specific-rules" id="toc-marketplace-specific-rules" class="nav-link" data-scroll-target="#marketplace-specific-rules">6.4 Marketplace Specific Rules</a></li>
<li><a href="#overview-level" id="toc-overview-level" class="nav-link" data-scroll-target="#overview-level">6.4.1 Overview Level</a></li>
<li><a href="#demo-level" id="toc-demo-level" class="nav-link" data-scroll-target="#demo-level">6.4.2 Demo Level</a></li>
</ul></li>
<li><a href="#textures-1" id="toc-textures-1" class="nav-link" data-scroll-target="#textures-1">7. Textures</a>
<ul class="collapse">
<li><a href="#sections-7" id="toc-sections-7" class="nav-link" data-scroll-target="#sections-7">Sections</a></li>
<li><a href="#dimensions-are-powers-of-2" id="toc-dimensions-are-powers-of-2" class="nav-link" data-scroll-target="#dimensions-are-powers-of-2">7.1 Dimensions Are Powers of 2</a></li>
<li><a href="#texture-density-should-be-uniform" id="toc-texture-density-should-be-uniform" class="nav-link" data-scroll-target="#texture-density-should-be-uniform">7.2 Texture Density Should Be Uniform</a></li>
<li><a href="#textures-should-be-no-bigger-than-8192" id="toc-textures-should-be-no-bigger-than-8192" class="nav-link" data-scroll-target="#textures-should-be-no-bigger-than-8192">7.3 Textures Should Be No Bigger than 8192</a></li>
<li><a href="#textures-should-be-grouped-correctly" id="toc-textures-should-be-grouped-correctly" class="nav-link" data-scroll-target="#textures-should-be-grouped-correctly">7.4 Textures Should Be Grouped Correctly</a></li>
</ul></li>
</ul>
</nav>
</div>
<!-- main -->
<main class="content" id="quarto-document-content">
<header id="title-block-header" class="quarto-title-block default">
<div class="quarto-title">
<h1 class="title">Styleguide</h1>
</div>
<div class="quarto-title-meta">
</div>
</header>
<p>This Styleguiade is adapted by Gamemakin UE5 Styleguide.</p>
<section id="important-terminology" class="level2">
<h2 class="anchored" data-anchor-id="important-terminology">Important Terminology</h2>
<p><a name="terms-level-map"></a></p>
<section id="levelsmaps" class="level5">
<h5 class="anchored" data-anchor-id="levelsmaps">Levels/Maps</h5>
<p>The word map generally refers to what the average person calls a level and may be used interchangeably. See this terms history <a href="https://en.wikipedia.org/wiki/Level_(video_gaming)">here</a>.</p>
</section>
<section id="identifiers" class="level5">
<h5 class="anchored" data-anchor-id="identifiers">Identifiers</h5>
<p>An <code>Identifier</code> is anything that resembles or serves as a “name”. For example, the name of an asset, or the name of a material later, or a blueprint property, a variable, or a folder name, or for a data table row name, etc…</p>
<p><a name="terms-cases"></a></p>
</section>
<section id="cases" class="level5">
<h5 class="anchored" data-anchor-id="cases">Cases</h5>
<p>There are a few different ways you can <code>CaseWordsWhenNaming</code>. Here are some common casing types:</p>
<blockquote class="blockquote">
<h6 id="pascalcase" class="anchored">PascalCase</h6>
<p>Capitalize every word and remove all spaces, e.g.&nbsp;<code>DesertEagle</code>, <code>StyleGuide</code>, <code>ASeriesOfWords</code>.</p>
<h6 id="camelcase" class="anchored">camelCase</h6>
<p>The first letter is always lowercase but every following word starts with uppercase, e.g.&nbsp;<code>desertEagle</code>, <code>styleGuide</code>, <code>aSeriesOfWords</code>.</p>
<h6 id="snake_case" class="anchored">Snake_case</h6>
<p>Words can arbitrarily start upper or lowercase but words are separated by an underscore, e.g.&nbsp;<code>desert_Eagle</code>, <code>Style_Guide</code>, <code>a_Series_of_Words</code>.</p>
</blockquote>
<p><a name="terms-var-prop"></a></p>
</section>
<section id="variables-properties" class="level5">
<h5 class="anchored" data-anchor-id="variables-properties">Variables / Properties</h5>
<p>The words variable and property in most contexts are interchangable. If they are both used together in the same context however:</p>
<p><a name="terms-property"></a></p>
<section id="property" class="level6">
<h6 class="anchored" data-anchor-id="property">Property</h6>
<p>Usually refers to a variable defined in a class. For example, if <code>BP_Barrel</code> had a variable <code>bExploded</code>, <code>bExploded</code> may be referred to as a property of <code>BP_Barrel</code>.</p>
<p>When in the context of a class, it is often used to imply accessing previously defined data.</p>
<p><a name="terms-variable"></a></p>
</section>
<section id="variable" class="level6">
<h6 class="anchored" data-anchor-id="variable">Variable</h6>
<p>Usually refers to a variable defined as a function argument or a local variable inside a function.</p>
<p>When in the context of a class, it is often used to convey discussion about its definition and what it will hold.</p>
<p><a name="0"></a></p>
</section>
</section>
</section>
<section id="principles" class="level2">
<h2 class="anchored" data-anchor-id="principles">0. Principles</h2>
<p>These principles have been adapted from <a href="https://github.com/rwaldron/idiomatic.js/">idomatic.js style guide</a>.</p>
<p><a name="0.1"></a></p>
<section id="if-your-ue4-project-already-has-a-style-guide-you-should-follow-it." class="level3">
<h3 class="anchored" data-anchor-id="if-your-ue4-project-already-has-a-style-guide-you-should-follow-it.">0.1 If your UE4 project already has a style guide, you should follow it.</h3>
<p>If you are working on a project or with a team that has a pre-existing style guide, it should be respected. Any inconsistency between an existing style guide and this guide should defer to the existing.</p>
<p>Style guides should be living documents. You should propose style guide changes to an existing style guide as well as this guide if you feel the change benefits all usages.</p>
<blockquote class="blockquote">
<h4 id="arguments-over-style-are-pointless.-there-should-be-a-style-guide-and-you-should-follow-it." class="anchored">“Arguments over style are pointless. There should be a style guide, and you should follow it.”</h4>
<p><a href="https://rmurphey.com"><em>Rebecca Murphey</em></a></p>
</blockquote>
<p><a name="0.2"></a></p>
</section>
<section id="all-structure-assets-and-code-in-any-unreal-engine-4-project-should-look-like-a-single-person-created-it-no-matter-how-many-people-contributed." class="level3">
<h3 class="anchored" data-anchor-id="all-structure-assets-and-code-in-any-unreal-engine-4-project-should-look-like-a-single-person-created-it-no-matter-how-many-people-contributed.">0.2 All structure, assets, and code in any Unreal Engine 4 project should look like a single person created it, no matter how many people contributed.</h3>
<p>Moving from one project to another should not cause a re-learning of style and structure. Conforming to a style guide removes unneeded guesswork and ambiguities.</p>
<p>It also allows for more productive creation and maintenance as one does not need to think about style. Simply follow the instructions. This style guide is written with best practices in mind, meaning that by following this style guide you will also minimize hard to track issues.</p>
<p><a name="0.3"></a></p>
</section>
<section id="friends-do-not-let-friends-have-bad-style." class="level3">
<h3 class="anchored" data-anchor-id="friends-do-not-let-friends-have-bad-style.">0.3 Friends do not let friends have bad style.</h3>
<p>If you see someone working either against a style guide or no style guide, try to correct them.</p>
<p>When working within a team or discussing within a community such as <a href="http://join.unrealslackers.org/">Unreal Slackers</a>, it is far easier to help and to ask for help when people are consistent. Nobody likes to help untangle someones Blueprint spaghetti or deal with assets that have names they cant understand.</p>
<p>If you are helping someone whose work conforms to a different but consistent and sane style guide, you should be able to adapt to it. If they do not conform to any style guide, please direct them here.</p>
<p><a name="0.4"></a></p>
</section>
<section id="a-team-without-a-style-guide-is-no-team-of-mine." class="level3">
<h3 class="anchored" data-anchor-id="a-team-without-a-style-guide-is-no-team-of-mine.">0.4 A team without a style guide is no team of mine.</h3>
<p>When joining an Unreal Engine 4 team, one of your first questions should be “Do you have a style guide?”. If the answer is no, you should be skeptical about their ability to work as a team.</p>
<p><a name="0.5"></a></p>
</section>
<section id="dont-break-the-law" class="level3">
<h3 class="anchored" data-anchor-id="dont-break-the-law">0.5 Dont Break The Law</h3>
<p>Gamemakin LLC is not a lawyer, but please dont introduce illegal actions and behavior to a project, including but not limited to:</p>
<ul>
<li>Dont distribute content you dont have the rights to distribute</li>
<li>Dont infringe on someone elses copyrighted or trademark material</li>
<li>Dont steal content</li>
<li>Follow licensing restrictions on content, e.g.&nbsp;attribute when attributions are needed</li>
</ul>
<p><a name="00"></a></p>
</section>
</section>
<section id="globally-enforced-opinions" class="level2">
<h2 class="anchored" data-anchor-id="globally-enforced-opinions">00. Globally Enforced Opinions</h2>
<p><span class="citation" data-cites="TODO">@TODO</span>: Make this section 1 and update this document accordingly. Or maybe we dont?</p>
<p><a name="00.1"></a></p>
<section id="forbidden-characters" class="level3">
<h3 class="anchored" data-anchor-id="forbidden-characters">00.1 Forbidden Characters</h3>
<section id="identifiers-1" class="level4">
<h4 class="anchored" data-anchor-id="identifiers-1">Identifiers</h4>
<p>In any <code>Identifier</code> of any kind, <strong>never</strong> use the following unless absolutely forced to:</p>
<ul>
<li>White space of any kind</li>
<li>Backward slashes <code>\</code></li>
<li>Symbols i.e.&nbsp;<code>#!@$%</code></li>
<li>Any Unicode character</li>
</ul>
<p>Any <code>Identifier</code> should strive to only have the following characters when possible (the <code>[A-Za-z0-9_]+</code>)</p>
<ul>
<li>ABCDEFGHIJKLMNOPQRSTUVWXYZ</li>
<li>abcdefghijklmnopqrstuvwxyz</li>
<li>1234567890</li>
<li>_ (sparingly)</li>
</ul>
<p>The reasoning for this is this will ensure the greatest compatibility of all data across all platforms across all tools, and help prevent downtime due to potentially bad character handling for identifiers in code you dont control.</p>
<p><a name="toc"></a></p>
</section>
</section>
</section>
<section id="table-of-contents" class="level2">
<h2 class="anchored" data-anchor-id="table-of-contents">Table of Contents</h2>
<blockquote class="blockquote">
<ol type="1">
<li><a href="#anc">Asset Naming Conventions</a></li>
<li><a href="#structure">Directory Structure</a></li>
<li><a href="#bp">Blueprints</a></li>
<li><a href="#s">Static Meshes</a></li>
<li><a href="#ps">Particle Systems</a></li>
<li><a href="#levels">Levels / Maps</a></li>
<li><a href="#textures">Textures</a></li>
</ol>
</blockquote>
<p><a name="anc"></a></p>
<p><a name="1"></a></p>
</section>
<section id="asset-naming-conventions" class="level2">
<h2 class="anchored" data-anchor-id="asset-naming-conventions">1. Asset Naming Conventions</h2>
<p>Naming conventions should be treated as law. A project that conforms to a naming convention is able to have its assets managed, searched, parsed, and maintained with incredible ease.</p>
<p>Most things are prefixed with prefixes being generally an acronym of the asset type followed by an underscore.</p>
<p><a name="base-asset-name"></a></p>
<p><a name="1.1"></a></p>
<section id="base-asset-name---prefix_baseassetname_variant_suffix" class="level3">
<h3 class="anchored" data-anchor-id="base-asset-name---prefix_baseassetname_variant_suffix">1.1 Base Asset Name - <code>Prefix_BaseAssetName_Variant_Suffix</code></h3>
<p>All assets should have a <em>Base Asset Name</em>. A Base Asset Name represents a logical grouping of related assets. Any asset that is part of this logical group should follow the standard of <code>Prefix_BaseAssetName_Variant_Suffix</code>.</p>
<p>Keeping the pattern <code>Prefix_BaseAssetName_Variant_Suffix</code> and in mind and using common sense is generally enough to warrant good asset names. Here are some detailed rules regarding each element.</p>
<p><code>Prefix</code> and <code>Suffix</code> are to be determined by the asset type through the following <a href="#asset-name-modifiers">Asset Name Modifier</a> tables.</p>
<p><code>BaseAssetName</code> should be determined by a short and easily recognizable name related to the context of this group of assets. For example, if you had a character named Bob, all of Bobs assets would have the <code>BaseAssetName</code> of <code>Bob</code>.</p>
<p>For unique and specific variations of assets, <code>Variant</code> is either a short and easily recognizable name that represents logical grouping of assets that are a subset of an assets base name. For example, if Bob had multiple skins these skins should still use <code>Bob</code> as the <code>BaseAssetName</code> but include a recognizable <code>Variant</code>. An Evil skin would be referred to as <code>Bob_Evil</code> and a Retro skin would be referred to as <code>Bob_Retro</code>.</p>
<p>For unique but generic variations of assets, <code>Variant</code> is a two digit number starting at <code>01</code>. For example, if you have an environment artist generating nondescript rocks, they would be named <code>Rock_01</code>, <code>Rock_02</code>, <code>Rock_03</code>, etc. Except for rare exceptions, you should never require a three digit variant number. If you have more than 100 assets, you should consider organizing them with different base names or using multiple variant names.</p>
<p>Depending on how your asset variants are made, you can chain together variant names. For example, if you are creating flooring assets for an Arch Viz project you should use the base name <code>Flooring</code> with chained variants such as <code>Flooring_Marble_01</code>, <code>Flooring_Maple_01</code>, <code>Flooring_Tile_Squares_01</code>.</p>
<p><a name="1.1-examples"></a></p>
<section id="examples" class="level4">
<h4 class="anchored" data-anchor-id="examples">1.1 Examples</h4>
<section id="e1-bob" class="level5">
<h5 class="anchored" data-anchor-id="e1-bob">1.1e1 Bob</h5>
<table class="caption-top table">
<colgroup>
<col style="width: 28%">
<col style="width: 71%">
</colgroup>
<thead>
<tr class="header">
<th>Asset Type</th>
<th>Asset Name</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>Skeletal Mesh</td>
<td>SK_Bob</td>
</tr>
<tr class="even">
<td>Material</td>
<td>M_Bob</td>
</tr>
<tr class="odd">
<td>Texture (Diffuse/Albedo)</td>
<td>T_Bob_D</td>
</tr>
<tr class="even">
<td>Texture (Normal)</td>
<td>T_Bob_N</td>
</tr>
<tr class="odd">
<td>Texture (Evil Diffuse)</td>
<td>T_Bob_Evil_D</td>
</tr>
</tbody>
</table>
</section>
<section id="e2-rocks" class="level5">
<h5 class="anchored" data-anchor-id="e2-rocks">1.1e2 Rocks</h5>
<table class="caption-top table">
<colgroup>
<col style="width: 28%">
<col style="width: 71%">
</colgroup>
<thead>
<tr class="header">
<th>Asset Type</th>
<th>Asset Name</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>Static Mesh (01)</td>
<td>S_Rock_01</td>
</tr>
<tr class="even">
<td>Static Mesh (02)</td>
<td>S_Rock_02</td>
</tr>
<tr class="odd">
<td>Static Mesh (03)</td>
<td>S_Rock_03</td>
</tr>
<tr class="even">
<td>Material</td>
<td>M_Rock</td>
</tr>
<tr class="odd">
<td>Material Instance (Snow)</td>
<td>MI_Rock_Snow</td>
</tr>
</tbody>
</table>
<p><a name="asset-name-modifiers"></a></p>
<p><a name="1.2"></a></p>
</section>
</section>
</section>
<section id="asset-name-modifiers" class="level3">
<h3 class="anchored" data-anchor-id="asset-name-modifiers">1.2 Asset Name Modifiers</h3>
<p>When naming an asset, use these tables to determine the prefix and suffix to use with an assets <a href="#base-asset-name">Base Asset Name</a>.</p>
<section id="sections" class="level4">
<h4 class="anchored" data-anchor-id="sections">Sections</h4>
<blockquote class="blockquote">
<p>1.2.1 <a href="#anc-common">Most Common</a></p>
</blockquote>
<blockquote class="blockquote">
<p>1.2.2 <a href="#anc-animations">Animations</a></p>
</blockquote>
<blockquote class="blockquote">
<p>1.2.3 <a href="#anc-ai">Artificial Intelligence</a></p>
</blockquote>
<blockquote class="blockquote">
<p>1.2.4 <a href="#anc-bp">Blueprints</a></p>
</blockquote>
<blockquote class="blockquote">
<p>1.2.5 <a href="#anc-materials">Materials</a></p>
</blockquote>
<blockquote class="blockquote">
<p>1.2.6 <a href="#anc-textures">Textures</a></p>
</blockquote>
<blockquote class="blockquote">
<p>1.2.7 <a href="#anc-misc">Miscellaneous</a></p>
</blockquote>
<blockquote class="blockquote">
<p>1.2.8 <a href="#anc-paper2d">Paper 2D</a></p>
</blockquote>
<blockquote class="blockquote">
<p>1.2.9 <a href="#anc-physics">Physics</a></p>
</blockquote>
<blockquote class="blockquote">
<p>1.2.10 <a href="#anc-sounds">Sound</a></p>
</blockquote>
<blockquote class="blockquote">
<p>1.2.11 <a href="#anc-ui">User Interface</a></p>
</blockquote>
<blockquote class="blockquote">
<p>1.2.12 <a href="#anc-effects">Effects</a></p>
</blockquote>
<p><a name="anc-common"></a></p>
<p><a name="1.2.1"></a></p>
</section>
<section id="most-common" class="level4">
<h4 class="anchored" data-anchor-id="most-common">1.2.1 Most Common</h4>
<table class="caption-top table">
<thead>
<tr class="header">
<th>Asset Type</th>
<th>Prefix</th>
<th>Suffix</th>
<th>Notes</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>Level / Map</td>
<td></td>
<td></td>
<td><a href="#2.4">Should be in a folder called Maps.</a></td>
</tr>
<tr class="even">
<td>Level (Persistent)</td>
<td></td>
<td>_P</td>
<td></td>
</tr>
<tr class="odd">
<td>Level (Audio)</td>
<td></td>
<td>_Audio</td>
<td></td>
</tr>
<tr class="even">
<td>Level (Lighting)</td>
<td></td>
<td>_Lighting</td>
<td></td>
</tr>
<tr class="odd">
<td>Level (Geometry)</td>
<td></td>
<td>_Geo</td>
<td></td>
</tr>
<tr class="even">
<td>Level (Gameplay)</td>
<td></td>
<td>_Gameplay</td>
<td></td>
</tr>
<tr class="odd">
<td>Blueprint</td>
<td>BP_</td>
<td></td>
<td></td>
</tr>
<tr class="even">
<td>Material</td>
<td>M_</td>
<td></td>
<td></td>
</tr>
<tr class="odd">
<td>Static Mesh</td>
<td>S_</td>
<td></td>
<td>Many use SM_. We use S_.</td>
</tr>
<tr class="even">
<td>Skeletal Mesh</td>
<td>SK_</td>
<td></td>
<td></td>
</tr>
<tr class="odd">
<td>Texture</td>
<td>T_</td>
<td>_?</td>
<td>See <a href="#anc-textures">Textures</a></td>
</tr>
<tr class="even">
<td>Particle System</td>
<td>PS_</td>
<td></td>
<td></td>
</tr>
<tr class="odd">
<td>Widget Blueprint</td>
<td>WBP_</td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
<p><a name="anc-animations"></a></p>
<p><a name="1.2.2"></a></p>
</section>
<section id="animations" class="level4">
<h4 class="anchored" data-anchor-id="animations">1.2.2 Animations</h4>
<table class="caption-top table">
<colgroup>
<col style="width: 30%">
<col style="width: 13%">
<col style="width: 13%">
<col style="width: 42%">
</colgroup>
<thead>
<tr class="header">
<th>Asset Type</th>
<th>Prefix</th>
<th>Suffix</th>
<th>Notes</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>Aim Offset</td>
<td>AO_</td>
<td></td>
<td></td>
</tr>
<tr class="even">
<td>Aim Offset 1D</td>
<td>AO_</td>
<td></td>
<td></td>
</tr>
<tr class="odd">
<td>Animation Blueprint</td>
<td>ABP_</td>
<td></td>
<td></td>
</tr>
<tr class="even">
<td>Animation Composite</td>
<td>AC_</td>
<td></td>
<td></td>
</tr>
<tr class="odd">
<td>Animation Montage</td>
<td>AM_</td>
<td></td>
<td></td>
</tr>
<tr class="even">
<td>Animation Sequence</td>
<td>A_</td>
<td></td>
<td></td>
</tr>
<tr class="odd">
<td>Blend Space</td>
<td>BS_</td>
<td></td>
<td></td>
</tr>
<tr class="even">
<td>Blend Space 1D</td>
<td>BS_</td>
<td></td>
<td></td>
</tr>
<tr class="odd">
<td>Level Sequence</td>
<td>LS_</td>
<td></td>
<td></td>
</tr>
<tr class="even">
<td>Morph Target</td>
<td>MT_</td>
<td></td>
<td></td>
</tr>
<tr class="odd">
<td>Paper Flipbook</td>
<td>PFB_</td>
<td></td>
<td></td>
</tr>
<tr class="even">
<td>Rig</td>
<td>Rig_</td>
<td></td>
<td></td>
</tr>
<tr class="odd">
<td>Control Rig</td>
<td>CR_</td>
<td></td>
<td></td>
</tr>
<tr class="even">
<td>Skeletal Mesh</td>
<td>SK_</td>
<td></td>
<td></td>
</tr>
<tr class="odd">
<td>Skeleton</td>
<td>SKEL_</td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
<p><a name="anc-ai"></a></p>
<p><a name="1.2.3"></a></p>
</section>
</section>
<section id="artificial-intelligence" class="level3">
<h3 class="anchored" data-anchor-id="artificial-intelligence">1.2.3 Artificial Intelligence</h3>
<table class="caption-top table">
<colgroup>
<col style="width: 30%">
<col style="width: 13%">
<col style="width: 13%">
<col style="width: 42%">
</colgroup>
<thead>
<tr class="header">
<th>Asset Type</th>
<th>Prefix</th>
<th>Suffix</th>
<th>Notes</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>AI Controller</td>
<td>AIC_</td>
<td></td>
<td></td>
</tr>
<tr class="even">
<td>Behavior Tree</td>
<td>BT_</td>
<td></td>
<td></td>
</tr>
<tr class="odd">
<td>Blackboard</td>
<td>BB_</td>
<td></td>
<td></td>
</tr>
<tr class="even">
<td>Decorator</td>
<td>BTDecorator_</td>
<td></td>
<td></td>
</tr>
<tr class="odd">
<td>Service</td>
<td>BTService_</td>
<td></td>
<td></td>
</tr>
<tr class="even">
<td>Task</td>
<td>BTTask_</td>
<td></td>
<td></td>
</tr>
<tr class="odd">
<td>Environment Query</td>
<td>EQS_</td>
<td></td>
<td></td>
</tr>
<tr class="even">
<td>EnvQueryContext</td>
<td>EQS_</td>
<td>Context</td>
<td></td>
</tr>
</tbody>
</table>
<p><a name="anc-bp"></a></p>
<p><a name="1.2.4"></a></p><a name="1.2.4">
</a></section><a name="1.2.4">
</a><section id="blueprints" class="level3"><a name="1.2.4">
<h3 class="anchored" data-anchor-id="blueprints">1.2.4 Blueprints</h3>
<table class="caption-top table">
<colgroup>
<col style="width: 30%">
<col style="width: 13%">
<col style="width: 13%">
<col style="width: 42%">
</colgroup>
<thead>
<tr class="header">
<th>Asset Type</th>
<th>Prefix</th>
<th>Suffix</th>
<th>Notes</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>Blueprint</td>
<td>BP_</td>
<td></td>
<td></td>
</tr>
<tr class="even">
<td>Blueprint Component</td>
<td>BP_</td>
<td>Component</td>
<td>I.e. BP_InventoryComponent</td>
</tr>
<tr class="odd">
<td>Blueprint Function Library</td>
<td>BPFL_</td>
<td></td>
<td></td>
</tr>
<tr class="even">
<td>Blueprint Interface</td>
<td>BPI_</td>
<td></td>
<td></td>
</tr>
<tr class="odd">
<td>Blueprint Macro Library</td>
<td>BPML_</td>
<td></td>
<td>Do not use macro libraries if possible.</td>
</tr>
<tr class="even">
<td>Enumeration</td>
<td>E</td>
<td></td>
<td>No underscore.</td>
</tr>
<tr class="odd">
<td>Structure</td>
<td>F or S</td>
<td></td>
<td>No underscore.</td>
</tr>
<tr class="even">
<td>Tutorial Blueprint</td>
<td>TBP_</td>
<td></td>
<td></td>
</tr>
<tr class="odd">
<td>Widget Blueprint</td>
<td>WBP_</td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
</a><p><a name="1.2.4"></a><a name="anc-materials"></a></p>
<p><a name="1.2.5"></a></p>
</section>
<section id="materials" class="level3">
<h3 class="anchored" data-anchor-id="materials">1.2.5 Materials</h3>
<table class="caption-top table">
<colgroup>
<col style="width: 35%">
<col style="width: 12%">
<col style="width: 12%">
<col style="width: 39%">
</colgroup>
<thead>
<tr class="header">
<th>Asset Type</th>
<th>Prefix</th>
<th>Suffix</th>
<th>Notes</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>Material</td>
<td>M_</td>
<td></td>
<td></td>
</tr>
<tr class="even">
<td>Material (Post Process)</td>
<td>PP_</td>
<td></td>
<td></td>
</tr>
<tr class="odd">
<td>Material Function</td>
<td>MF_</td>
<td></td>
<td></td>
</tr>
<tr class="even">
<td>Material Instance</td>
<td>MI_</td>
<td></td>
<td></td>
</tr>
<tr class="odd">
<td>Material Parameter Collection</td>
<td>MPC_</td>
<td></td>
<td></td>
</tr>
<tr class="even">
<td>Subsurface Profile</td>
<td>SP_</td>
<td></td>
<td></td>
</tr>
<tr class="odd">
<td>Physical Materials</td>
<td>PM_</td>
<td></td>
<td></td>
</tr>
<tr class="even">
<td>Decal</td>
<td>M_, MI_</td>
<td>_Decal</td>
<td></td>
</tr>
</tbody>
</table>
<p><a name="anc-textures"></a></p>
<p><a name="1.2.6"></a></p>
</section>
<section id="textures" class="level3">
<h3 class="anchored" data-anchor-id="textures">1.2.6 Textures</h3>
<table class="caption-top table">
<thead>
<tr class="header">
<th>Asset Type</th>
<th>Prefix</th>
<th>Suffix</th>
<th>Notes</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>Texture</td>
<td>T_</td>
<td></td>
<td></td>
</tr>
<tr class="even">
<td>Texture (Diffuse/Albedo/Base Color)</td>
<td>T_</td>
<td>_D</td>
<td></td>
</tr>
<tr class="odd">
<td>Texture (Normal)</td>
<td>T_</td>
<td>_N</td>
<td></td>
</tr>
<tr class="even">
<td>Texture (Roughness)</td>
<td>T_</td>
<td>_R</td>
<td></td>
</tr>
<tr class="odd">
<td>Texture (Alpha/Opacity)</td>
<td>T_</td>
<td>_A</td>
<td></td>
</tr>
<tr class="even">
<td>Texture (Ambient Occlusion)</td>
<td>T_</td>
<td>_O</td>
<td></td>
</tr>
<tr class="odd">
<td>Texture (Bump)</td>
<td>T_</td>
<td>_B</td>
<td></td>
</tr>
<tr class="even">
<td>Texture (Emissive)</td>
<td>T_</td>
<td>_E</td>
<td></td>
</tr>
<tr class="odd">
<td>Texture (Mask)</td>
<td>T_</td>
<td>_M</td>
<td></td>
</tr>
<tr class="even">
<td>Texture (Specular)</td>
<td>T_</td>
<td>_S</td>
<td></td>
</tr>
<tr class="odd">
<td>Texture (Metallic)</td>
<td>T_</td>
<td>_M</td>
<td></td>
</tr>
<tr class="even">
<td>Texture (Packed)</td>
<td>T_</td>
<td>_*</td>
<td>See notes below about <a href="#anc-textures-packing">packing</a>.</td>
</tr>
<tr class="odd">
<td>Texture Cube</td>
<td>TC_</td>
<td></td>
<td></td>
</tr>
<tr class="even">
<td>Media Texture</td>
<td>MT_</td>
<td></td>
<td></td>
</tr>
<tr class="odd">
<td>Render Target</td>
<td>RT_</td>
<td></td>
<td></td>
</tr>
<tr class="even">
<td>Cube Render Target</td>
<td>RTC_</td>
<td></td>
<td></td>
</tr>
<tr class="odd">
<td>Texture Light Profile</td>
<td>TLP</td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
<p><a name="anc-textures-packing"></a></p>
<p><a name="1.2.6.1"></a></p>
<section id="texture-packing" class="level4">
<h4 class="anchored" data-anchor-id="texture-packing">1.2.6.1 Texture Packing</h4>
<p>It is common practice to pack multiple layers of texture data into one texture. An example of this is packing Emissive, Roughness, Ambient Occlusion together as the Red, Green, and Blue channels of a texture respectively. To determine the suffix, simply stack the given suffix letters from above together, e.g.&nbsp;<code>_ERO</code>.</p>
<blockquote class="blockquote">
<p>It is generally acceptable to include an Alpha/Opacity layer in your Diffuse/Albedos alpha channel and as this is common practice, adding <code>A</code> to the <code>_D</code> suffix is optional.</p>
</blockquote>
<p>Packing 4 channels of data into a texture (RGBA) is not recommended except for an Alpha/Opacity mask in the Diffuse/Albedos alpha channel as a texture with an alpha channel incurs more overhead than one without.</p>
<p><a name="anc-misc"></a></p>
<p><a name="1.2.7"></a></p>
</section>
</section>
<section id="miscellaneous" class="level3">
<h3 class="anchored" data-anchor-id="miscellaneous">1.2.7 Miscellaneous</h3>
<table class="caption-top table">
<colgroup>
<col style="width: 33%">
<col style="width: 12%">
<col style="width: 12%">
<col style="width: 41%">
</colgroup>
<thead>
<tr class="header">
<th>Asset Type</th>
<th>Prefix</th>
<th>Suffix</th>
<th>Notes</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>Animated Vector Field</td>
<td>VFA_</td>
<td></td>
<td></td>
</tr>
<tr class="even">
<td>Camera Anim</td>
<td>CA_</td>
<td></td>
<td></td>
</tr>
<tr class="odd">
<td>Color Curve</td>
<td>Curve_</td>
<td>_Color</td>
<td></td>
</tr>
<tr class="even">
<td>Curve Table</td>
<td>Curve_</td>
<td>_Table</td>
<td></td>
</tr>
<tr class="odd">
<td>Data Asset</td>
<td>*_</td>
<td></td>
<td>Prefix should be based on class.</td>
</tr>
<tr class="even">
<td>Data Table</td>
<td>DT_</td>
<td></td>
<td></td>
</tr>
<tr class="odd">
<td>Float Curve</td>
<td>Curve_</td>
<td>_Float</td>
<td></td>
</tr>
<tr class="even">
<td>Foliage Type</td>
<td>FT_</td>
<td></td>
<td></td>
</tr>
<tr class="odd">
<td>Force Feedback Effect</td>
<td>FFE_</td>
<td></td>
<td></td>
</tr>
<tr class="even">
<td>Landscape Grass Type</td>
<td>LG_</td>
<td></td>
<td></td>
</tr>
<tr class="odd">
<td>Landscape Layer</td>
<td>LL_</td>
<td></td>
<td></td>
</tr>
<tr class="even">
<td>Matinee Data</td>
<td>Matinee_</td>
<td></td>
<td></td>
</tr>
<tr class="odd">
<td>Media Player</td>
<td>MP_</td>
<td></td>
<td></td>
</tr>
<tr class="even">
<td>Object Library</td>
<td>OL_</td>
<td></td>
<td></td>
</tr>
<tr class="odd">
<td>Redirector</td>
<td></td>
<td></td>
<td>These should be fixed up ASAP.</td>
</tr>
<tr class="even">
<td>Sprite Sheet</td>
<td>SS_</td>
<td></td>
<td></td>
</tr>
<tr class="odd">
<td>Static Vector Field</td>
<td>VF_</td>
<td></td>
<td></td>
</tr>
<tr class="even">
<td>Substance Graph Instance</td>
<td>SGI_</td>
<td></td>
<td></td>
</tr>
<tr class="odd">
<td>Substance Instance Factory</td>
<td>SIF_</td>
<td></td>
<td></td>
</tr>
<tr class="even">
<td>Touch Interface Setup</td>
<td>TI_</td>
<td></td>
<td></td>
</tr>
<tr class="odd">
<td>Vector Curve</td>
<td>Curve_</td>
<td>_Vector</td>
<td></td>
</tr>
</tbody>
</table>
<p><a name="anc-paper2d"></a></p>
<p><a name="1.2.8"></a></p>
</section>
<section id="paper-2d" class="level3">
<h3 class="anchored" data-anchor-id="paper-2d">1.2.8 Paper 2D</h3>
<table class="caption-top table">
<colgroup>
<col style="width: 30%">
<col style="width: 13%">
<col style="width: 13%">
<col style="width: 42%">
</colgroup>
<thead>
<tr class="header">
<th>Asset Type</th>
<th>Prefix</th>
<th>Suffix</th>
<th>Notes</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>Paper Flipbook</td>
<td>PFB_</td>
<td></td>
<td></td>
</tr>
<tr class="even">
<td>Sprite</td>
<td>SPR_</td>
<td></td>
<td></td>
</tr>
<tr class="odd">
<td>Sprite Atlas Group</td>
<td>SPRG_</td>
<td></td>
<td></td>
</tr>
<tr class="even">
<td>Tile Map</td>
<td>TM_</td>
<td></td>
<td></td>
</tr>
<tr class="odd">
<td>Tile Set</td>
<td>TS_</td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
<p><a name="anc-physics"></a></p>
<p><a name="1.2.9"></a></p>
</section>
<section id="physics" class="level3">
<h3 class="anchored" data-anchor-id="physics">1.2.9 Physics</h3>
<table class="caption-top table">
<colgroup>
<col style="width: 30%">
<col style="width: 13%">
<col style="width: 13%">
<col style="width: 42%">
</colgroup>
<thead>
<tr class="header">
<th>Asset Type</th>
<th>Prefix</th>
<th>Suffix</th>
<th>Notes</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>Physical Material</td>
<td>PM_</td>
<td></td>
<td></td>
</tr>
<tr class="even">
<td>Physics Asset</td>
<td>PHYS_</td>
<td></td>
<td></td>
</tr>
<tr class="odd">
<td>Destructible Mesh</td>
<td>DM_</td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
<p><a name="anc-sounds"></a></p>
<p><a name="1.2.10"></a></p>
</section>
<section id="sounds" class="level3">
<h3 class="anchored" data-anchor-id="sounds">1.2.10 Sounds</h3>
<table class="caption-top table">
<colgroup>
<col style="width: 30%">
<col style="width: 13%">
<col style="width: 13%">
<col style="width: 42%">
</colgroup>
<thead>
<tr class="header">
<th>Asset Type</th>
<th>Prefix</th>
<th>Suffix</th>
<th>Notes</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>Dialogue Voice</td>
<td>DV_</td>
<td></td>
<td></td>
</tr>
<tr class="even">
<td>Dialogue Wave</td>
<td>DW_</td>
<td></td>
<td></td>
</tr>
<tr class="odd">
<td>Media Sound Wave</td>
<td>MSW_</td>
<td></td>
<td></td>
</tr>
<tr class="even">
<td>Reverb Effect</td>
<td>Reverb_</td>
<td></td>
<td></td>
</tr>
<tr class="odd">
<td>Sound Attenuation</td>
<td>ATT_</td>
<td></td>
<td></td>
</tr>
<tr class="even">
<td>Sound Class</td>
<td></td>
<td></td>
<td>No prefix/suffix. Should be put in a folder called SoundClasses</td>
</tr>
<tr class="odd">
<td>Sound Concurrency</td>
<td></td>
<td>_SC</td>
<td>Should be named after a SoundClass</td>
</tr>
<tr class="even">
<td>Sound Cue</td>
<td>A_</td>
<td>_Cue</td>
<td></td>
</tr>
<tr class="odd">
<td>Sound Mix</td>
<td>Mix_</td>
<td></td>
<td></td>
</tr>
<tr class="even">
<td>Sound Wave</td>
<td>A_</td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
<p><a name="anc-ui"></a></p>
<p><a name="1.2.11"></a></p>
</section>
<section id="user-interface" class="level3">
<h3 class="anchored" data-anchor-id="user-interface">1.2.11 User Interface</h3>
<table class="caption-top table">
<colgroup>
<col style="width: 30%">
<col style="width: 13%">
<col style="width: 13%">
<col style="width: 42%">
</colgroup>
<thead>
<tr class="header">
<th>Asset Type</th>
<th>Prefix</th>
<th>Suffix</th>
<th>Notes</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>Font</td>
<td>Font_</td>
<td></td>
<td></td>
</tr>
<tr class="even">
<td>Slate Brush</td>
<td>Brush_</td>
<td></td>
<td></td>
</tr>
<tr class="odd">
<td>Slate Widget Style</td>
<td>Style_</td>
<td></td>
<td></td>
</tr>
<tr class="even">
<td>Widget Blueprint</td>
<td>WBP_</td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
<p><a name="anc-effects"></a></p>
<p><a name="1.2.12"></a></p>
</section>
<section id="effects" class="level3">
<h3 class="anchored" data-anchor-id="effects">1.2.12 Effects</h3>
<table class="caption-top table">
<colgroup>
<col style="width: 30%">
<col style="width: 13%">
<col style="width: 13%">
<col style="width: 42%">
</colgroup>
<thead>
<tr class="header">
<th>Asset Type</th>
<th>Prefix</th>
<th>Suffix</th>
<th>Notes</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>Particle System</td>
<td>PS_</td>
<td></td>
<td></td>
</tr>
<tr class="even">
<td>Material (Post Process)</td>
<td>PP_</td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
<p><strong><a href="#table-of-contents">⬆ Back to Top</a></strong></p>
<p><a name="2"></a></p>
<p><a name="structure"></a></p>
</section>
</section>
<section id="content-directory-structure" class="level2">
<h2 class="anchored" data-anchor-id="content-directory-structure">2. Content Directory Structure</h2>
<p>Equally important as asset names, the directory structure style of a project should be considered law. Asset naming conventions and content directory structure go hand in hand, and a violation of either causes unneeded chaos.</p>
<p>There are multiple ways to lay out the content of a UE4 project. In this style, we will be using a structure that relies more on filtering and search abilities of the Content Browser for those working with assets to find assets of a specific type instead of another common structure that groups asset types with folders.</p>
<blockquote class="blockquote">
<p>If you are using the prefix <a href="#1.2">naming convention</a> above, using folders to contain assets of similar types such as <code>Meshes</code>, <code>Textures</code>, and <code>Materials</code> is a redundant practice as asset types are already both sorted by prefix as well as able to be filtered in the content browser.</p>
</blockquote>
<a name="2e1"></a><a> ### 2e1 Example Project Content Structure
</a><pre><a>|-- Content
|-- </a><a href="#2.2">GenericShooter</a>
|-- Art
| |-- Industrial
| | |-- Ambient
| | |-- Machinery
| | |-- Pipes
| |-- Nature
| | |-- Ambient
| | |-- Foliage
| | |-- Rocks
| | |-- Trees
| |-- Office
|-- Characters
| |-- Bob
| |-- Common
| | |-- <a href="#2.7">Animations</a>
| | |-- Audio
| |-- Jack
| |-- Steve
| |-- <a href="#2.1.3">Zoe</a>
|-- <a href="#2.5">Core</a>
| |-- Characters
| |-- Engine
| |-- <a href="#2.1.2">GameModes</a>
| |-- Interactables
| |-- Pickups
| |-- Weapons
|-- Effects
| |-- Electrical
| |-- Fire
| |-- Weather
|-- <a href="#2.4">Maps</a>
| |-- Campaign1
| |-- Campaign2
|-- <a href="#2.8">MaterialLibrary</a>
| |-- Debug
| |-- Metal
| |-- Paint
| |-- Utility
| |-- Weathering
|-- Placeables
| |-- Pickups
|-- Weapons
|-- Common
|-- Pistols
| |-- DesertEagle
| |-- RocketPistol
|-- Rifles
</pre>
<p>The reasons for this structure are listed in the following sub-sections.</p>
<section id="sections-1" class="level3">
<h3 class="anchored" data-anchor-id="sections-1">Sections</h3>
<blockquote class="blockquote">
<p>2.1 <a href="#structure-folder-names">Folder Names</a></p>
</blockquote>
<blockquote class="blockquote">
<p>2.2 <a href="#structure-top-level">Top-Level Folders</a></p>
</blockquote>
<blockquote class="blockquote">
<p>2.3 <a href="#structure-developers">Developer Folders</a></p>
</blockquote>
<blockquote class="blockquote">
<p>2.4 <a href="#structure-maps">Maps</a></p>
</blockquote>
<blockquote class="blockquote">
<p>2.5 <a href="#structure-core">Core</a></p>
</blockquote>
<blockquote class="blockquote">
<p>2.6 <a href="#structure-assettypes"><code>Assets</code> and <code>AssetTypes</code></a></p>
</blockquote>
<blockquote class="blockquote">
<p>2.7 <a href="#structure-large-sets">Large Sets</a></p>
</blockquote>
<blockquote class="blockquote">
<p>2.8 <a href="#structure-material-library">Material Library</a></p>
</blockquote>
<p><a name="2.1"></a></p>
<p><a name="structure-folder-names"></a><a> ### 2.1 Folder Names</a></p><a>
<p>These are common rules for naming any folder in the content structure.</p>
</a><p><a></a><a name="2.1.1"></a></p>
<section id="always-use-pascalcase" class="level4">
<h4 class="anchored" data-anchor-id="always-use-pascalcase">2.1.1 Always Use PascalCase<a href="#terms-cases"><sup>*</sup></a></h4>
<p>PascalCase refers to starting a name with a capital letter and then instead of using spaces, every following word also starts with a capital letter. For example, <code>DesertEagle</code>, <code>RocketPistol</code>, and <code>ASeriesOfWords</code>.</p>
<p>See <a href="#terms-cases">Cases</a>.</p>
<p><a name="2.1.2"></a></p>
</section>
<section id="never-use-spaces" class="level4">
<h4 class="anchored" data-anchor-id="never-use-spaces">2.1.2 Never Use Spaces</h4>
<p>Re-enforcing <a href="#2.1.1">2.1.1</a>, never use spaces. Spaces can cause various engineering tools and batch processes to fail. Ideally, your projects root also contains no spaces and is located somewhere such as <code>D:\Project</code> instead of <code>C:\Users\My Name\My Documents\Unreal Projects</code>.</p>
<p><a name="2.1.3"></a></p>
</section>
<section id="never-use-unicode-characters-and-other-symbols" class="level4">
<h4 class="anchored" data-anchor-id="never-use-unicode-characters-and-other-symbols">2.1.3 Never Use Unicode Characters And Other Symbols</h4>
<p>If one of your game characters is named Zoë, its folder name should be <code>Zoe</code>. Unicode characters can be worse than <a href="#2.1.2">Spaces</a> for engineering tool and some parts of UE4 dont support Unicode characters in paths either.</p>
<p>Related to this, if your project has <a href="https://answers.unrealengine.com/questions/101207/undefined.html">unexplained issues</a> and your computers user name has a Unicode character (i.e.&nbsp;your name is <code>Zoë</code>), any project located in your <code>My Documents</code> folder will suffer from this issue. Often simply moving your project to something like <code>D:\Project</code> will fix these mysterious issues.</p>
<p>Using other characters outside <code>a-z</code>, <code>A-Z</code>, and <code>0-9</code> such as <code>@</code>, <code>-</code>, <code>_</code>, <code>,</code>, <code>*</code>, and <code>#</code> can also lead to unexpected and hard to track issues on other platforms, source control, and weaker engineering tools.</p>
<p><a name="2.2"></a></p>
<p><a name="structure-top-level"></a><a> ### 2.2 Use A Top Level Folder For Project Specific Assets</a></p><a>
<p>All of a projects assets should exist in a folder named after the project. For example, if your project is named Generic Shooter, <em>all</em> of its content should exist in <code>Content/GenericShooter</code>.</p>
</a><blockquote class="blockquote"><a>
</a><p><a>The <code>Developers</code> folder is not for assets that your project relies on and therefore is not project specific. See </a><a href="#2.3">Developer Folders</a> for details about this.</p>
</blockquote>
<p>There are multiple reasons for this approach.</p>
<p><a name="2.2.1"></a></p>
</section>
<section id="no-global-assets" class="level4">
<h4 class="anchored" data-anchor-id="no-global-assets">2.2.1 No Global Assets</h4>
<p>Often in code style guides it is written that you should not pollute the global namespace and this follows the same principle. When assets are allowed to exist outside of a project folder, it often becomes much harder to enforce a strict structure layout as assets not in a folder encourages the bad behavior of not having to organize assets.</p>
<p>Every asset should have a purpose, otherwise it does not belong in a project. If an asset is an experimental test and shouldnt be used by the project it should be put in a <a href="#2.3"><code>Developer</code></a> folder.</p>
<p><a name="2.2.2"></a></p>
</section>
<section id="reduce-migration-conflicts" class="level4">
<h4 class="anchored" data-anchor-id="reduce-migration-conflicts">2.2.2 Reduce Migration Conflicts</h4>
<p>When working on multiple projects it is common for a team to copy assets from one project to another if they have made something useful for both. When this occurs, the easiest way to perform the copy is to use the Content Browsers Migrate functionality as it will copy over not just the selected asset but all of its dependencies.</p>
<p>These dependencies are what can easily get you into trouble. If two projects assets do not have a top level folder and they happen to have similarly named or already previously migrated assets, a new migration can accidentally wipe any changes to the existing assets.</p>
<p>This is also the primary reason why Epics Marketplace staff enforces the same policy for submitted assets.</p>
<p>After a migration, safe merging of assets can be done using the Replace References tool in the content browser with the added clarity of assets not belonging to a projects top level folder are clearly pending a merge. Once assets are merged and fully migrated, there shouldnt be another top level folder in your Content tree. This method is <em>100%</em> guaranteed to make any migrations that occur completely safe.</p>
<p><a name="2.2.2e1"></a></p>
<section id="e1-master-material-example" class="level5">
<h5 class="anchored" data-anchor-id="e1-master-material-example">2.2.2e1 Master Material Example</h5>
<p>For example, say you created a master material in one project that you would like to use in another project so you migrated that asset over. If this asset is not in a top level folder, it may have a name like <code>Content/MaterialLibrary/M_Master</code>. If the target project doesnt have a master material already, this should work without issue.</p>
<p>As work on one or both projects progress, their respective master materials may change to be tailored for their specific projects due to the course of normal development.</p>
<p>The issue comes when, for example, an artist for one project created a nice generic modular set of static meshes and someone wants to include that set of static meshes in the second project. If the artist who created the assets used material instances based on <code>Content/MaterialLibrary/M_Master</code> as theyre instructed to, when a migration is performed there is a great chance of conflict for the previously migrated <code>Content/MaterialLibrary/M_Master</code> asset.</p>
<p>This issue can be hard to predict and hard to account for. The person migrating the static meshes may not be the same person who is familiar with the development of both projects master material, and they may not be even aware that the static meshes in question rely on material instances which then rely on the master material. The Migrate tool requires the entire chain of dependencies to work however, and so it will be forced to grab <code>Content/MaterialLibrary/M_Master</code> when it copies these assets to the other project and it will overwrite the existing asset.</p>
<p>It is at this point where if the master materials for both projects are incompatible in <em>any way</em>, you risk breaking possibly the entire material library for a project as well as any other dependencies that may have already been migrated, simply because assets were not stored in a top level folder. The simple migration of static meshes now becomes a very ugly task.</p>
<p><a name="2.2.3"></a></p>
</section>
</section>
<section id="samples-templates-and-marketplace-content-are-risk-free" class="level4">
<h4 class="anchored" data-anchor-id="samples-templates-and-marketplace-content-are-risk-free">2.2.3 Samples, Templates, and Marketplace Content Are Risk-Free</h4>
<p>An extension to <a href="#2.2.2">2.2.2</a>, if a team member decides to add sample content, template files, or assets they bought from the marketplace, it is guaranteed, as long your projects top-level folder is uniquely named,that these new assets will not interfere with your project.</p>
<p>You can not trust marketplace content to fully conform to the <a href="#2.2">top level folder rule</a>. There exists many assets that have the majority of their content in a top level folder but also have possibly modified Epic sample content as well as level files polluting the global <code>Content</code> folder.</p>
<p>When adhering to <a href="#2.2">2.2</a>, the worst marketplace conflict you can have is if two marketplace assets both have the same Epic sample content. If all your assets are in a project specific folder, including sample content you may have moved into your folder, your project will never break.</p>
</section>
<section id="dlc-sub-projects-and-patches-are-easily-maintained" class="level4">
<h4 class="anchored" data-anchor-id="dlc-sub-projects-and-patches-are-easily-maintained">2.2.4 DLC, Sub-Projects, and Patches Are Easily Maintained</h4>
<p>If your project plans to release DLC or has multiple sub-projects associated with it that may either be migrated out or simply not cooked in a build, assets relating to these projects should have their own separate top level content folder. This make cooking DLC separate from main project content far easier. Sub-projects can also be migrated in and out with minimal effort. If you need to change a material of an asset or add some very specific asset override behavior in a patch, you can easily put these changes in a patch folder and work safely without the chance of breaking the core project.</p>
<p><a name="2.3"></a></p>
<p><a name="structure-developers"></a></p>
</section>
</section>
<section id="use-developers-folder-for-local-testing" class="level3">
<h3 class="anchored" data-anchor-id="use-developers-folder-for-local-testing">2.3 Use Developers Folder For Local Testing</h3>
<p>During a projects development, it is very common for team members to have a sort of sandbox where they can experiment freely without risking the core project. Because this work may be ongoing, these team members may wish to put their assets on a projects source control server. Not all teams require use of Developer folders, but ones that do use them often run into a common problem with assets submitted to source control.</p>
<p>It is very easy for a team member to accidentally use assets that are not ready for use, which will cause issues once those assets are removed. For example, an artist may be iterating on a modular set of static meshes and still working on getting their sizing and grid snapping correct. If a world builder sees these assets in the main project folder, they might use them all over a level not knowing they could be subject to incredible change and/or removal. This causes massive amounts of re-working for everyone on the team to resolve.</p>
<p>If these modular assets were placed in a Developer folder, the world builder should never have had a reason to use them and the whole issue would never happen. The Content Browser has specific View Options that will hide Developer folders (they are hidden by default) making it impossible to accidentally use Developer assets under normal use.</p>
<p>Once the assets are ready for use, an artist simply has to move the assets into the project specific folder and fix up redirectors. This is essentially promoting the assets from experimental to production.</p>
<p><a name="2.4"></a></p>
<p><a name="structure-maps"></a></p>
</section>
<section id="all-map-files-belong-in-a-folder-called-maps" class="level3">
<h3 class="anchored" data-anchor-id="all-map-files-belong-in-a-folder-called-maps">2.4 All Map<a href="#terms-level-map"><sup>*</sup></a> Files Belong In A Folder Called Maps</h3>
<p>Map files are incredibly special and it is common for every project to have its own map naming system, especially if they work with sub-levels or streaming levels. No matter what system of map organization is in place for the specific project, all levels should belong in <code>/Content/Project/Maps</code>.</p>
<p>Being able to tell someone to open a specific map without having to explain where it is is a great time saver and general quality of life improvement. It is common for levels to be within sub-folders of <code>Maps</code>, such as <code>Maps/Campaign1/</code> or <code>Maps/Arenas</code>, but the most important thing here is that they all exist within <code>/Content/Project/Maps</code>.</p>
<p>This also simplifies the job of cooking for engineers. Wrangling levels for a build process can be extremely frustrating if they have to dig through arbitrary folders for them. If a teams maps are all in one place, it is much harder to accidentally not cook a map in a build. It also simplifies lighting build scripts as well as QA processes.</p>
<p><a name="2.5"></a></p>
<p><a name="structure-core"></a></p>
</section>
<section id="use-a-core-folder-for-critical-blueprints-and-other-assets" class="level3">
<h3 class="anchored" data-anchor-id="use-a-core-folder-for-critical-blueprints-and-other-assets">2.5 Use A <code>Core</code> Folder For Critical Blueprints And Other Assets</h3>
<p>Use <code>/Content/Project/Core</code> folder for assets that are absolutely fundamental to a projects workings. For example, base <code>GameMode</code>, <code>Character</code>, <code>PlayerController</code>, <code>GameState</code>, <code>PlayerState</code>, and related Blueprints should live here.</p>
<p>This creates a very clear “dont touch these” message for other team members. Non-engineers should have very little reason to enter the <code>Core</code> folder. Following good code structure style, designers should be making their gameplay tweaks in child classes that expose functionality. World builders should be using prefab Blueprints in designated folders instead of potentially abusing base classes.</p>
<p>For example, if your project requires pickups that can be placed in a level, there should exist a base Pickup class in <code>Core/Pickups</code> that defines base behavior for a pickup. Specific pickups such as a Health or Ammo should exist in a folder such as <code>/Content/Project/Placeables/Pickups/</code>. Game designers can define and tweak pickups in this folder however they please, but they should not touch <code>Core/Pickups</code> as they may unintentionally break pickups project-wide.</p>
<p><a name="2.6"></a></p>
<p><a name="structure-assettypes"></a></p>
</section>
<section id="do-not-create-folders-called-assets-or-assettypes" class="level3">
<h3 class="anchored" data-anchor-id="do-not-create-folders-called-assets-or-assettypes">2.6 Do Not Create Folders Called <code>Assets</code> or <code>AssetTypes</code></h3>
<p><a name="2.6.1"></a></p>
<section id="creating-a-folder-named-assets-is-redundant." class="level4">
<h4 class="anchored" data-anchor-id="creating-a-folder-named-assets-is-redundant.">2.6.1 Creating a folder named <code>Assets</code> is redundant.</h4>
<p>All assets are assets.</p>
<p><a name="2.6.2"></a></p>
</section>
<section id="creating-a-folder-named-meshes-textures-or-materials-is-redundant." class="level4">
<h4 class="anchored" data-anchor-id="creating-a-folder-named-meshes-textures-or-materials-is-redundant.">2.6.2 Creating a folder named <code>Meshes</code>, <code>Textures</code>, or <code>Materials</code> is redundant.</h4>
<p>All asset names are named with their asset type in mind. These folders offer only redundant information and the use of these folders can easily be replaced with the robust and easy to use filtering system the Content Browser provides.</p>
<p>Want to view only static mesh in <code>Environment/Rocks/</code>? Simply turn on the Static Mesh filter. If all assets are named correctly, they will also be sorted in alphabetical order regardless of prefixes. Want to view both static meshes and skeletal meshes? Simply turn on both filters. This eliminates the need to potentially have to <code>Control-Click</code> select two folders in the Content Browsers tree view.</p>
<blockquote class="blockquote">
<p>This also extends the full path name of an asset for very little benefit. The <code>S_</code> prefix for a static mesh is only two characters, whereas <code>Meshes/</code> is seven characters.</p>
</blockquote>
<p>Not doing this also prevents the inevitability of someone putting a static mesh or a texture in a <code>Materials</code> folder.</p>
<p><a name="2.7"></a></p>
<p><a name="structure-large-sets"></a></p>
</section>
</section>
<section id="very-large-asset-sets-get-their-own-folder-layout" class="level3">
<h3 class="anchored" data-anchor-id="very-large-asset-sets-get-their-own-folder-layout">2.7 Very Large Asset Sets Get Their Own Folder Layout</h3>
<p>This can be seen as a pseudo-exception to <a href="#2.6">2.6</a>.</p>
<p>There are certain asset types that have a huge volume of related files where each asset has a unique purpose. The two most common are Animation and Audio assets. If you find yourself having 15+ of these assets that belong together, they should be together.</p>
<p>For example, animations that are shared across multiple characters should lay in <code>Characters/Common/Animations</code> and may have sub-folders such as <code>Locomotion</code> or <code>Cinematic</code>.</p>
<blockquote class="blockquote">
<p>This does not apply to assets like textures and materials. It is common for a <code>Rocks</code> folder to have a large amount of textures if there are a large amount of rocks, however these textures are generally only related to a few specific rocks and should be named appropriately. Even if these textures are part of a <a href="#2.8">Material Library</a>.</p>
</blockquote>
<p><a name="2.8"></a></p>
<p><a name="structure-material-library"></a></p>
</section>
<section id="materiallibrary" class="level3">
<h3 class="anchored" data-anchor-id="materiallibrary">2.8 <code>MaterialLibrary</code></h3>
<p>If your project makes use of master materials, layered materials, or any form of reusable materials or textures that do not belong to any subset of assets, these assets should be located in <code>Content/Project/MaterialLibrary</code>.</p>
<p>This way all global materials have a place to live and are easily located.</p>
<blockquote class="blockquote">
<p>This also makes it incredibly easy to enforce a use material instances only policy within a project. If all artists and assets should be using material instances, then the only regular material assets that should exist are within this folder. You can easily verify this by searching for base materials in any folder that isnt the <code>MaterialLibrary</code>.</p>
</blockquote>
<p>The <code>MaterialLibrary</code> doesnt have to consist of purely materials. Shared utility textures, material functions, and other things of this nature should be stored here as well within folders that designate their intended purpose. For example, generic noise textures should be located in <code>MaterialLibrary/Utility</code>.</p>
<p>Any testing or debug materials should be within <code>MaterialLibrary/Debug</code>. This allows debug materials to be easily stripped from a project before shipping and makes it incredibly apparent if production assets are using them if reference errors are shown.</p>
<p><a name="2.9"></a></p>
<p><a name="structure-no-empty-folders"></a></p>
</section>
<section id="no-empty-folders" class="level3">
<h3 class="anchored" data-anchor-id="no-empty-folders">2.9 No Empty Folders</h3>
<p>There simply shouldnt be any empty folders. They clutter the content browser.</p>
<p>If you find that the content browser has an empty folder you cant delete, you should perform the following: 1. Be sure youre using source control. 1. Immediately run Fix Up Redirectors on your project. 1. Navigate to the folder on-disk and delete the assets inside. 1. Close the editor. 1. Make sure your source control state is in sync (i.e.&nbsp;if using Perforce, run a Reconcile Offline Work on your content directory) 1. Open the editor. Confirm everything still works as expected. If it doesnt, revert, figure out what went wrong, and try again. 1. Ensure the folder is now gone. 1. Submit changes to source control.</p>
<p><strong><a href="#table-of-contents">⬆ Back to Top</a></strong></p>
<p><a name="3"></a></p>
<p><a name="bp"></a></p>
</section>
</section>
<section id="blueprints-1" class="level2">
<h2 class="anchored" data-anchor-id="blueprints-1">3. Blueprints</h2>
<p>This section will focus on Blueprint classes and their internals. When possible, style rules conform to <a href="https://docs.unrealengine.com/latest/INT/Programming/Development/CodingStandard">Epics Coding Standard</a>.</p>
<p>Remember: Blueprinting badly bears blunders, beware! (Phrase by <a href="http://github.com/KorkuVeren">KorkuVeren</a>)</p>
<section id="sections-2" class="level3">
<h3 class="anchored" data-anchor-id="sections-2">Sections</h3>
<blockquote class="blockquote">
<p>3.1 <a href="#bp-compiling">Compiling</a></p>
</blockquote>
<blockquote class="blockquote">
<p>3.2 <a href="#bp-vars">Variables</a></p>
</blockquote>
<blockquote class="blockquote">
<p>3.3 <a href="#bp-functions">Functions</a></p>
</blockquote>
<blockquote class="blockquote">
<p>3.4 <a href="#bp-graphs">Graphs</a></p>
</blockquote>
<p><a name="3.1"></a></p>
<p><a name="bp-compiling"></a></p>
</section>
<section id="compiling" class="level3">
<h3 class="anchored" data-anchor-id="compiling">3.1 Compiling</h3>
<p>All blueprints should compile with zero warnings and zero errors. You should fix blueprint warnings and errors immediately as they can quickly cascade into very scary unexpected behavior.</p>
<p>Do <em>not</em> submit broken blueprints to source control. If you must store them on source control, shelve them instead.</p>
<p>Broken blueprints can cause problems that manifest in other ways, such as broken references, unexpected behavior, cooking failures, and frequent unneeded recompilation. A broken blueprint has the power to break your entire game.</p>
<p><a name="3.2"></a></p>
<p><a name="bp-vars"></a></p>
</section>
<section id="variables" class="level3">
<h3 class="anchored" data-anchor-id="variables">3.2 Variables</h3>
<p>The words <code>variable</code> and <code>property</code> may be used interchangeably.</p>
<section id="sections-3" class="level4">
<h4 class="anchored" data-anchor-id="sections-3">Sections</h4>
<blockquote class="blockquote">
<p>3.2.1 <a href="#bp-vars">Naming</a></p>
</blockquote>
<blockquote class="blockquote">
<p>3.2.2 <a href="#bp-vars-editable">Editable</a></p>
</blockquote>
<blockquote class="blockquote">
<p>3.2.3 <a href="#bp-vars-categories">Categories</a></p>
</blockquote>
<blockquote class="blockquote">
<p>3.2.4 <a href="#bp-vars-access">Access</a></p>
</blockquote>
<blockquote class="blockquote">
<p>3.2.5 <a href="#bp-vars-advanced">Advanced</a></p>
</blockquote>
<blockquote class="blockquote">
<p>3.2.6 <a href="#bp-vars-transient">Transient</a></p>
</blockquote>
<blockquote class="blockquote">
<p>3.2.7 <a href="#bp-vars-config">Config</a></p>
</blockquote>
<p><a name="3.2.1"></a></p>
<p><a name="bp-var-naming"></a></p>
</section>
<section id="naming" class="level4">
<h4 class="anchored" data-anchor-id="naming">3.2.1 Naming</h4>
<p><a name="3.2.1.1"></a></p>
<p><a name="bp-var-naming-nouns"></a></p>
<section id="nouns" class="level5">
<h5 class="anchored" data-anchor-id="nouns">3.2.1.1 Nouns</h5>
<p>All non-boolean variable names must be clear, unambiguous, and descriptive nouns.</p>
<p><a name="3.2.1.2"></a></p>
<p><a name="bp-var-naming-case"></a></p>
</section>
<section id="pascalcase-1" class="level5">
<h5 class="anchored" data-anchor-id="pascalcase-1">3.2.1.2 PascalCase</h5>
<p>All non-boolean variables should be in the form of <a href="#terms-cases">PascalCase</a>.</p>
<p><a name="3.2.1.2e"></a></p>
<section id="e-examples" class="level6">
<h6 class="anchored" data-anchor-id="e-examples">3.2.1.2e Examples:</h6>
<ul>
<li><code>Score</code></li>
<li><code>Kills</code></li>
<li><code>TargetPlayer</code></li>
<li><code>Range</code></li>
<li><code>CrosshairColor</code></li>
<li><code>AbilityID</code></li>
</ul>
<p><a name="3.2.1.3"></a></p>
<p><a name="bp-var-bool-prefix"></a></p>
</section>
</section>
<section id="boolean-b-prefix" class="level5">
<h5 class="anchored" data-anchor-id="boolean-b-prefix">3.2.1.3 Boolean <code>b</code> Prefix</h5>
<p>All booleans should be named in PascalCase but prefixed with a lowercase <code>b</code>.</p>
<p>Example: Use <code>bDead</code> and <code>bEvil</code>, <strong>not</strong> <code>Dead</code> and <code>Evil</code>.</p>
<p>UE4 Blueprint editors know not to include the <code>b</code> in user-friendly displays of the variable.</p>
<p><a name="3.2.1.4"></a></p>
<p><a name="bp-var-bool-names"></a></p>
</section>
<section id="boolean-names" class="level5">
<h5 class="anchored" data-anchor-id="boolean-names">3.2.1.4 Boolean Names</h5>
<p><a name="3.2.1.4.1"></a></p>
<section id="general-and-independent-state-information" class="level6">
<h6 class="anchored" data-anchor-id="general-and-independent-state-information">3.2.1.4.1 General And Independent State Information</h6>
<p>All booleans should be named as descriptive adjectives when possible if representing general information. Do not include words that phrase the variable as a question, such as <code>Is</code>. This is reserved for functions.</p>
<p>Example: Use <code>bDead</code> and <code>bHostile</code> <strong>not</strong> <code>bIsDead</code> and <code>bIsHostile</code>.</p>
<p>Try to not use verbs such as <code>bRunning</code>. Verbs tend to lead to complex states.</p>
<p><a name="3.2.1.4.2"></a></p>
</section>
<section id="complex-states" class="level6">
<h6 class="anchored" data-anchor-id="complex-states">3.2.1.4.2 Complex States</h6>
<p>Do not to use booleans to represent complex and/or dependent states. This makes state adding and removing complex and no longer easily readable. Use an enumeration instead.</p>
<p>Example: When defining a weapon, do <strong>not</strong> use <code>bReloading</code> and <code>bEquipping</code> if a weapon cant be both reloading and equipping. Define an enumeration named <code>EWeaponState</code> and use a variable with this type named <code>WeaponState</code> instead. This makes it far easier to add new states to weapons.</p>
<p>Example: Do <strong>not</strong> use <code>bRunning</code> if you also need <code>bWalking</code> or <code>bSprinting</code>. This should be defined as an enumeration with clearly defined state names.</p>
<p><a name="3.2.1.5"></a></p>
<p><a name="bp-vars-naming-context"></a></p>
</section>
</section>
<section id="considered-context" class="level5">
<h5 class="anchored" data-anchor-id="considered-context">3.2.1.5 Considered Context</h5>
<p>All variable names must not be redundant with their context as all variable references in Blueprint will always have context.</p>
<p><a name="3.2.1.5e"></a></p>
<section id="e-examples-1" class="level6">
<h6 class="anchored" data-anchor-id="e-examples-1">3.2.1.5e Examples:</h6>
<p>Consider a Blueprint called <code>BP_PlayerCharacter</code>.</p>
<p><strong>Bad</strong></p>
<ul>
<li><code>PlayerScore</code></li>
<li><code>PlayerKills</code></li>
<li><code>MyTargetPlayer</code></li>
<li><code>MyCharacterName</code></li>
<li><code>CharacterSkills</code></li>
<li><code>ChosenCharacterSkin</code></li>
</ul>
<p>All of these variables are named redundantly. It is implied that the variable is representative of the <code>BP_PlayerCharacter</code> it belongs to because it is <code>BP_PlayerCharacter</code> that is defining these variables.</p>
<p><strong>Good</strong></p>
<ul>
<li><code>Score</code></li>
<li><code>Kills</code></li>
<li><code>TargetPlayer</code></li>
<li><code>Name</code></li>
<li><code>Skills</code></li>
<li><code>Skin</code></li>
</ul>
<p><a name="3.2.1.6"></a></p>
<p><a name="bp-vars-naming-atomic"></a></p>
</section>
</section>
<section id="do-not-include-atomic-type-names" class="level5">
<h5 class="anchored" data-anchor-id="do-not-include-atomic-type-names">3.2.1.6 Do <em>Not</em> Include Atomic Type Names</h5>
<p>Atomic or primitive variables are variables that represent data in their simplest form, such as booleans, integers, floats, and enumerations.</p>
<p>Strings and vectors are considered atomic in terms of style when working with Blueprints, however they are technically not atomic.</p>
<blockquote class="blockquote">
<p>While vectors consist of three floats, vectors are often able to be manipulated as a whole, same with rotators.</p>
</blockquote>
<blockquote class="blockquote">
<p>Do <em>not</em> consider Text variables as atomic, they are secretly hiding localization functionality. The atomic type of a string of characters is <code>String</code>, not <code>Text</code>.</p>
</blockquote>
<p>Atomic variables should not have their type name in their name.</p>
<p>Example: Use <code>Score</code>, <code>Kills</code>, and <code>Description</code> <strong>not</strong> <code>ScoreFloat</code>, <code>FloatKills</code>, <code>DescriptionString</code>.</p>
<p>The only exception to this rule is when a variable represents a number of something to be counted <em>and</em> when using a name without a variable type is not easy to read.</p>
<p>Example: A fence generator needs to generate X number of posts. Store X in <code>NumPosts</code> or <code>PostsCount</code> instead of <code>Posts</code> as <code>Posts</code> may potentially read as an Array of a variable type named <code>Post</code>.</p>
<p><a name="3.2.1.7"></a></p>
<p><a name="bp-vars-naming-complex"></a></p>
</section>
<section id="do-include-non-atomic-type-names" class="level5">
<h5 class="anchored" data-anchor-id="do-include-non-atomic-type-names">3.2.1.7 Do Include Non-Atomic Type Names</h5>
<p>Non-atomic or complex variables are variables that represent data as a collection of atomic variables. Structs, Classes, Interfaces, and primitives with hidden behavior such as <code>Text</code> and <code>Name</code> all qualify under this rule.</p>
<blockquote class="blockquote">
<p>While an Array of an atomic variable type is a list of variables, Arrays do not change the atomicness of a variable type.</p>
</blockquote>
<p>These variables should include their type name while still considering their context.</p>
<p>If a class owns an instance of a complex variable, i.e.&nbsp;if a <code>BP_PlayerCharacter</code> owns a <code>BP_Hat</code>, it should be stored as the variable type as without any name modifications.</p>
<p>Example: Use <code>Hat</code>, <code>Flag</code>, and <code>Ability</code> <strong>not</strong> <code>MyHat</code>, <code>MyFlag</code>, and <code>PlayerAbility</code>.</p>
<p>If a class does not own the value a complex variable represents, you should use a noun along with the variable type.</p>
<p>Example: If a <code>BP_Turret</code> has the ability to target a <code>BP_PlayerCharacter</code>, it should store its target as <code>TargetPlayer</code> as when in the context of <code>BP_Turret</code> it should be clear that it is a reference to another complex variable type that it does not own.</p>
<p><a name="3.2.1.8"></a></p>
<p><a name="bp-vars-naming-arrays"></a></p>
</section>
<section id="arrays" class="level5">
<h5 class="anchored" data-anchor-id="arrays">3.2.1.8 Arrays</h5>
<p>Arrays follow the same naming rules as above, but should be named as a plural noun.</p>
<p>Example: Use <code>Targets</code>, <code>Hats</code>, and <code>EnemyPlayers</code>, <strong>not</strong> <code>TargetList</code>, <code>HatArray</code>, <code>EnemyPlayerArray</code>.</p>
<p><a name="3.2.2"></a></p>
<p><a name="bp-vars-editable"></a></p>
</section>
</section>
<section id="editable-variables" class="level4">
<h4 class="anchored" data-anchor-id="editable-variables">3.2.2 Editable Variables</h4>
<p>All variables that are safe to change the value of in order to configure behavior of a blueprint should be marked as <code>Editable</code>.</p>
<p>Conversely, all variables that are not safe to change or should not be exposed to designers should <em>not</em> be marked as editable, unless for engineering reasons the variable must be marked as <code>Expose On Spawn</code>.</p>
<p>Do not arbitrarily mark variables as <code>Editable</code>.</p>
<p><a name="3.2.2.1"></a></p>
<p><a name="bp-vars-editable-tooltips"></a></p>
<section id="tooltips" class="level5">
<h5 class="anchored" data-anchor-id="tooltips">3.2.2.1 Tooltips</h5>
<p>All <code>Editable</code> variables, including those marked editable just so they can be marked as <code>Expose On Spawn</code>, should have a description in their <code>Tooltip</code> fields that explains how changing this value affects the behavior of the blueprint.</p>
<p><a name="3.2.2.2"></a></p>
<p><a name="bp-vars-editable-ranges"></a></p>
</section>
<section id="slider-and-value-ranges" class="level5">
<h5 class="anchored" data-anchor-id="slider-and-value-ranges">3.2.2.2 Slider And Value Ranges</h5>
<p>All <code>Editable</code> variables should make use of slider and value ranges if there is ever a value that a variable should <em>not</em> be set to.</p>
<p>Example: A blueprint that generates fence posts might have an editable variable named <code>PostsCount</code> and a value of -1 would not make any sense. Use the range fields to mark 0 as a minimum.</p>
<p>If an editable variable is used in a Construction Script, it should have a reasonable Slider Range defined so that someone can not accidentally assign it a large value that could crash the editor.</p>
<p>A Value Range only needs to be defined if the bounds of a value are known. While a Slider Range prevents accidental large number inputs, an undefined Value Range allows a user to specify a value outside the Slider Range that may be considered dangerous but still valid.</p>
<p><a name="3.2.3"></a></p>
<p><a name="bp-vars-categories"></a></p>
</section>
</section>
<section id="categories" class="level4">
<h4 class="anchored" data-anchor-id="categories">3.2.3 Categories</h4>
<p>If a class has only a small number of variables, categories are not required.</p>
<p>If a class has a moderate amount of variables (5-10), all <code>Editable</code> variables should have a non-default category assigned. A common category is <code>Config</code>.</p>
<p>If a class has a large amount of variables, all <code>Editable</code> variables should be categorized into sub-categories using the category <code>Config</code> as the base category. Non-editable variables should be categorized into descriptive categories describing their usage.</p>
<blockquote class="blockquote">
<p>You can define sub-categories by using the pipe character <code>|</code>, i.e.&nbsp;<code>Config | Animations</code>.</p>
</blockquote>
<p>Example: A weapon class set of variables might be organized as:</p>
<pre><code>|-- Config
| |-- Animations
| |-- Effects
| |-- Audio
| |-- Recoil
| |-- Timings
|-- Animations
|-- State
|-- Visuals</code></pre>
<p><a name="3.2.4"></a></p>
<p><a name="bp-vars-access"></a></p>
</section>
<section id="variable-access-level" class="level4">
<h4 class="anchored" data-anchor-id="variable-access-level">3.2.4 Variable Access Level</h4>
<p>In C++, variables have a concept of access level. Public means any code outside the class can access the variable. Protected means only the class and any child classes can access this variable internally. Private means only this class and no child classes can access this variable.</p>
<p>Blueprints do not have a defined concept of protected access currently.</p>
<p>Treat <code>Editable</code> variables as public variables. Treat non-editable variables as protected variables.</p>
<p><a name="3.2.4.1"></a></p>
<p><a name="bp-vars-access-private"></a></p>
<section id="private-variables" class="level5">
<h5 class="anchored" data-anchor-id="private-variables">3.2.4.1 Private Variables</h5>
<p>Unless it is known that a variable should only be accessed within the class it is defined and never a child class, do not mark variables as private. Until variables are able to be marked <code>protected</code>, reserve private for when you absolutely know you want to restrict child class usage.</p>
<p><a name="3.2.5"></a></p>
<p><a name="bp-vars-advanced"></a></p>
</section>
</section>
<section id="advanced-display" class="level4">
<h4 class="anchored" data-anchor-id="advanced-display">3.2.5 Advanced Display</h4>
<p>If a variable should be editable but often untouched, mark it as <code>Advanced Display</code>. This makes the variable hidden unless the advanced display arrow is clicked.</p>
<p>To find the <code>Advanced Display</code> option, it is listed as an advanced displayed variable in the variable details list.</p>
<p><a name="3.2.6"></a></p>
<p><a name="bp-vars-transient"></a></p>
</section>
<section id="transient-variables" class="level4">
<h4 class="anchored" data-anchor-id="transient-variables">3.2.6 Transient Variables</h4>
<p>Transient variables are variables that do not need to have their value saved and loaded and have an initial value of zero or null. This is useful for references to other objects and actors whos value isnt known until run-time. This prevents the editor from ever saving a reference to it, and speeds up saving and loading of the blueprint class.</p>
<p>Because of this, all transient variables should always be initialized as zero or null. To do otherwise would result in hard to debug errors.</p>
<p><a name="3.2.7"></a></p>
<p><a name="bp-vars-config"></a></p>
</section>
<section id="config-variables" class="level4">
<h4 class="anchored" data-anchor-id="config-variables">3.2.8 Config Variables</h4>
<p>Do not use the <code>Config Variable</code> flag. This makes it harder for designers to control blueprint behavior. Config variables should only be used in C++ for rarely changed variables. Think of them as <code>Advanced Advanced Display</code> variables.</p>
<p><a name="3.3"></a></p>
<p><a name="bp-functions"></a></p>
</section>
</section>
<section id="functions-events-and-event-dispatchers" class="level3">
<h3 class="anchored" data-anchor-id="functions-events-and-event-dispatchers">3.3 Functions, Events, and Event Dispatchers</h3>
<p>This section describes how you should author functions, events, and event dispatchers. Everything that applies to functions also applies to events, unless otherwise noted.</p>
<p><a name="3.3.1"></a></p>
<p><a name="bp-funcs-naming"></a></p>
<section id="function-naming" class="level4">
<h4 class="anchored" data-anchor-id="function-naming">3.3.1 Function Naming</h4>
<p>The naming of functions, events, and event dispatchers is critically important. Based on the name alone, certain assumptions can be made about functions. For example:</p>
<ul>
<li>Is it a pure function?</li>
<li>Is it fetching state information?</li>
<li>Is it a handler?</li>
<li>Is it an RPC?</li>
<li>What is its purpose?</li>
</ul>
<p>These questions and more can all be answered when functions are named appropriately.</p>
<p><a name="3.3.1.1"></a></p>
<p><a name="bp-funcs-naming-verbs"></a></p>
</section>
<section id="all-functions-should-be-verbs" class="level4">
<h4 class="anchored" data-anchor-id="all-functions-should-be-verbs">3.3.1.1 All Functions Should Be Verbs</h4>
<p>All functions and events perform some form of action, whether its getting info, calculating data, or causing something to explode. Therefore, all functions should all start with verbs. They should be worded in the present tense whenever possible. They should also have some context as to what they are doing.</p>
<p><code>OnRep</code> functions, event handlers, and event dispatchers are an exception to this rule.</p>
<p>Good examples:</p>
<ul>
<li><code>Fire</code> - Good example if in a Character / Weapon class, as it has context. Bad if in a Barrel / Grass / any ambiguous class.</li>
<li><code>Jump</code> - Good example if in a Character class, otherwise, needs context.</li>
<li><code>Explode</code></li>
<li><code>ReceiveMessage</code></li>
<li><code>SortPlayerArray</code></li>
<li><code>GetArmOffset</code></li>
<li><code>GetCoordinates</code></li>
<li><code>UpdateTransforms</code></li>
<li><code>EnableBigHeadMode</code></li>
<li><code>IsEnemy</code> - <a href="http://writingexplained.org/is-is-a-verb">“Is” is a verb.</a></li>
</ul>
<p>Bad examples:</p>
<ul>
<li><code>Dead</code> - Is Dead? Will deaden?</li>
<li><code>Rock</code></li>
<li><code>ProcessData</code> - Ambiguous, these words mean nothing.</li>
<li><code>PlayerState</code> - Nouns are ambiguous.</li>
<li><code>Color</code> - Verb with no context, or ambiguous noun.</li>
</ul>
<p><a name="3.3.1.2"></a></p>
<p><a name="bp-funcs-naming-onrep"></a></p>
</section>
<section id="property-repnotify-functions-always-onrep_variable" class="level4">
<h4 class="anchored" data-anchor-id="property-repnotify-functions-always-onrep_variable">3.3.1.2 Property RepNotify Functions Always <code>OnRep_Variable</code></h4>
<p>All functions for replicated with notification variables should have the form <code>OnRep_Variable</code>. This is forced by the Blueprint editor. If you are writing a C++ <code>OnRep</code> function however, it should also follow this convention when exposing it to Blueprints.</p>
<p><a name="3.3.1.3"></a></p>
<p><a name="bp-funcs-naming-bool"></a></p>
</section>
<section id="info-functions-returning-bool-should-ask-questions" class="level4">
<h4 class="anchored" data-anchor-id="info-functions-returning-bool-should-ask-questions">3.3.1.3 Info Functions Returning Bool Should Ask Questions</h4>
<p>When writing a function that does not change the state of or modify any object and is purely for getting information, state, or computing a yes/no value, it should ask a question. This should also follow <a href="#bp-funcs-naming-verbs">the verb rule</a>.</p>
<p>This is extremely important as if a question is not asked, it may be assumed that the function performs an action and is returning whether that action succeeded.</p>
<p>Good examples:</p>
<ul>
<li><code>IsDead</code></li>
<li><code>IsOnFire</code></li>
<li><code>IsAlive</code></li>
<li><code>IsSpeaking</code></li>
<li><code>IsHavingAnExistentialCrisis</code></li>
<li><code>IsVisible</code></li>
<li><code>HasWeapon</code> - <a href="http://grammar.yourdictionary.com/parts-of-speech/verbs/Helping-Verbs.html">“Has” is a verb.</a></li>
<li><code>WasCharging</code> - <a href="http://grammar.yourdictionary.com/parts-of-speech/verbs/Helping-Verbs.html">“Was” is past-tense of “be”.</a> Use “was” when referring to previous frame or previous state.</li>
<li><code>CanReload</code> - <a href="http://grammar.yourdictionary.com/parts-of-speech/verbs/Helping-Verbs.html">“Can” is a verb.</a></li>
</ul>
<p>Bad examples:</p>
<ul>
<li><code>Fire</code> - Is on fire? Will fire? Do fire?</li>
<li><code>OnFire</code> - Can be confused with event dispatcher for firing.</li>
<li><code>Dead</code> - Is dead? Will deaden?</li>
<li><code>Visibility</code> - Is visible? Set visibility? A description of flying conditions?</li>
</ul>
<p><a name="3.3.1.4"></a></p>
<p><a name="bp-funcs-naming-eventhandlers"></a></p>
</section>
<section id="event-handlers-and-dispatchers-should-start-with-on" class="level4">
<h4 class="anchored" data-anchor-id="event-handlers-and-dispatchers-should-start-with-on">3.3.1.4 Event Handlers and Dispatchers Should Start With <code>On</code></h4>
<p>Any function that handles an event or dispatches an event should start with <code>On</code> and continue to follow <a href="#bp-funcs-naming-verbs">the verb rule</a>. The verb may move to the end however if past-tense reads better.</p>
<p><a href="http://dictionary.cambridge.org/us/grammar/british-grammar/about-words-clauses-and-sentences/collocation">Collocations</a> of the word <code>On</code> are exempt from following the verb rule.</p>
<p><code>Handle</code> is not allowed. It is Unreal to use <code>On</code> instead of <code>Handle</code>, while other frameworks may prefer to use <code>Handle</code> instead of <code>On</code>.</p>
<p>Good examples:</p>
<ul>
<li><code>OnDeath</code> - Common collocation in games</li>
<li><code>OnPickup</code></li>
<li><code>OnReceiveMessage</code></li>
<li><code>OnMessageRecieved</code></li>
<li><code>OnTargetChanged</code></li>
<li><code>OnClick</code></li>
<li><code>OnLeave</code></li>
</ul>
<p>Bad examples:</p>
<ul>
<li><code>OnData</code></li>
<li><code>OnTarget</code></li>
<li><code>HandleMessage</code></li>
<li><code>HandleDeath</code></li>
</ul>
<p><a name="3.3.1.5"></a></p>
<p><a name="bp-funcs-naming-rpcs"></a></p>
</section>
<section id="remote-procedure-calls-should-be-prefixed-with-target" class="level4">
<h4 class="anchored" data-anchor-id="remote-procedure-calls-should-be-prefixed-with-target">3.3.1.5 Remote Procedure Calls Should Be Prefixed With Target</h4>
<p>Any time an RPC is created, it should be prefixed with either <code>Server</code>, <code>Client</code>, or <code>Multicast</code>. No exceptions.</p>
<p>After the prefix, follow all other rules regarding function naming.</p>
<p>Good examples:</p>
<ul>
<li><code>ServerFireWeapon</code></li>
<li><code>ClientNotifyDeath</code></li>
<li><code>MulticastSpawnTracerEffect</code></li>
</ul>
<p>Bad examples:</p>
<ul>
<li><code>FireWeapon</code> - Does not indicate its an RPC of some kind.</li>
<li><code>ServerClientBroadcast</code> - Confusing.</li>
<li><code>AllNotifyDeath</code> - Use <code>Multicast</code>, never <code>All</code>.</li>
<li><code>ClientWeapon</code> - No verb, ambiguous.</li>
</ul>
<p><a name="3.3.2"></a></p>
<p><a name="bp-funcs-return"></a></p>
</section>
<section id="all-functions-must-have-return-nodes" class="level4">
<h4 class="anchored" data-anchor-id="all-functions-must-have-return-nodes">3.3.2 All Functions Must Have Return Nodes</h4>
<p>All functions must have return nodes, no exceptions.</p>
<p>Return nodes explicitly note that a function has finished its execution. In a world where blueprints can be filled with <code>Sequence</code>, <code>ForLoopWithBreak</code>, and backwards reroute nodes, explicit execution flow is important for readability, maintenance, and easier debugging.</p>
<p>The Blueprint compiler is able to follow the flow of execution and will warn you if there is a branch of your code with an unhandled return or bad flow if you use return nodes.</p>
<p>In situations like where a programmer may add a pin to a Sequence node or add logic after a for loop completes but the loop iteration might return early, this can often result in an accidental error in code flow. The warnings the Blueprint compiler will alert everyone of these issues immediately.</p>
<p><a name="3.3.3"></a></p>
<p><a name="bp-graphs-funcs-node-limit"></a></p>
</section>
<section id="no-function-should-have-more-than-50-nodes" class="level4">
<h4 class="anchored" data-anchor-id="no-function-should-have-more-than-50-nodes">3.3.3 No Function Should Have More Than 50 Nodes</h4>
<p>Simply, no function should have more than 50 nodes. Any function this big should be broken down into smaller functions for readability and ease of maintenance.</p>
<p>The following nodes are not counted as they are deemed to not increase function complexity:</p>
<ul>
<li>Comment</li>
<li>Route</li>
<li>Cast</li>
<li>Getting a Variable</li>
<li>Breaking a Struct</li>
<li>Function Entry</li>
<li>Self</li>
</ul>
<p><a name="3.3.4"></a></p>
<p><a name="bp-graphs-funcs-description"></a></p>
</section>
<section id="all-public-functions-should-have-a-description" class="level4">
<h4 class="anchored" data-anchor-id="all-public-functions-should-have-a-description">3.3.4 All Public Functions Should Have A Description</h4>
<p>This rule applies more to public facing or marketplace blueprints, so that others can more easily navigate and consume your blueprint API.</p>
<p>Simply, any function that has an access specificer of Public should have its description filled out.</p>
<p><a name="3.3.5"></a></p>
<p><a name="bp-graphs-funcs-plugin-category"></a></p>
</section>
<section id="all-custom-static-plugin-blueprintcallable-functions-must-be-categorized-by-plugin-name" class="level4">
<h4 class="anchored" data-anchor-id="all-custom-static-plugin-blueprintcallable-functions-must-be-categorized-by-plugin-name">3.3.5 All Custom Static Plugin <code>BlueprintCallable</code> Functions Must Be Categorized By Plugin Name</h4>
<p>If your project includes a plugin that defines <code>static</code> <code>BlueprintCallable</code> functions, they should have their category set to the plugins name or a subset category of the plugins name.</p>
<p>For example, <code>Zed Camera Interface</code> or <code>Zed Camera Interface | Image Capturing</code>.</p>
<p><a name="3.4"></a></p>
<p><a name="bp-graphs"></a></p>
</section>
</section>
<section id="blueprint-graphs" class="level3">
<h3 class="anchored" data-anchor-id="blueprint-graphs">3.4 Blueprint Graphs</h3>
<p>This section covers things that apply to all Blueprint graphs.</p>
<p><a name="3.4.1"></a></p>
<p><a name="bp-graphs-spaghetti"></a></p>
<section id="no-spaghetti" class="level4">
<h4 class="anchored" data-anchor-id="no-spaghetti">3.4.1 No Spaghetti</h4>
<p>Wires should have clear beginnings and ends. You should never have to mentally untangle wires to make sense of a graph. Many of the following sections are dedicated to reducing spaghetti.</p>
<p><a name="3.4.2"></a></p>
<p><a name="bp-graphs-align-wires"></a></p>
</section>
<section id="align-wires-not-nodes" class="level4">
<h4 class="anchored" data-anchor-id="align-wires-not-nodes">3.4.2 Align Wires Not Nodes</h4>
<p>Always align wires, not nodes. You cant always control the size and pin location on a node, but you can always control the location of a node and thus control the wires. Straight wires provide clear linear flow. Wiggly wires wear wits wickedly. You can straighten wires by using the Straighten Connections command with BP nodes selected. Hotkey: Q</p>
<p>Good example: The tops of the nodes are staggered to keep a perfectly straight white exec line. <img src="https://github.com/allar/ue4-style-guide/raw/master/images/bp-graphs-align-wires-good.png" title="Aligned By Wires" class="img-fluid" alt="Aligned By Wires"></p>
<p>Bad Example: The tops of the nodes are aligned creating a wiggly white exec line. <img src="https://github.com/allar/ue4-style-guide/raw/master/images/bp-graphs-align-wires-bad.png" title="Wiggly" class="img-fluid" alt="Bad"></p>
<p>Acceptable Example: Certain nodes might not cooperate no matter how you use the alignment tools. In this situation, try to minimize the wiggle by bringing the node in closer. <img src="https://github.com/allar/ue4-style-guide/raw/master/images/bp-graphs-align-wires-acceptable.png" title="Acceptable" class="img-fluid" alt="Acceptable"></p>
<p><a name="3.4.3"></a></p>
<p><a name="bp-graphs-exec-first-class"></a></p>
</section>
<section id="white-exec-lines-are-top-priority" class="level4">
<h4 class="anchored" data-anchor-id="white-exec-lines-are-top-priority">3.4.3 White Exec Lines Are Top Priority</h4>
<p>If you ever have to decide between straightening a linear white exec line or straightening data lines of some kind, always straighten the white exec line.</p>
<p><a name="3.4.4"></a></p>
<p><a name="bp-graphs-block-comments"></a></p>
</section>
<section id="graphs-should-be-reasonably-commented" class="level4">
<h4 class="anchored" data-anchor-id="graphs-should-be-reasonably-commented">3.4.4 Graphs Should Be Reasonably Commented</h4>
<p>Blocks of nodes should be wrapped in comments that describe their higher-level behavior. While every function should be well named so that each individual node is easily readable and understandable, groups of nodes contributing to a purpose should have their purpose described in a comment block. If a function does not have many blocks of nodes and its clear that the nodes are serving a direct purpose in the functions goal, then they do not need to be commented as the function name and description should suffice.</p>
<p><a name="3.4.5"></a></p>
<p><a name="bp-graphs-cast-error-handling"></a></p>
</section>
<section id="graphs-should-handle-casting-errors-where-appropriate" class="level4">
<h4 class="anchored" data-anchor-id="graphs-should-handle-casting-errors-where-appropriate">3.4.5 Graphs Should Handle Casting Errors Where Appropriate</h4>
<p>If a function or event assumes that a cast always succeeds, it should appropriately report a failure in logic if the cast fails. This lets others know why something that is supposed to work doesnt. A function should also attempt a graceful recover after a failed cast if its known that the reference being casted could ever fail to be casted.</p>
<p>This does not mean every cast node should have its failure handled. In many cases, especially events regarding things like collisions, it is expected that execution flow terminates on a failed cast quietly.</p>
<p><a name="3.4.6"></a></p>
<p><a name="bp-graphs-dangling-nodes"></a></p>
</section>
<section id="graphs-should-not-have-any-dangling-loose-dead-nodes" class="level4">
<h4 class="anchored" data-anchor-id="graphs-should-not-have-any-dangling-loose-dead-nodes">3.4.6 Graphs Should Not Have Any Dangling / Loose / Dead Nodes</h4>
<p>All nodes in all blueprint graphs must have a purpose. You should not leave dangling blueprint nodes around that have no purpose or are not executed.</p>
<p><strong><a href="#table-of-contents">⬆ Back to Top</a></strong></p>
<p><a name="4"></a></p>
<p><a name="Static Meshes"></a></p>
<p><a name="s"></a></p>
</section>
</section>
</section>
<section id="static-meshes" class="level2">
<h2 class="anchored" data-anchor-id="static-meshes">4. Static Meshes</h2>
<p>This section will focus on Static Mesh assets and their internals.</p>
<section id="sections-4" class="level3">
<h3 class="anchored" data-anchor-id="sections-4">Sections</h3>
<blockquote class="blockquote">
<p>4.1 <a href="#s-uvs">UVs</a></p>
</blockquote>
<blockquote class="blockquote">
<p>4.2 <a href="#s-lods">LODs</a></p>
</blockquote>
<blockquote class="blockquote">
<p>4.3 <a href="#s-modular-snapping">Modular Socketless Snapping</a></p>
</blockquote>
<blockquote class="blockquote">
<p>4.4 <a href="#s-collision">Must Have Collision</a></p>
</blockquote>
<blockquote class="blockquote">
<p>4.5 <a href="#s-scaled">Correct Scale</a></p>
</blockquote>
<p><a name="4.1"></a></p>
<p><a name="s-uvs"></a></p>
</section>
<section id="static-mesh-uvs" class="level3">
<h3 class="anchored" data-anchor-id="static-mesh-uvs">4.1 Static Mesh UVs</h3>
<p>If Linter is reporting bad UVs and you cant seem to track it down, open the resulting <code>.log</code> file in your projects <code>Saved/Logs</code> folder for exact details as to why its failing. I am hoping to include these messages in the Lint report in the future.</p>
<p><a name="4.1.1"></a></p>
<p><a name="s-uvs-no-missing"></a></p>
<section id="all-meshes-must-have-uvs" class="level4">
<h4 class="anchored" data-anchor-id="all-meshes-must-have-uvs">4.1.1 All Meshes Must Have UVs</h4>
<p>Pretty simple. All meshes, regardless how they are to be used, should not be missing UVs.</p>
<p><a name="4.1.2"></a></p>
<p><a name="s-uvs-no-overlapping"></a></p>
</section>
<section id="all-meshes-must-not-have-overlapping-uvs-for-lightmaps" class="level4">
<h4 class="anchored" data-anchor-id="all-meshes-must-not-have-overlapping-uvs-for-lightmaps">4.1.2 All Meshes Must Not Have Overlapping UVs for Lightmaps</h4>
<p>Pretty simple. All meshes, regardless how they are to be used, should have valid non-overlapping UVs.</p>
<p><a name="4.2"></a></p>
<p><a name="s-lods"></a></p>
</section>
</section>
<section id="lods-should-be-set-up-correctly" class="level3">
<h3 class="anchored" data-anchor-id="lods-should-be-set-up-correctly">4.2 LODs Should Be Set Up Correctly</h3>
<p>This is a subjective check on a per-project basis, but as a general rule any mesh that can be seen at varying distances should have proper LODs.</p>
<p><a name="4.3"></a></p>
<p><a name="s-modular-snapping"></a></p>
</section>
<section id="modular-socketless-assets-should-snap-to-the-grid-cleanly" class="level3">
<h3 class="anchored" data-anchor-id="modular-socketless-assets-should-snap-to-the-grid-cleanly">4.3 Modular Socketless Assets Should Snap To The Grid Cleanly</h3>
<p>This is a subjective check on a per-asset basis, however any modular socketless assets should snap together cleanly based on the projects grid settings.</p>
<p>It is up to the project whether to snap based on a power of 2 grid or on a base 10 grid. However if you are authoring modular socketless assets for the marketplace, Epics requirement is that they snap cleanly when the grid is set to 10 units or bigger.</p>
<p><a name="4.4"></a></p>
<p><a name="s-collision"></a></p>
</section>
<section id="all-meshes-must-have-collision" class="level3">
<h3 class="anchored" data-anchor-id="all-meshes-must-have-collision">4.4 All Meshes Must Have Collision</h3>
<p>Regardless of whether an asset is going to be used for collision in a level, all meshes should have proper collision defined. This helps the engine with things such as bounds calculations, occlusion, and lighting. Collision should also be well-formed to the asset.</p>
<p><a name="4.5"></a></p>
<p><a name="s-scaled"></a></p>
</section>
<section id="all-meshes-should-be-scaled-correctly" class="level3">
<h3 class="anchored" data-anchor-id="all-meshes-should-be-scaled-correctly">4.5 All Meshes Should Be Scaled Correctly</h3>
<p>This is a subjective check on a per-project basis, however all assets should be scaled correctly to their project. Level designers or blueprint authors should not have to tweak the scale of meshes to get them to confirm in the editor. Scaling meshes in the engine should be treated as a scale override, not a scale correction.</p>
<p><strong><a href="#table-of-contents">⬆ Back to Top</a></strong></p>
<p><a name="5"></a></p>
<p><a name="Niagara"></a></p>
<p><a name="ng"></a></p>
</section>
</section>
<section id="niagara" class="level2">
<h2 class="anchored" data-anchor-id="niagara">5. Niagara</h2>
<p>This section will focus on Niagara assets and their internals.</p>
<section id="sections-5" class="level3">
<h3 class="anchored" data-anchor-id="sections-5">Sections</h3>
<blockquote class="blockquote">
<p>5.1 <a href="#ng-rules">Naming Rules</a></p>
</blockquote>
<p><a name="5.1"></a></p>
<p><a name="ng-rules"></a></p>
</section>
<section id="no-spaces-ever" class="level3">
<h3 class="anchored" data-anchor-id="no-spaces-ever">5.1 No Spaces, Ever</h3>
<p>As mentioned in <a href="#00">00.1 Forbidden Identifiers</a>, spaces and all white space characters are forbidden in identifiers. This is especially true for Niagara systems as it makes working with things significantly harder if not impossible when working with HLSL or other means of scripting within Niagara and trying to reference an identifier.</p>
<p>(Original Contribution by <a href="https://github.com/Allar/ue5-style-guide/issues/58"><span class="citation" data-cites="dunenkoff">@dunenkoff</span></a>)</p>
<p><strong><a href="#table-of-contents">⬆ Back to Top</a></strong></p>
<p><a name="6"></a></p>
<p><a name="Levels"></a></p>
<p><a name="levels"></a></p>
</section>
</section>
<section id="levels-maps" class="level2">
<h2 class="anchored" data-anchor-id="levels-maps">6. Levels / Maps</h2>
<p><a href="#terms-level-map">See Terminology Note</a> regarding “levels” vs “maps”.</p>
<p>This section will focus on Level assets and their internals.</p>
<section id="sections-6" class="level3">
<h3 class="anchored" data-anchor-id="sections-6">Sections</h3>
<blockquote class="blockquote">
<p>6.1 <a href="#levels-no-errors-or-warnings">No Errors Or Warnings</a></p>
</blockquote>
<blockquote class="blockquote">
<p>6.2 <a href="#levels-lighting-should-be-built">Lighting Should Be Built</a></p>
</blockquote>
<blockquote class="blockquote">
<p>6.3 <a href="#evels-no-visible-z-fighting">No Player Visible Z Fighting</a></p>
</blockquote>
<blockquote class="blockquote">
<p>6.4 <a href="#evels-levels-mp-rules">Marketplace Specific Rules</a></p>
</blockquote>
<p><a name="6.1"></a></p>
<p><a name="levels-no-errors-or-warnings"></a></p>
</section>
<section id="no-errors-or-warnings" class="level3">
<h3 class="anchored" data-anchor-id="no-errors-or-warnings">6.1 No Errors Or Warnings</h3>
<p>All levels should load with zero errors or warnings. If a level loads with any errors or warnings, they should be fixed immediately to prevent cascading issues.</p>
<p>You can run a map check on an open level in the editor by using the console command “map check”.</p>
<p>Please note: Linter is even more strict on this than the editor is currently, and will catch load errors that the editor will resolve on its own.</p>
<p><a name="6.2"></a></p>
<p><a name="levels-lighting-should-be-built"></a></p>
</section>
<section id="lighting-should-be-built" class="level3">
<h3 class="anchored" data-anchor-id="lighting-should-be-built">6.2 Lighting Should Be Built</h3>
<p>It is normal during development for levels to occasionally not have lighting built. When doing a test/internal/shipping build or any build that is to be distributed however, lighting should always be built.</p>
<p><a name="6.3"></a></p>
<p><a name="levels-no-visible-z-fighting"></a></p>
</section>
<section id="no-player-visible-z-fighting" class="level3">
<h3 class="anchored" data-anchor-id="no-player-visible-z-fighting">6.3 No Player Visible Z Fighting</h3>
<p>Levels should not have any <a href="https://en.wikipedia.org/wiki/Z-fighting">z-fighting</a> in all areas visible to the player.</p>
<p><a name="6.4"></a></p>
<p><a name="levels-mp-rules"></a></p>
</section>
<section id="marketplace-specific-rules" class="level3">
<h3 class="anchored" data-anchor-id="marketplace-specific-rules">6.4 Marketplace Specific Rules</h3>
<p>If a project is to be sold on the UE4 Marketplace, it must follow these rules.</p>
<p><a name="6.4.1"></a></p>
<p><a name="levels-mp-rules-overview"></a></p>
</section>
<section id="overview-level" class="level3">
<h3 class="anchored" data-anchor-id="overview-level">6.4.1 Overview Level</h3>
<p>If your project contains assets that should be visualized or demoed, you must have a map within your project that contains the name “Overview”.</p>
<p>This overview map, if it is visualizing assets, should be set up according to <a href="http://help.epicgames.com/customer/en/portal/articles/2592186-marketplace-submission-guidelines-preparing-your-assets#Required%20Levels%20and%20Maps">Epics guidelines</a>.</p>
<p>For example, <code>InteractionComponent_Overview</code>.</p>
<p><a name="6.4.2"></a></p>
<p><a name="levels-mp-rules-demo"></a></p>
</section>
<section id="demo-level" class="level3">
<h3 class="anchored" data-anchor-id="demo-level">6.4.2 Demo Level</h3>
<p>If your project contains assets that should be demoed or come with some sort of tutorial, you must have a map within your project that contains the name “Demo”. This level should also contain documentation within it in some form that illustrates how to use your project. See Epics Content Examples project for good examples on how to do this.</p>
<p>If your project is a gameplay mechanic or other form of system as opposed to an art pack, this can be the same as your “Overview” map.</p>
<p>For example, <code>InteractionComponent_Overview_Demo</code>, <code>ExplosionKit_Demo</code>.</p>
<p><strong><a href="#table-of-contents">⬆ Back to Top</a></strong></p>
<p><a name="7"></a></p>
<p><a name="textures"></a></p>
</section>
</section>
<section id="textures-1" class="level2">
<h2 class="anchored" data-anchor-id="textures-1">7. Textures</h2>
<p>This section will focus on Texture assets and their internals.</p>
<section id="sections-7" class="level3">
<h3 class="anchored" data-anchor-id="sections-7">Sections</h3>
<blockquote class="blockquote">
<p>7.1 <a href="#textures-dimension">Dimensions Are Powers of 2</a></p>
</blockquote>
<blockquote class="blockquote">
<p>7.2 <a href="#textures-dimension">Texture Density Should Be Uniform</a></p>
</blockquote>
<blockquote class="blockquote">
<p>7.3 <a href="#textures-max-size">Textures Should Be No Bigger than 8192</a></p>
</blockquote>
<blockquote class="blockquote">
<p>7.4 <a href="#textures-textures-group">Correct Texture Groups</a></p>
</blockquote>
<p><a name="7.1"></a></p>
<p><a name="textures-dimensions"></a></p>
</section>
<section id="dimensions-are-powers-of-2" class="level3">
<h3 class="anchored" data-anchor-id="dimensions-are-powers-of-2">7.1 Dimensions Are Powers of 2</h3>
<p>All textures, except for UI textures, must have its dimensions in multiples of powers of 2. Textures do not have to be square.</p>
<p>For example, <code>128x512</code>, <code>1024x1024</code>, <code>2048x1024</code>, <code>1024x2048</code>, <code>1x512</code>.</p>
<p><a name="7.2"></a></p>
<p><a name="textures-density"></a></p>
</section>
<section id="texture-density-should-be-uniform" class="level3">
<h3 class="anchored" data-anchor-id="texture-density-should-be-uniform">7.2 Texture Density Should Be Uniform</h3>
<p>All textures should be of a size appropriate for their standard use case. Appropriate texture density varies from project to project, but all textures within that project should have a consistent density.</p>
<p>For example, if a projects texture density is 8 pixel per 1 unit, a texture that is meant to be applied to a 100x100 unit cube should be 1024x1024, as that is the closest power of 2 that matches the projects texture density.</p>
<p><a name="7.3"></a></p>
<p><a name="textures-max-size"></a></p>
</section>
<section id="textures-should-be-no-bigger-than-8192" class="level3">
<h3 class="anchored" data-anchor-id="textures-should-be-no-bigger-than-8192">7.3 Textures Should Be No Bigger than 8192</h3>
<p>No texture should have a dimension that exceeds 8192 in size, unless you have a very explicit reason to do so. Often, using a texture this big is simply just a waste of resources.</p>
<p><a name="7.4"></a></p>
<p><a name="textures-group"></a></p>
</section>
<section id="textures-should-be-grouped-correctly" class="level3">
<h3 class="anchored" data-anchor-id="textures-should-be-grouped-correctly">7.4 Textures Should Be Grouped Correctly</h3>
<p>Every texture has a Texture Group property used for LODing, and this should be set correctly based on its use. For example, all UI textures should belong in the UI texture group.</p>
<p><strong><a href="#table-of-contents">⬆ Back to Top</a></strong></p>
</section>
</section>
</main> <!-- /main -->
<script id="quarto-html-after-body" type="application/javascript">
window.document.addEventListener("DOMContentLoaded", function (event) {
const toggleBodyColorMode = (bsSheetEl) => {
const mode = bsSheetEl.getAttribute("data-mode");
const bodyEl = window.document.querySelector("body");
if (mode === "dark") {
bodyEl.classList.add("quarto-dark");
bodyEl.classList.remove("quarto-light");
} else {
bodyEl.classList.add("quarto-light");
bodyEl.classList.remove("quarto-dark");
}
}
const toggleBodyColorPrimary = () => {
const bsSheetEl = window.document.querySelector("link#quarto-bootstrap");
if (bsSheetEl) {
toggleBodyColorMode(bsSheetEl);
}
}
toggleBodyColorPrimary();
const icon = "";
const anchorJS = new window.AnchorJS();
anchorJS.options = {
placement: 'right',
icon: icon
};
anchorJS.add('.anchored');
const isCodeAnnotation = (el) => {
for (const clz of el.classList) {
if (clz.startsWith('code-annotation-')) {
return true;
}
}
return false;
}
const onCopySuccess = function(e) {
// button target
const button = e.trigger;
// don't keep focus
button.blur();
// flash "checked"
button.classList.add('code-copy-button-checked');
var currentTitle = button.getAttribute("title");
button.setAttribute("title", "Copied!");
let tooltip;
if (window.bootstrap) {
button.setAttribute("data-bs-toggle", "tooltip");
button.setAttribute("data-bs-placement", "left");
button.setAttribute("data-bs-title", "Copied!");
tooltip = new bootstrap.Tooltip(button,
{ trigger: "manual",
customClass: "code-copy-button-tooltip",
offset: [0, -8]});
tooltip.show();
}
setTimeout(function() {
if (tooltip) {
tooltip.hide();
button.removeAttribute("data-bs-title");
button.removeAttribute("data-bs-toggle");
button.removeAttribute("data-bs-placement");
}
button.setAttribute("title", currentTitle);
button.classList.remove('code-copy-button-checked');
}, 1000);
// clear code selection
e.clearSelection();
}
const getTextToCopy = function(trigger) {
const codeEl = trigger.previousElementSibling.cloneNode(true);
for (const childEl of codeEl.children) {
if (isCodeAnnotation(childEl)) {
childEl.remove();
}
}
return codeEl.innerText;
}
const clipboard = new window.ClipboardJS('.code-copy-button:not([data-in-quarto-modal])', {
text: getTextToCopy
});
clipboard.on('success', onCopySuccess);
if (window.document.getElementById('quarto-embedded-source-code-modal')) {
const clipboardModal = new window.ClipboardJS('.code-copy-button[data-in-quarto-modal]', {
text: getTextToCopy,
container: window.document.getElementById('quarto-embedded-source-code-modal')
});
clipboardModal.on('success', onCopySuccess);
}
var localhostRegex = new RegExp(/^(?:http|https):\/\/localhost\:?[0-9]*\//);
var mailtoRegex = new RegExp(/^mailto:/);
var filterRegex = new RegExp('/' + window.location.host + '/');
var isInternal = (href) => {
return filterRegex.test(href) || localhostRegex.test(href) || mailtoRegex.test(href);
}
// Inspect non-navigation links and adorn them if external
var links = window.document.querySelectorAll('a[href]:not(.nav-link):not(.navbar-brand):not(.toc-action):not(.sidebar-link):not(.sidebar-item-toggle):not(.pagination-link):not(.no-external):not([aria-hidden]):not(.dropdown-item):not(.quarto-navigation-tool):not(.about-link)');
for (var i=0; i<links.length; i++) {
const link = links[i];
if (!isInternal(link.href)) {
// undo the damage that might have been done by quarto-nav.js in the case of
// links that we want to consider external
if (link.dataset.originalHref !== undefined) {
link.href = link.dataset.originalHref;
}
}
}
function tippyHover(el, contentFn, onTriggerFn, onUntriggerFn) {
const config = {
allowHTML: true,
maxWidth: 500,
delay: 100,
arrow: false,
appendTo: function(el) {
return el.parentElement;
},
interactive: true,
interactiveBorder: 10,
theme: 'quarto',
placement: 'bottom-start',
};
if (contentFn) {
config.content = contentFn;
}
if (onTriggerFn) {
config.onTrigger = onTriggerFn;
}
if (onUntriggerFn) {
config.onUntrigger = onUntriggerFn;
}
window.tippy(el, config);
}
const noterefs = window.document.querySelectorAll('a[role="doc-noteref"]');
for (var i=0; i<noterefs.length; i++) {
const ref = noterefs[i];
tippyHover(ref, function() {
// use id or data attribute instead here
let href = ref.getAttribute('data-footnote-href') || ref.getAttribute('href');
try { href = new URL(href).hash; } catch {}
const id = href.replace(/^#\/?/, "");
const note = window.document.getElementById(id);
if (note) {
return note.innerHTML;
} else {
return "";
}
});
}
const xrefs = window.document.querySelectorAll('a.quarto-xref');
const processXRef = (id, note) => {
// Strip column container classes
const stripColumnClz = (el) => {
el.classList.remove("page-full", "page-columns");
if (el.children) {
for (const child of el.children) {
stripColumnClz(child);
}
}
}
stripColumnClz(note)
if (id === null || id.startsWith('sec-')) {
// Special case sections, only their first couple elements
const container = document.createElement("div");
if (note.children && note.children.length > 2) {
container.appendChild(note.children[0].cloneNode(true));
for (let i = 1; i < note.children.length; i++) {
const child = note.children[i];
if (child.tagName === "P" && child.innerText === "") {
continue;
} else {
container.appendChild(child.cloneNode(true));
break;
}
}
if (window.Quarto?.typesetMath) {
window.Quarto.typesetMath(container);
}
return container.innerHTML
} else {
if (window.Quarto?.typesetMath) {
window.Quarto.typesetMath(note);
}
return note.innerHTML;
}
} else {
// Remove any anchor links if they are present
const anchorLink = note.querySelector('a.anchorjs-link');
if (anchorLink) {
anchorLink.remove();
}
if (window.Quarto?.typesetMath) {
window.Quarto.typesetMath(note);
}
if (note.classList.contains("callout")) {
return note.outerHTML;
} else {
return note.innerHTML;
}
}
}
for (var i=0; i<xrefs.length; i++) {
const xref = xrefs[i];
tippyHover(xref, undefined, function(instance) {
instance.disable();
let url = xref.getAttribute('href');
let hash = undefined;
if (url.startsWith('#')) {
hash = url;
} else {
try { hash = new URL(url).hash; } catch {}
}
if (hash) {
const id = hash.replace(/^#\/?/, "");
const note = window.document.getElementById(id);
if (note !== null) {
try {
const html = processXRef(id, note.cloneNode(true));
instance.setContent(html);
} finally {
instance.enable();
instance.show();
}
} else {
// See if we can fetch this
fetch(url.split('#')[0])
.then(res => res.text())
.then(html => {
const parser = new DOMParser();
const htmlDoc = parser.parseFromString(html, "text/html");
const note = htmlDoc.getElementById(id);
if (note !== null) {
const html = processXRef(id, note);
instance.setContent(html);
}
}).finally(() => {
instance.enable();
instance.show();
});
}
} else {
// See if we can fetch a full url (with no hash to target)
// This is a special case and we should probably do some content thinning / targeting
fetch(url)
.then(res => res.text())
.then(html => {
const parser = new DOMParser();
const htmlDoc = parser.parseFromString(html, "text/html");
const note = htmlDoc.querySelector('main.content');
if (note !== null) {
// This should only happen for chapter cross references
// (since there is no id in the URL)
// remove the first header
if (note.children.length > 0 && note.children[0].tagName === "HEADER") {
note.children[0].remove();
}
const html = processXRef(null, note);
instance.setContent(html);
}
}).finally(() => {
instance.enable();
instance.show();
});
}
}, function(instance) {
});
}
let selectedAnnoteEl;
const selectorForAnnotation = ( cell, annotation) => {
let cellAttr = 'data-code-cell="' + cell + '"';
let lineAttr = 'data-code-annotation="' + annotation + '"';
const selector = 'span[' + cellAttr + '][' + lineAttr + ']';
return selector;
}
const selectCodeLines = (annoteEl) => {
const doc = window.document;
const targetCell = annoteEl.getAttribute("data-target-cell");
const targetAnnotation = annoteEl.getAttribute("data-target-annotation");
const annoteSpan = window.document.querySelector(selectorForAnnotation(targetCell, targetAnnotation));
const lines = annoteSpan.getAttribute("data-code-lines").split(",");
const lineIds = lines.map((line) => {
return targetCell + "-" + line;
})
let top = null;
let height = null;
let parent = null;
if (lineIds.length > 0) {
//compute the position of the single el (top and bottom and make a div)
const el = window.document.getElementById(lineIds[0]);
top = el.offsetTop;
height = el.offsetHeight;
parent = el.parentElement.parentElement;
if (lineIds.length > 1) {
const lastEl = window.document.getElementById(lineIds[lineIds.length - 1]);
const bottom = lastEl.offsetTop + lastEl.offsetHeight;
height = bottom - top;
}
if (top !== null && height !== null && parent !== null) {
// cook up a div (if necessary) and position it
let div = window.document.getElementById("code-annotation-line-highlight");
if (div === null) {
div = window.document.createElement("div");
div.setAttribute("id", "code-annotation-line-highlight");
div.style.position = 'absolute';
parent.appendChild(div);
}
div.style.top = top - 2 + "px";
div.style.height = height + 4 + "px";
div.style.left = 0;
let gutterDiv = window.document.getElementById("code-annotation-line-highlight-gutter");
if (gutterDiv === null) {
gutterDiv = window.document.createElement("div");
gutterDiv.setAttribute("id", "code-annotation-line-highlight-gutter");
gutterDiv.style.position = 'absolute';
const codeCell = window.document.getElementById(targetCell);
const gutter = codeCell.querySelector('.code-annotation-gutter');
gutter.appendChild(gutterDiv);
}
gutterDiv.style.top = top - 2 + "px";
gutterDiv.style.height = height + 4 + "px";
}
selectedAnnoteEl = annoteEl;
}
};
const unselectCodeLines = () => {
const elementsIds = ["code-annotation-line-highlight", "code-annotation-line-highlight-gutter"];
elementsIds.forEach((elId) => {
const div = window.document.getElementById(elId);
if (div) {
div.remove();
}
});
selectedAnnoteEl = undefined;
};
// Handle positioning of the toggle
window.addEventListener(
"resize",
throttle(() => {
elRect = undefined;
if (selectedAnnoteEl) {
selectCodeLines(selectedAnnoteEl);
}
}, 10)
);
function throttle(fn, ms) {
let throttle = false;
let timer;
return (...args) => {
if(!throttle) { // first call gets through
fn.apply(this, args);
throttle = true;
} else { // all the others get throttled
if(timer) clearTimeout(timer); // cancel #2
timer = setTimeout(() => {
fn.apply(this, args);
timer = throttle = false;
}, ms);
}
};
}
// Attach click handler to the DT
const annoteDls = window.document.querySelectorAll('dt[data-target-cell]');
for (const annoteDlNode of annoteDls) {
annoteDlNode.addEventListener('click', (event) => {
const clickedEl = event.target;
if (clickedEl !== selectedAnnoteEl) {
unselectCodeLines();
const activeEl = window.document.querySelector('dt[data-target-cell].code-annotation-active');
if (activeEl) {
activeEl.classList.remove('code-annotation-active');
}
selectCodeLines(clickedEl);
clickedEl.classList.add('code-annotation-active');
} else {
// Unselect the line
unselectCodeLines();
clickedEl.classList.remove('code-annotation-active');
}
});
}
const findCites = (el) => {
const parentEl = el.parentElement;
if (parentEl) {
const cites = parentEl.dataset.cites;
if (cites) {
return {
el,
cites: cites.split(' ')
};
} else {
return findCites(el.parentElement)
}
} else {
return undefined;
}
};
var bibliorefs = window.document.querySelectorAll('a[role="doc-biblioref"]');
for (var i=0; i<bibliorefs.length; i++) {
const ref = bibliorefs[i];
const citeInfo = findCites(ref);
if (citeInfo) {
tippyHover(citeInfo.el, function() {
var popup = window.document.createElement('div');
citeInfo.cites.forEach(function(cite) {
var citeDiv = window.document.createElement('div');
citeDiv.classList.add('hanging-indent');
citeDiv.classList.add('csl-entry');
var biblioDiv = window.document.getElementById('ref-' + cite);
if (biblioDiv) {
citeDiv.innerHTML = biblioDiv.innerHTML;
}
popup.appendChild(citeDiv);
});
return popup.innerHTML;
});
}
}
});
</script>
</div> <!-- /content -->
<footer class="footer">
<div class="nav-footer">
<div class="nav-footer-left">
<p>Copyright 2025, Simeon Wallrath</p>
</div>
<div class="nav-footer-center">
&nbsp;
</div>
<div class="nav-footer-right">
<ul class="footer-items list-unstyled">
<li class="nav-item compact">
<a class="nav-link" href="https://github.com/">
<i class="bi bi-github" role="img">
</i>
</a>
</li>
<li class="nav-item compact">
<a class="nav-link" href="https://twitter.com/">
<i class="bi bi-mastodon" role="img">
</i>
</a>
</li>
</ul>
</div>
</div>
</footer>
</body></html>