2397 lines
82 KiB
TeX
2397 lines
82 KiB
TeX
% Options for packages loaded elsewhere
|
|
\PassOptionsToPackage{unicode}{hyperref}
|
|
\PassOptionsToPackage{hyphens}{url}
|
|
\PassOptionsToPackage{dvipsnames,svgnames,x11names}{xcolor}
|
|
%
|
|
\documentclass[
|
|
letterpaper,
|
|
DIV=11,
|
|
numbers=noendperiod,
|
|
oneside]{scrartcl}
|
|
|
|
\usepackage{amsmath,amssymb}
|
|
\usepackage{iftex}
|
|
\ifPDFTeX
|
|
\usepackage[T1]{fontenc}
|
|
\usepackage[utf8]{inputenc}
|
|
\usepackage{textcomp} % provide euro and other symbols
|
|
\else % if luatex or xetex
|
|
\usepackage{unicode-math}
|
|
\defaultfontfeatures{Scale=MatchLowercase}
|
|
\defaultfontfeatures[\rmfamily]{Ligatures=TeX,Scale=1}
|
|
\fi
|
|
\usepackage{lmodern}
|
|
\ifPDFTeX\else
|
|
% xetex/luatex font selection
|
|
\fi
|
|
% Use upquote if available, for straight quotes in verbatim environments
|
|
\IfFileExists{upquote.sty}{\usepackage{upquote}}{}
|
|
\IfFileExists{microtype.sty}{% use microtype if available
|
|
\usepackage[]{microtype}
|
|
\UseMicrotypeSet[protrusion]{basicmath} % disable protrusion for tt fonts
|
|
}{}
|
|
\makeatletter
|
|
\@ifundefined{KOMAClassName}{% if non-KOMA class
|
|
\IfFileExists{parskip.sty}{%
|
|
\usepackage{parskip}
|
|
}{% else
|
|
\setlength{\parindent}{0pt}
|
|
\setlength{\parskip}{6pt plus 2pt minus 1pt}}
|
|
}{% if KOMA class
|
|
\KOMAoptions{parskip=half}}
|
|
\makeatother
|
|
\usepackage{xcolor}
|
|
\usepackage[left=1in,marginparwidth=2.0666666666667in,textwidth=4.1333333333333in,marginparsep=0.3in]{geometry}
|
|
\setlength{\emergencystretch}{3em} % prevent overfull lines
|
|
\setcounter{secnumdepth}{-\maxdimen} % remove section numbering
|
|
% Make \paragraph and \subparagraph free-standing
|
|
\makeatletter
|
|
\ifx\paragraph\undefined\else
|
|
\let\oldparagraph\paragraph
|
|
\renewcommand{\paragraph}{
|
|
\@ifstar
|
|
\xxxParagraphStar
|
|
\xxxParagraphNoStar
|
|
}
|
|
\newcommand{\xxxParagraphStar}[1]{\oldparagraph*{#1}\mbox{}}
|
|
\newcommand{\xxxParagraphNoStar}[1]{\oldparagraph{#1}\mbox{}}
|
|
\fi
|
|
\ifx\subparagraph\undefined\else
|
|
\let\oldsubparagraph\subparagraph
|
|
\renewcommand{\subparagraph}{
|
|
\@ifstar
|
|
\xxxSubParagraphStar
|
|
\xxxSubParagraphNoStar
|
|
}
|
|
\newcommand{\xxxSubParagraphStar}[1]{\oldsubparagraph*{#1}\mbox{}}
|
|
\newcommand{\xxxSubParagraphNoStar}[1]{\oldsubparagraph{#1}\mbox{}}
|
|
\fi
|
|
\makeatother
|
|
|
|
|
|
\providecommand{\tightlist}{%
|
|
\setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}}\usepackage{longtable,booktabs,array}
|
|
\usepackage{calc} % for calculating minipage widths
|
|
% Correct order of tables after \paragraph or \subparagraph
|
|
\usepackage{etoolbox}
|
|
\makeatletter
|
|
\patchcmd\longtable{\par}{\if@noskipsec\mbox{}\fi\par}{}{}
|
|
\makeatother
|
|
% Allow footnotes in longtable head/foot
|
|
\IfFileExists{footnotehyper.sty}{\usepackage{footnotehyper}}{\usepackage{footnote}}
|
|
\makesavenoteenv{longtable}
|
|
\usepackage{graphicx}
|
|
\makeatletter
|
|
\newsavebox\pandoc@box
|
|
\newcommand*\pandocbounded[1]{% scales image to fit in text height/width
|
|
\sbox\pandoc@box{#1}%
|
|
\Gscale@div\@tempa{\textheight}{\dimexpr\ht\pandoc@box+\dp\pandoc@box\relax}%
|
|
\Gscale@div\@tempb{\linewidth}{\wd\pandoc@box}%
|
|
\ifdim\@tempb\p@<\@tempa\p@\let\@tempa\@tempb\fi% select the smaller of both
|
|
\ifdim\@tempa\p@<\p@\scalebox{\@tempa}{\usebox\pandoc@box}%
|
|
\else\usebox{\pandoc@box}%
|
|
\fi%
|
|
}
|
|
% Set default figure placement to htbp
|
|
\def\fps@figure{htbp}
|
|
\makeatother
|
|
|
|
\KOMAoption{captions}{tableheading}
|
|
\makeatletter
|
|
\@ifpackageloaded{caption}{}{\usepackage{caption}}
|
|
\AtBeginDocument{%
|
|
\ifdefined\contentsname
|
|
\renewcommand*\contentsname{Table of contents}
|
|
\else
|
|
\newcommand\contentsname{Table of contents}
|
|
\fi
|
|
\ifdefined\listfigurename
|
|
\renewcommand*\listfigurename{List of Figures}
|
|
\else
|
|
\newcommand\listfigurename{List of Figures}
|
|
\fi
|
|
\ifdefined\listtablename
|
|
\renewcommand*\listtablename{List of Tables}
|
|
\else
|
|
\newcommand\listtablename{List of Tables}
|
|
\fi
|
|
\ifdefined\figurename
|
|
\renewcommand*\figurename{Figure}
|
|
\else
|
|
\newcommand\figurename{Figure}
|
|
\fi
|
|
\ifdefined\tablename
|
|
\renewcommand*\tablename{Table}
|
|
\else
|
|
\newcommand\tablename{Table}
|
|
\fi
|
|
}
|
|
\@ifpackageloaded{float}{}{\usepackage{float}}
|
|
\floatstyle{ruled}
|
|
\@ifundefined{c@chapter}{\newfloat{codelisting}{h}{lop}}{\newfloat{codelisting}{h}{lop}[chapter]}
|
|
\floatname{codelisting}{Listing}
|
|
\newcommand*\listoflistings{\listof{codelisting}{List of Listings}}
|
|
\makeatother
|
|
\makeatletter
|
|
\makeatother
|
|
\makeatletter
|
|
\@ifpackageloaded{caption}{}{\usepackage{caption}}
|
|
\@ifpackageloaded{subcaption}{}{\usepackage{subcaption}}
|
|
\makeatother
|
|
\makeatletter
|
|
\@ifpackageloaded{sidenotes}{}{\usepackage{sidenotes}}
|
|
\@ifpackageloaded{marginnote}{}{\usepackage{marginnote}}
|
|
\makeatother
|
|
|
|
\usepackage{bookmark}
|
|
|
|
\IfFileExists{xurl.sty}{\usepackage{xurl}}{} % add URL line breaks if available
|
|
\urlstyle{same} % disable monospaced font for URLs
|
|
\hypersetup{
|
|
pdftitle={Styleguide},
|
|
colorlinks=true,
|
|
linkcolor={blue},
|
|
filecolor={Maroon},
|
|
citecolor={Blue},
|
|
urlcolor={Blue},
|
|
pdfcreator={LaTeX via pandoc}}
|
|
|
|
|
|
\title{Styleguide}
|
|
\author{}
|
|
\date{}
|
|
|
|
\begin{document}
|
|
\maketitle
|
|
|
|
|
|
This Styleguiade is adapted by Gamemakin UE5 Styleguide.
|
|
|
|
\subsection{Important Terminology}\label{important-terminology}
|
|
|
|
\subparagraph{Levels/Maps}\label{levelsmaps}
|
|
|
|
The word `map' generally refers to what the average person calls a
|
|
`level' and may be used interchangeably. See this term's history
|
|
\href{https://en.wikipedia.org/wiki/Level_(video_gaming)}{here}.
|
|
|
|
\subparagraph{Identifiers}\label{identifiers}
|
|
|
|
An \texttt{Identifier} 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\ldots{}
|
|
|
|
\subparagraph{Cases}\label{cases}
|
|
|
|
There are a few different ways you can \texttt{CaseWordsWhenNaming}.
|
|
Here are some common casing types:
|
|
|
|
\begin{quote}
|
|
PascalCase
|
|
|
|
Capitalize every word and remove all spaces, e.g.~\texttt{DesertEagle},
|
|
\texttt{StyleGuide}, \texttt{ASeriesOfWords}.
|
|
|
|
camelCase
|
|
|
|
The first letter is always lowercase but every following word starts
|
|
with uppercase, e.g.~\texttt{desertEagle}, \texttt{styleGuide},
|
|
\texttt{aSeriesOfWords}.
|
|
|
|
Snake\_case
|
|
|
|
Words can arbitrarily start upper or lowercase but words are separated
|
|
by an underscore, e.g.~\texttt{desert\_Eagle}, \texttt{Style\_Guide},
|
|
\texttt{a\_Series\_of\_Words}.
|
|
\end{quote}
|
|
|
|
\subparagraph{Variables / Properties}\label{variables-properties}
|
|
|
|
The words `variable' and `property' in most contexts are interchangable.
|
|
If they are both used together in the same context however:
|
|
|
|
Property
|
|
|
|
Usually refers to a variable defined in a class. For example, if
|
|
\texttt{BP\_Barrel} had a variable \texttt{bExploded},
|
|
\texttt{bExploded} may be referred to as a property of
|
|
\texttt{BP\_Barrel}.
|
|
|
|
When in the context of a class, it is often used to imply accessing
|
|
previously defined data.
|
|
|
|
Variable
|
|
|
|
Usually refers to a variable defined as a function argument or a local
|
|
variable inside a function.
|
|
|
|
When in the context of a class, it is often used to convey discussion
|
|
about its definition and what it will hold.
|
|
|
|
\subsection{0. Principles}\label{principles}
|
|
|
|
These principles have been adapted from
|
|
\href{https://github.com/rwaldron/idiomatic.js/}{idomatic.js style
|
|
guide}.
|
|
|
|
\subsubsection{0.1 If your UE4 project already has a style guide, you
|
|
should follow
|
|
it.}\label{if-your-ue4-project-already-has-a-style-guide-you-should-follow-it.}
|
|
|
|
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.
|
|
|
|
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.
|
|
|
|
\begin{quote}
|
|
\mbox{}%
|
|
\paragraph{``Arguments over style are pointless. There should be a style
|
|
guide, and you should follow
|
|
it.''}\label{arguments-over-style-are-pointless.-there-should-be-a-style-guide-and-you-should-follow-it.}
|
|
|
|
\href{https://rmurphey.com}{\emph{Rebecca Murphey}}
|
|
\end{quote}
|
|
|
|
\subsubsection{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.}\label{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.}
|
|
|
|
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.
|
|
|
|
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.
|
|
|
|
\subsubsection{0.3 Friends do not let friends have bad
|
|
style.}\label{friends-do-not-let-friends-have-bad-style.}
|
|
|
|
If you see someone working either against a style guide or no style
|
|
guide, try to correct them.
|
|
|
|
When working within a team or discussing within a community such as
|
|
\href{http://join.unrealslackers.org/}{Unreal Slackers}, it is far
|
|
easier to help and to ask for help when people are consistent. Nobody
|
|
likes to help untangle someone's Blueprint spaghetti or deal with assets
|
|
that have names they can't understand.
|
|
|
|
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.
|
|
|
|
\subsubsection{0.4 A team without a style guide is no team of
|
|
mine.}\label{a-team-without-a-style-guide-is-no-team-of-mine.}
|
|
|
|
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.
|
|
|
|
\subsubsection{0.5 Don't Break The Law}\label{dont-break-the-law}
|
|
|
|
Gamemakin LLC is not a lawyer, but please don't introduce illegal
|
|
actions and behavior to a project, including but not limited to:
|
|
|
|
\begin{itemize}
|
|
\tightlist
|
|
\item
|
|
Don't distribute content you don't have the rights to distribute
|
|
\item
|
|
Don't infringe on someone else's copyrighted or trademark material
|
|
\item
|
|
Don't steal content
|
|
\item
|
|
Follow licensing restrictions on content, e.g.~attribute when
|
|
attributions are needed
|
|
\end{itemize}
|
|
|
|
\subsection{00. Globally Enforced
|
|
Opinions}\label{globally-enforced-opinions}
|
|
|
|
@TODO\marginpar{\begin{footnotesize}{?quarto-cite:TODO}\vspace{2mm}\par\end{footnotesize}}:
|
|
Make this section 1 and update this document accordingly. Or maybe we
|
|
don't?
|
|
|
|
\subsubsection{00.1 Forbidden Characters}\label{forbidden-characters}
|
|
|
|
\paragraph{Identifiers}\label{identifiers-1}
|
|
|
|
In any \texttt{Identifier} of any kind, \textbf{never} use the following
|
|
unless absolutely forced to:
|
|
|
|
\begin{itemize}
|
|
\tightlist
|
|
\item
|
|
White space of any kind
|
|
\item
|
|
Backward slashes \texttt{\textbackslash{}}
|
|
\item
|
|
Symbols i.e.~\texttt{\#!@\$\%}
|
|
\item
|
|
Any Unicode character
|
|
\end{itemize}
|
|
|
|
Any \texttt{Identifier} should strive to only have the following
|
|
characters when possible (the \n \texttt{{[}A-Za-z0-9\_{]}+})
|
|
|
|
\begin{itemize}
|
|
\tightlist
|
|
\item
|
|
ABCDEFGHIJKLMNOPQRSTUVWXYZ
|
|
\item
|
|
abcdefghijklmnopqrstuvwxyz
|
|
\item
|
|
1234567890
|
|
\item
|
|
\_ (sparingly)
|
|
\end{itemize}
|
|
|
|
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 don't control.
|
|
|
|
\subsection{Table of Contents}\label{table-of-contents}
|
|
|
|
\begin{quote}
|
|
\begin{enumerate}
|
|
\def\labelenumi{\arabic{enumi}.}
|
|
\tightlist
|
|
\item
|
|
\hyperref[anc]{Asset Naming Conventions}
|
|
\item
|
|
\hyperref[structure]{Directory Structure}
|
|
\item
|
|
\hyperref[bp]{Blueprints}
|
|
\item
|
|
\hyperref[s]{Static Meshes}
|
|
\item
|
|
\hyperref[ps]{Particle Systems}
|
|
\item
|
|
\hyperref[levels]{Levels / Maps}
|
|
\item
|
|
\hyperref[textures]{Textures}
|
|
\end{enumerate}
|
|
\end{quote}
|
|
|
|
\subsection{1. Asset Naming Conventions}\label{asset-naming-conventions}
|
|
|
|
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.
|
|
|
|
Most things are prefixed with prefixes being generally an acronym of the
|
|
asset type followed by an underscore.
|
|
|
|
\subsubsection{\texorpdfstring{1.1 Base Asset Name -
|
|
\texttt{Prefix\_BaseAssetName\_Variant\_Suffix}}{1.1 Base Asset Name - Prefix\_BaseAssetName\_Variant\_Suffix}}\label{base-asset-name---prefix_baseassetname_variant_suffix}
|
|
|
|
All assets should have a \emph{Base Asset Name}. 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
|
|
\texttt{Prefix\_BaseAssetName\_Variant\_Suffix}.
|
|
|
|
Keeping the pattern \texttt{Prefix\_BaseAssetName\_Variant\_Suffix} and
|
|
in mind and using common sense is generally enough to warrant good asset
|
|
names. Here are some detailed rules regarding each element.
|
|
|
|
\texttt{Prefix} and \texttt{Suffix} are to be determined by the asset
|
|
type through the following \hyperref[asset-name-modifiers]{Asset Name
|
|
Modifier} tables.
|
|
|
|
\texttt{BaseAssetName} 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 Bob's assets would
|
|
have the \texttt{BaseAssetName} of \texttt{Bob}.
|
|
|
|
For unique and specific variations of assets, \texttt{Variant} is either
|
|
a short and easily recognizable name that represents logical grouping of
|
|
assets that are a subset of an asset's base name. For example, if Bob
|
|
had multiple skins these skins should still use \texttt{Bob} as the
|
|
\texttt{BaseAssetName} but include a recognizable \texttt{Variant}. An
|
|
`Evil' skin would be referred to as \texttt{Bob\_Evil} and a `Retro'
|
|
skin would be referred to as \texttt{Bob\_Retro}.
|
|
|
|
For unique but generic variations of assets, \texttt{Variant} is a two
|
|
digit number starting at \texttt{01}. For example, if you have an
|
|
environment artist generating nondescript rocks, they would be named
|
|
\texttt{Rock\_01}, \texttt{Rock\_02}, \texttt{Rock\_03}, 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.
|
|
|
|
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 \texttt{Flooring} with
|
|
chained variants such as \texttt{Flooring\_Marble\_01},
|
|
\texttt{Flooring\_Maple\_01}, \texttt{Flooring\_Tile\_Squares\_01}.
|
|
|
|
\paragraph{1.1 Examples}\label{examples}
|
|
|
|
\subparagraph{1.1e1 Bob}\label{e1-bob}
|
|
|
|
\begin{longtable}[]{@{}
|
|
>{\raggedright\arraybackslash}p{(\linewidth - 2\tabcolsep) * \real{0.2840}}
|
|
>{\raggedright\arraybackslash}p{(\linewidth - 2\tabcolsep) * \real{0.7160}}@{}}
|
|
\toprule\noalign{}
|
|
\begin{minipage}[b]{\linewidth}\raggedright
|
|
Asset Type
|
|
\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright
|
|
Asset Name
|
|
\end{minipage} \\
|
|
\midrule\noalign{}
|
|
\endhead
|
|
\bottomrule\noalign{}
|
|
\endlastfoot
|
|
Skeletal Mesh & SK\_Bob \\
|
|
Material & M\_Bob \\
|
|
Texture (Diffuse/Albedo) & T\_Bob\_D \\
|
|
Texture (Normal) & T\_Bob\_N \\
|
|
Texture (Evil Diffuse) & T\_Bob\_Evil\_D \\
|
|
\end{longtable}
|
|
|
|
\subparagraph{1.1e2 Rocks}\label{e2-rocks}
|
|
|
|
\begin{longtable}[]{@{}
|
|
>{\raggedright\arraybackslash}p{(\linewidth - 2\tabcolsep) * \real{0.2840}}
|
|
>{\raggedright\arraybackslash}p{(\linewidth - 2\tabcolsep) * \real{0.7160}}@{}}
|
|
\toprule\noalign{}
|
|
\begin{minipage}[b]{\linewidth}\raggedright
|
|
Asset Type
|
|
\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright
|
|
Asset Name
|
|
\end{minipage} \\
|
|
\midrule\noalign{}
|
|
\endhead
|
|
\bottomrule\noalign{}
|
|
\endlastfoot
|
|
Static Mesh (01) & S\_Rock\_01 \\
|
|
Static Mesh (02) & S\_Rock\_02 \\
|
|
Static Mesh (03) & S\_Rock\_03 \\
|
|
Material & M\_Rock \\
|
|
Material Instance (Snow) & MI\_Rock\_Snow \\
|
|
\end{longtable}
|
|
|
|
\subsubsection{1.2 Asset Name Modifiers}\label{asset-name-modifiers}
|
|
|
|
When naming an asset, use these tables to determine the prefix and
|
|
suffix to use with an asset's \hyperref[base-asset-name]{Base Asset
|
|
Name}.
|
|
|
|
\paragraph{Sections}\label{sections}
|
|
|
|
\begin{quote}
|
|
1.2.1 \hyperref[anc-common]{Most Common}
|
|
\end{quote}
|
|
|
|
\begin{quote}
|
|
1.2.2 \hyperref[anc-animations]{Animations}
|
|
\end{quote}
|
|
|
|
\begin{quote}
|
|
1.2.3 \hyperref[anc-ai]{Artificial Intelligence}
|
|
\end{quote}
|
|
|
|
\begin{quote}
|
|
1.2.4 \hyperref[anc-bp]{Blueprints}
|
|
\end{quote}
|
|
|
|
\begin{quote}
|
|
1.2.5 \hyperref[anc-materials]{Materials}
|
|
\end{quote}
|
|
|
|
\begin{quote}
|
|
1.2.6 \hyperref[anc-textures]{Textures}
|
|
\end{quote}
|
|
|
|
\begin{quote}
|
|
1.2.7 \hyperref[anc-misc]{Miscellaneous}
|
|
\end{quote}
|
|
|
|
\begin{quote}
|
|
1.2.8 \hyperref[anc-paper2d]{Paper 2D}
|
|
\end{quote}
|
|
|
|
\begin{quote}
|
|
1.2.9 \hyperref[anc-physics]{Physics}
|
|
\end{quote}
|
|
|
|
\begin{quote}
|
|
1.2.10 \hyperref[anc-sounds]{Sound}
|
|
\end{quote}
|
|
|
|
\begin{quote}
|
|
1.2.11 \hyperref[anc-ui]{User Interface}
|
|
\end{quote}
|
|
|
|
\begin{quote}
|
|
1.2.12 \hyperref[anc-effects]{Effects}
|
|
\end{quote}
|
|
|
|
\paragraph{1.2.1 Most Common}\label{most-common}
|
|
|
|
\begin{longtable}[]{@{}
|
|
>{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.3067}}
|
|
>{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.1333}}
|
|
>{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.1333}}
|
|
>{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.4267}}@{}}
|
|
\toprule\noalign{}
|
|
\begin{minipage}[b]{\linewidth}\raggedright
|
|
Asset Type
|
|
\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright
|
|
Prefix
|
|
\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright
|
|
Suffix
|
|
\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright
|
|
Notes
|
|
\end{minipage} \\
|
|
\midrule\noalign{}
|
|
\endhead
|
|
\bottomrule\noalign{}
|
|
\endlastfoot
|
|
Level / Map & & & \hyperref[2.4]{Should be in a folder called Maps.} \\
|
|
Level (Persistent) & & \_P & \\
|
|
Level (Audio) & & \_Audio & \\
|
|
Level (Lighting) & & \_Lighting & \\
|
|
Level (Geometry) & & \_Geo & \\
|
|
Level (Gameplay) & & \_Gameplay & \\
|
|
Blueprint & BP\_ & & \\
|
|
Material & M\_ & & \\
|
|
Static Mesh & S\_ & & Many use SM\_. We use S\_. \\
|
|
Skeletal Mesh & SK\_ & & \\
|
|
Texture & T\_ & \_? & See \hyperref[anc-textures]{Textures} \\
|
|
Particle System & PS\_ & & \\
|
|
Widget Blueprint & WBP\_ & & \\
|
|
\end{longtable}
|
|
|
|
\paragraph{1.2.2 Animations}\label{animations}
|
|
|
|
\begin{longtable}[]{@{}
|
|
>{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.3067}}
|
|
>{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.1333}}
|
|
>{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.1333}}
|
|
>{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.4267}}@{}}
|
|
\toprule\noalign{}
|
|
\begin{minipage}[b]{\linewidth}\raggedright
|
|
Asset Type
|
|
\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright
|
|
Prefix
|
|
\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright
|
|
Suffix
|
|
\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright
|
|
Notes
|
|
\end{minipage} \\
|
|
\midrule\noalign{}
|
|
\endhead
|
|
\bottomrule\noalign{}
|
|
\endlastfoot
|
|
Aim Offset & AO\_ & & \\
|
|
Aim Offset 1D & AO\_ & & \\
|
|
Animation Blueprint & ABP\_ & & \\
|
|
Animation Composite & AC\_ & & \\
|
|
Animation Montage & AM\_ & & \\
|
|
Animation Sequence & A\_ & & \\
|
|
Blend Space & BS\_ & & \\
|
|
Blend Space 1D & BS\_ & & \\
|
|
Level Sequence & LS\_ & & \\
|
|
Morph Target & MT\_ & & \\
|
|
Paper Flipbook & PFB\_ & & \\
|
|
Rig & Rig\_ & & \\
|
|
Control Rig & CR\_ & & \\
|
|
Skeletal Mesh & SK\_ & & \\
|
|
Skeleton & SKEL\_ & & \\
|
|
\end{longtable}
|
|
|
|
\subsubsection{1.2.3 Artificial
|
|
Intelligence}\label{artificial-intelligence}
|
|
|
|
\begin{longtable}[]{@{}
|
|
>{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.3067}}
|
|
>{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.1333}}
|
|
>{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.1333}}
|
|
>{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.4267}}@{}}
|
|
\toprule\noalign{}
|
|
\begin{minipage}[b]{\linewidth}\raggedright
|
|
Asset Type
|
|
\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright
|
|
Prefix
|
|
\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright
|
|
Suffix
|
|
\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright
|
|
Notes
|
|
\end{minipage} \\
|
|
\midrule\noalign{}
|
|
\endhead
|
|
\bottomrule\noalign{}
|
|
\endlastfoot
|
|
AI Controller & AIC\_ & & \\
|
|
Behavior Tree & BT\_ & & \\
|
|
Blackboard & BB\_ & & \\
|
|
Decorator & BTDecorator\_ & & \\
|
|
Service & BTService\_ & & \\
|
|
Task & BTTask\_ & & \\
|
|
Environment Query & EQS\_ & & \\
|
|
EnvQueryContext & EQS\_ & Context & \\
|
|
\end{longtable}
|
|
|
|
\subsubsection{1.2.4 Blueprints}\label{blueprints}
|
|
|
|
\begin{longtable}[]{@{}
|
|
>{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.3067}}
|
|
>{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.1333}}
|
|
>{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.1333}}
|
|
>{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.4267}}@{}}
|
|
\toprule\noalign{}
|
|
\begin{minipage}[b]{\linewidth}\raggedright
|
|
Asset Type
|
|
\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright
|
|
Prefix
|
|
\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright
|
|
Suffix
|
|
\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright
|
|
Notes
|
|
\end{minipage} \\
|
|
\midrule\noalign{}
|
|
\endhead
|
|
\bottomrule\noalign{}
|
|
\endlastfoot
|
|
Blueprint & BP\_ & & \\
|
|
Blueprint Component & BP\_ & Component & I.e. BP\_InventoryComponent \\
|
|
Blueprint Function Library & BPFL\_ & & \\
|
|
Blueprint Interface & BPI\_ & & \\
|
|
Blueprint Macro Library & BPML\_ & & Do not use macro libraries if
|
|
possible. \\
|
|
Enumeration & E & & No underscore. \\
|
|
Structure & F or S & & No underscore. \\
|
|
Tutorial Blueprint & TBP\_ & & \\
|
|
Widget Blueprint & WBP\_ & & \\
|
|
\end{longtable}
|
|
|
|
\subsubsection{1.2.5 Materials}\label{materials}
|
|
|
|
\begin{longtable}[]{@{}
|
|
>{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.3580}}
|
|
>{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.1235}}
|
|
>{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.1235}}
|
|
>{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.3951}}@{}}
|
|
\toprule\noalign{}
|
|
\begin{minipage}[b]{\linewidth}\raggedright
|
|
Asset Type
|
|
\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright
|
|
Prefix
|
|
\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright
|
|
Suffix
|
|
\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright
|
|
Notes
|
|
\end{minipage} \\
|
|
\midrule\noalign{}
|
|
\endhead
|
|
\bottomrule\noalign{}
|
|
\endlastfoot
|
|
Material & M\_ & & \\
|
|
Material (Post Process) & PP\_ & & \\
|
|
Material Function & MF\_ & & \\
|
|
Material Instance & MI\_ & & \\
|
|
Material Parameter Collection & MPC\_ & & \\
|
|
Subsurface Profile & SP\_ & & \\
|
|
Physical Materials & PM\_ & & \\
|
|
Decal & M\_, MI\_ & \_Decal & \\
|
|
\end{longtable}
|
|
|
|
\subsubsection{1.2.6 Textures}\label{textures}
|
|
|
|
\begin{longtable}[]{@{}
|
|
>{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.3067}}
|
|
>{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.1333}}
|
|
>{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.1333}}
|
|
>{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.4267}}@{}}
|
|
\toprule\noalign{}
|
|
\begin{minipage}[b]{\linewidth}\raggedright
|
|
Asset Type
|
|
\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright
|
|
Prefix
|
|
\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright
|
|
Suffix
|
|
\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright
|
|
Notes
|
|
\end{minipage} \\
|
|
\midrule\noalign{}
|
|
\endhead
|
|
\bottomrule\noalign{}
|
|
\endlastfoot
|
|
Texture & T\_ & & \\
|
|
Texture (Diffuse/Albedo/Base Color) & T\_ & \_D & \\
|
|
Texture (Normal) & T\_ & \_N & \\
|
|
Texture (Roughness) & T\_ & \_R & \\
|
|
Texture (Alpha/Opacity) & T\_ & \_A & \\
|
|
Texture (Ambient Occlusion) & T\_ & \_O & \\
|
|
Texture (Bump) & T\_ & \_B & \\
|
|
Texture (Emissive) & T\_ & \_E & \\
|
|
Texture (Mask) & T\_ & \_M & \\
|
|
Texture (Specular) & T\_ & \_S & \\
|
|
Texture (Metallic) & T\_ & \_M & \\
|
|
Texture (Packed) & T\_ & \_* & See notes below about
|
|
\hyperref[anc-textures-packing]{packing}. \\
|
|
Texture Cube & TC\_ & & \\
|
|
Media Texture & MT\_ & & \\
|
|
Render Target & RT\_ & & \\
|
|
Cube Render Target & RTC\_ & & \\
|
|
Texture Light Profile & TLP & & \\
|
|
\end{longtable}
|
|
|
|
\paragraph{1.2.6.1 Texture Packing}\label{texture-packing}
|
|
|
|
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.~\texttt{\_ERO}.
|
|
|
|
\begin{quote}
|
|
It is generally acceptable to include an Alpha/Opacity layer in your
|
|
Diffuse/Albedo's alpha channel and as this is common practice, adding
|
|
\texttt{A} to the \texttt{\_D} suffix is optional.
|
|
\end{quote}
|
|
|
|
Packing 4 channels of data into a texture (RGBA) is not recommended
|
|
except for an Alpha/Opacity mask in the Diffuse/Albedo's alpha channel
|
|
as a texture with an alpha channel incurs more overhead than one
|
|
without.
|
|
|
|
\subsubsection{1.2.7 Miscellaneous}\label{miscellaneous}
|
|
|
|
\begin{longtable}[]{@{}
|
|
>{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.3333}}
|
|
>{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.1282}}
|
|
>{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.1282}}
|
|
>{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.4103}}@{}}
|
|
\toprule\noalign{}
|
|
\begin{minipage}[b]{\linewidth}\raggedright
|
|
Asset Type
|
|
\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright
|
|
Prefix
|
|
\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright
|
|
Suffix
|
|
\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright
|
|
Notes
|
|
\end{minipage} \\
|
|
\midrule\noalign{}
|
|
\endhead
|
|
\bottomrule\noalign{}
|
|
\endlastfoot
|
|
Animated Vector Field & VFA\_ & & \\
|
|
Camera Anim & CA\_ & & \\
|
|
Color Curve & Curve\_ & \_Color & \\
|
|
Curve Table & Curve\_ & \_Table & \\
|
|
Data Asset & *\_ & & Prefix should be based on class. \\
|
|
Data Table & DT\_ & & \\
|
|
Float Curve & Curve\_ & \_Float & \\
|
|
Foliage Type & FT\_ & & \\
|
|
Force Feedback Effect & FFE\_ & & \\
|
|
Landscape Grass Type & LG\_ & & \\
|
|
Landscape Layer & LL\_ & & \\
|
|
Matinee Data & Matinee\_ & & \\
|
|
Media Player & MP\_ & & \\
|
|
Object Library & OL\_ & & \\
|
|
Redirector & & & These should be fixed up ASAP. \\
|
|
Sprite Sheet & SS\_ & & \\
|
|
Static Vector Field & VF\_ & & \\
|
|
Substance Graph Instance & SGI\_ & & \\
|
|
Substance Instance Factory & SIF\_ & & \\
|
|
Touch Interface Setup & TI\_ & & \\
|
|
Vector Curve & Curve\_ & \_Vector & \\
|
|
\end{longtable}
|
|
|
|
\subsubsection{1.2.8 Paper 2D}\label{paper-2d}
|
|
|
|
\begin{longtable}[]{@{}
|
|
>{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.3067}}
|
|
>{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.1333}}
|
|
>{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.1333}}
|
|
>{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.4267}}@{}}
|
|
\toprule\noalign{}
|
|
\begin{minipage}[b]{\linewidth}\raggedright
|
|
Asset Type
|
|
\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright
|
|
Prefix
|
|
\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright
|
|
Suffix
|
|
\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright
|
|
Notes
|
|
\end{minipage} \\
|
|
\midrule\noalign{}
|
|
\endhead
|
|
\bottomrule\noalign{}
|
|
\endlastfoot
|
|
Paper Flipbook & PFB\_ & & \\
|
|
Sprite & SPR\_ & & \\
|
|
Sprite Atlas Group & SPRG\_ & & \\
|
|
Tile Map & TM\_ & & \\
|
|
Tile Set & TS\_ & & \\
|
|
\end{longtable}
|
|
|
|
\subsubsection{1.2.9 Physics}\label{physics}
|
|
|
|
\begin{longtable}[]{@{}
|
|
>{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.3067}}
|
|
>{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.1333}}
|
|
>{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.1333}}
|
|
>{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.4267}}@{}}
|
|
\toprule\noalign{}
|
|
\begin{minipage}[b]{\linewidth}\raggedright
|
|
Asset Type
|
|
\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright
|
|
Prefix
|
|
\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright
|
|
Suffix
|
|
\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright
|
|
Notes
|
|
\end{minipage} \\
|
|
\midrule\noalign{}
|
|
\endhead
|
|
\bottomrule\noalign{}
|
|
\endlastfoot
|
|
Physical Material & PM\_ & & \\
|
|
Physics Asset & PHYS\_ & & \\
|
|
Destructible Mesh & DM\_ & & \\
|
|
\end{longtable}
|
|
|
|
\subsubsection{1.2.10 Sounds}\label{sounds}
|
|
|
|
\begin{longtable}[]{@{}
|
|
>{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.3067}}
|
|
>{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.1333}}
|
|
>{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.1333}}
|
|
>{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.4267}}@{}}
|
|
\toprule\noalign{}
|
|
\begin{minipage}[b]{\linewidth}\raggedright
|
|
Asset Type
|
|
\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright
|
|
Prefix
|
|
\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright
|
|
Suffix
|
|
\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright
|
|
Notes
|
|
\end{minipage} \\
|
|
\midrule\noalign{}
|
|
\endhead
|
|
\bottomrule\noalign{}
|
|
\endlastfoot
|
|
Dialogue Voice & DV\_ & & \\
|
|
Dialogue Wave & DW\_ & & \\
|
|
Media Sound Wave & MSW\_ & & \\
|
|
Reverb Effect & Reverb\_ & & \\
|
|
Sound Attenuation & ATT\_ & & \\
|
|
Sound Class & & & No prefix/suffix. Should be put in a folder called
|
|
SoundClasses \\
|
|
Sound Concurrency & & \_SC & Should be named after a SoundClass \\
|
|
Sound Cue & A\_ & \_Cue & \\
|
|
Sound Mix & Mix\_ & & \\
|
|
Sound Wave & A\_ & & \\
|
|
\end{longtable}
|
|
|
|
\subsubsection{1.2.11 User Interface}\label{user-interface}
|
|
|
|
\begin{longtable}[]{@{}
|
|
>{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.3067}}
|
|
>{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.1333}}
|
|
>{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.1333}}
|
|
>{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.4267}}@{}}
|
|
\toprule\noalign{}
|
|
\begin{minipage}[b]{\linewidth}\raggedright
|
|
Asset Type
|
|
\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright
|
|
Prefix
|
|
\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright
|
|
Suffix
|
|
\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright
|
|
Notes
|
|
\end{minipage} \\
|
|
\midrule\noalign{}
|
|
\endhead
|
|
\bottomrule\noalign{}
|
|
\endlastfoot
|
|
Font & Font\_ & & \\
|
|
Slate Brush & Brush\_ & & \\
|
|
Slate Widget Style & Style\_ & & \\
|
|
Widget Blueprint & WBP\_ & & \\
|
|
\end{longtable}
|
|
|
|
\subsubsection{1.2.12 Effects}\label{effects}
|
|
|
|
\begin{longtable}[]{@{}
|
|
>{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.3067}}
|
|
>{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.1333}}
|
|
>{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.1333}}
|
|
>{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.4267}}@{}}
|
|
\toprule\noalign{}
|
|
\begin{minipage}[b]{\linewidth}\raggedright
|
|
Asset Type
|
|
\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright
|
|
Prefix
|
|
\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright
|
|
Suffix
|
|
\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright
|
|
Notes
|
|
\end{minipage} \\
|
|
\midrule\noalign{}
|
|
\endhead
|
|
\bottomrule\noalign{}
|
|
\endlastfoot
|
|
Particle System & PS\_ & & \\
|
|
Material (Post Process) & PP\_ & & \\
|
|
\end{longtable}
|
|
|
|
\textbf{\hyperref[table-of-contents]{⬆ Back to Top}}
|
|
|
|
\subsection{2. Content Directory
|
|
Structure}\label{content-directory-structure}
|
|
|
|
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.
|
|
|
|
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.
|
|
|
|
\begin{quote}
|
|
If you are using the prefix \hyperref[1.2]{naming convention} above,
|
|
using folders to contain assets of similar types such as
|
|
\texttt{Meshes}, \texttt{Textures}, and \texttt{Materials} is a
|
|
redundant practice as asset types are already both sorted by prefix as
|
|
well as able to be filtered in the content browser.
|
|
\end{quote}
|
|
|
|
\#\#\# 2e1 Example Project Content Structure
|
|
|
|
The reasons for this structure are listed in the following sub-sections.
|
|
|
|
\subsubsection{Sections}\label{sections-1}
|
|
|
|
\begin{quote}
|
|
2.1 \hyperref[structure-folder-names]{Folder Names}
|
|
\end{quote}
|
|
|
|
\begin{quote}
|
|
2.2 \hyperref[structure-top-level]{Top-Level Folders}
|
|
\end{quote}
|
|
|
|
\begin{quote}
|
|
2.3 \hyperref[structure-developers]{Developer Folders}
|
|
\end{quote}
|
|
|
|
\begin{quote}
|
|
2.4 \hyperref[structure-maps]{Maps}
|
|
\end{quote}
|
|
|
|
\begin{quote}
|
|
2.5 \hyperref[structure-core]{Core}
|
|
\end{quote}
|
|
|
|
\begin{quote}
|
|
2.6 \hyperref[structure-assettypes]{\texttt{Assets} and
|
|
\texttt{AssetTypes}}
|
|
\end{quote}
|
|
|
|
\begin{quote}
|
|
2.7 \hyperref[structure-large-sets]{Large Sets}
|
|
\end{quote}
|
|
|
|
\begin{quote}
|
|
2.8 \hyperref[structure-material-library]{Material Library}
|
|
\end{quote}
|
|
|
|
\#\#\# 2.1 Folder Names
|
|
|
|
These are common rules for naming any folder in the content structure.
|
|
|
|
\paragraph{\texorpdfstring{2.1.1 Always Use
|
|
PascalCase\hyperref[terms-cases]{*}}{2.1.1 Always Use PascalCase*}}\label{always-use-pascalcase}
|
|
|
|
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, \texttt{DesertEagle}, \texttt{RocketPistol}, and
|
|
\texttt{ASeriesOfWords}.
|
|
|
|
See \hyperref[terms-cases]{Cases}.
|
|
|
|
\paragraph{2.1.2 Never Use Spaces}\label{never-use-spaces}
|
|
|
|
Re-enforcing \hyperref[2.1.1]{2.1.1}, never use spaces. Spaces can cause
|
|
various engineering tools and batch processes to fail. Ideally, your
|
|
project's root also contains no spaces and is located somewhere such as
|
|
\texttt{D:\textbackslash{}Project} instead of
|
|
\texttt{C:\textbackslash{}Users\textbackslash{}My\ Name\textbackslash{}My\ Documents\textbackslash{}Unreal\ Projects}.
|
|
|
|
\paragraph{2.1.3 Never Use Unicode Characters And Other
|
|
Symbols}\label{never-use-unicode-characters-and-other-symbols}
|
|
|
|
If one of your game characters is named `Zoë', its folder name should be
|
|
\texttt{Zoe}. Unicode characters can be worse than
|
|
\hyperref[2.1.2]{Spaces} for engineering tool and some parts of UE4
|
|
don't support Unicode characters in paths either.
|
|
|
|
Related to this, if your project has
|
|
\href{https://answers.unrealengine.com/questions/101207/undefined.html}{unexplained
|
|
issues} and your computer's user name has a Unicode character (i.e.~your
|
|
name is \texttt{Zoë}), any project located in your
|
|
\texttt{My\ Documents} folder will suffer from this issue. Often simply
|
|
moving your project to something like \texttt{D:\textbackslash{}Project}
|
|
will fix these mysterious issues.
|
|
|
|
Using other characters outside \texttt{a-z}, \texttt{A-Z}, and
|
|
\texttt{0-9} such as \texttt{@}, \texttt{-}, \texttt{\_}, \texttt{,},
|
|
\texttt{*}, and \texttt{\#} can also lead to unexpected and hard to
|
|
track issues on other platforms, source control, and weaker engineering
|
|
tools.
|
|
|
|
\#\#\# 2.2 Use A Top Level Folder For Project Specific Assets
|
|
|
|
All of a project's assets should exist in a folder named after the
|
|
project. For example, if your project is named `Generic Shooter',
|
|
\emph{all} of it's content should exist in
|
|
\texttt{Content/GenericShooter}.
|
|
|
|
\begin{quote}
|
|
The \texttt{Developers} folder is not for assets that your project
|
|
relies on and therefore is not project specific. See
|
|
\hyperref[2.3]{Developer Folders} for details about this.
|
|
\end{quote}
|
|
|
|
There are multiple reasons for this approach.
|
|
|
|
\paragraph{2.2.1 No Global Assets}\label{no-global-assets}
|
|
|
|
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.
|
|
|
|
Every asset should have a purpose, otherwise it does not belong in a
|
|
project. If an asset is an experimental test and shouldn't be used by
|
|
the project it should be put in a \hyperref[2.3]{\texttt{Developer}}
|
|
folder.
|
|
|
|
\paragraph{2.2.2 Reduce Migration
|
|
Conflicts}\label{reduce-migration-conflicts}
|
|
|
|
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 Browser's Migrate functionality as it will copy over not just
|
|
the selected asset but all of its dependencies.
|
|
|
|
These dependencies are what can easily get you into trouble. If two
|
|
project's 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.
|
|
|
|
This is also the primary reason why Epic's Marketplace staff enforces
|
|
the same policy for submitted assets.
|
|
|
|
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 project's top level folder are clearly pending a
|
|
merge. Once assets are merged and fully migrated, there shouldn't be
|
|
another top level folder in your Content tree. This method is
|
|
\emph{100\%} guaranteed to make any migrations that occur completely
|
|
safe.
|
|
|
|
\subparagraph{2.2.2e1 Master Material
|
|
Example}\label{e1-master-material-example}
|
|
|
|
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
|
|
\texttt{Content/MaterialLibrary/M\_Master}. If the target project
|
|
doesn't have a master material already, this should work without issue.
|
|
|
|
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.
|
|
|
|
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
|
|
\texttt{Content/MaterialLibrary/M\_Master} as they're instructed to,
|
|
when a migration is performed there is a great chance of conflict for
|
|
the previously migrated \texttt{Content/MaterialLibrary/M\_Master}
|
|
asset.
|
|
|
|
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 project's 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 \texttt{Content/MaterialLibrary/M\_Master} when
|
|
it copies these assets to the other project and it will overwrite the
|
|
existing asset.
|
|
|
|
It is at this point where if the master materials for both projects are
|
|
incompatible in \emph{any way}, 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.
|
|
|
|
\paragraph{2.2.3 Samples, Templates, and Marketplace Content Are
|
|
Risk-Free}\label{samples-templates-and-marketplace-content-are-risk-free}
|
|
|
|
An extension to \hyperref[2.2.2]{2.2.2}, if a team member decides to add
|
|
sample content, template files, or assets they bought from the
|
|
marketplace, it is guaranteed, as long your project's top-level folder
|
|
is uniquely named,that these new assets will not interfere with your
|
|
project.
|
|
|
|
You can not trust marketplace content to fully conform to the
|
|
\hyperref[2.2]{top level folder rule}. 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 \texttt{Content} folder.
|
|
|
|
When adhering to \hyperref[2.2]{2.2}, 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.
|
|
|
|
\paragraph{2.2.4 DLC, Sub-Projects, and Patches Are Easily
|
|
Maintained}\label{dlc-sub-projects-and-patches-are-easily-maintained}
|
|
|
|
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.
|
|
|
|
\subsubsection{2.3 Use Developers Folder For Local
|
|
Testing}\label{use-developers-folder-for-local-testing}
|
|
|
|
During a project's 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 project's 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.
|
|
|
|
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.
|
|
|
|
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.
|
|
|
|
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.
|
|
|
|
\subsubsection{\texorpdfstring{2.4 All Map\hyperref[terms-level-map]{*}
|
|
Files Belong In A Folder Called
|
|
Maps}{2.4 All Map* Files Belong In A Folder Called Maps}}\label{all-map-files-belong-in-a-folder-called-maps}
|
|
|
|
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
|
|
\texttt{/Content/Project/Maps}.
|
|
|
|
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
|
|
\texttt{Maps}, such as \texttt{Maps/Campaign1/} or \texttt{Maps/Arenas},
|
|
but the most important thing here is that they all exist within
|
|
\texttt{/Content/Project/Maps}.
|
|
|
|
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 team's 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.
|
|
|
|
\subsubsection{\texorpdfstring{2.5 Use A \texttt{Core} Folder For
|
|
Critical Blueprints And Other
|
|
Assets}{2.5 Use A Core Folder For Critical Blueprints And Other Assets}}\label{use-a-core-folder-for-critical-blueprints-and-other-assets}
|
|
|
|
Use \texttt{/Content/Project/Core} folder for assets that are absolutely
|
|
fundamental to a project's workings. For example, base
|
|
\texttt{GameMode}, \texttt{Character}, \texttt{PlayerController},
|
|
\texttt{GameState}, \texttt{PlayerState}, and related Blueprints should
|
|
live here.
|
|
|
|
This creates a very clear ``don't touch these'' message for other team
|
|
members. Non-engineers should have very little reason to enter the
|
|
\texttt{Core} 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.
|
|
|
|
For example, if your project requires pickups that can be placed in a
|
|
level, there should exist a base Pickup class in \texttt{Core/Pickups}
|
|
that defines base behavior for a pickup. Specific pickups such as a
|
|
Health or Ammo should exist in a folder such as
|
|
\texttt{/Content/Project/Placeables/Pickups/}. Game designers can define
|
|
and tweak pickups in this folder however they please, but they should
|
|
not touch \texttt{Core/Pickups} as they may unintentionally break
|
|
pickups project-wide.
|
|
|
|
\subsubsection{\texorpdfstring{2.6 Do Not Create Folders Called
|
|
\texttt{Assets} or
|
|
\texttt{AssetTypes}}{2.6 Do Not Create Folders Called Assets or AssetTypes}}\label{do-not-create-folders-called-assets-or-assettypes}
|
|
|
|
\paragraph{\texorpdfstring{2.6.1 Creating a folder named \texttt{Assets}
|
|
is
|
|
redundant.}{2.6.1 Creating a folder named Assets is redundant.}}\label{creating-a-folder-named-assets-is-redundant.}
|
|
|
|
All assets are assets.
|
|
|
|
\paragraph{\texorpdfstring{2.6.2 Creating a folder named
|
|
\texttt{Meshes}, \texttt{Textures}, or \texttt{Materials} is
|
|
redundant.}{2.6.2 Creating a folder named Meshes, Textures, or Materials is redundant.}}\label{creating-a-folder-named-meshes-textures-or-materials-is-redundant.}
|
|
|
|
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.
|
|
|
|
Want to view only static mesh in \texttt{Environment/Rocks/}? 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
|
|
\texttt{Control-Click} select two folders in the Content Browser's tree
|
|
view.
|
|
|
|
\begin{quote}
|
|
This also extends the full path name of an asset for very little
|
|
benefit. The \texttt{S\_} prefix for a static mesh is only two
|
|
characters, whereas \texttt{Meshes/} is seven characters.
|
|
\end{quote}
|
|
|
|
Not doing this also prevents the inevitability of someone putting a
|
|
static mesh or a texture in a \texttt{Materials} folder.
|
|
|
|
\subsubsection{2.7 Very Large Asset Sets Get Their Own Folder
|
|
Layout}\label{very-large-asset-sets-get-their-own-folder-layout}
|
|
|
|
This can be seen as a pseudo-exception to \hyperref[2.6]{2.6}.
|
|
|
|
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.
|
|
|
|
For example, animations that are shared across multiple characters
|
|
should lay in \texttt{Characters/Common/Animations} and may have
|
|
sub-folders such as \texttt{Locomotion} or \texttt{Cinematic}.
|
|
|
|
\begin{quote}
|
|
This does not apply to assets like textures and materials. It is common
|
|
for a \texttt{Rocks} 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 \hyperref[2.8]{Material Library}.
|
|
\end{quote}
|
|
|
|
\subsubsection{\texorpdfstring{2.8
|
|
\texttt{MaterialLibrary}}{2.8 MaterialLibrary}}\label{materiallibrary}
|
|
|
|
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
|
|
\texttt{Content/Project/MaterialLibrary}.
|
|
|
|
This way all `global' materials have a place to live and are easily
|
|
located.
|
|
|
|
\begin{quote}
|
|
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 isn't the
|
|
\texttt{MaterialLibrary}.
|
|
\end{quote}
|
|
|
|
The \texttt{MaterialLibrary} doesn't 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 \texttt{MaterialLibrary/Utility}.
|
|
|
|
Any testing or debug materials should be within
|
|
\texttt{MaterialLibrary/Debug}. 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.
|
|
|
|
\subsubsection{2.9 No Empty Folders}\label{no-empty-folders}
|
|
|
|
There simply shouldn't be any empty folders. They clutter the content
|
|
browser.
|
|
|
|
If you find that the content browser has an empty folder you can't
|
|
delete, you should perform the following: 1. Be sure you're 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.~if
|
|
using Perforce, run a Reconcile Offline Work on your content directory)
|
|
1. Open the editor. Confirm everything still works as expected. If it
|
|
doesn't, revert, figure out what went wrong, and try again. 1. Ensure
|
|
the folder is now gone. 1. Submit changes to source control.
|
|
|
|
\textbf{\hyperref[table-of-contents]{⬆ Back to Top}}
|
|
|
|
\subsection{3. Blueprints}\label{blueprints-1}
|
|
|
|
This section will focus on Blueprint classes and their internals. When
|
|
possible, style rules conform to
|
|
\href{https://docs.unrealengine.com/latest/INT/Programming/Development/CodingStandard}{Epic's
|
|
Coding Standard}.
|
|
|
|
Remember: Blueprinting badly bears blunders, beware! (Phrase by
|
|
\href{http://github.com/KorkuVeren}{KorkuVeren})
|
|
|
|
\subsubsection{Sections}\label{sections-2}
|
|
|
|
\begin{quote}
|
|
3.1 \hyperref[bp-compiling]{Compiling}
|
|
\end{quote}
|
|
|
|
\begin{quote}
|
|
3.2 \hyperref[bp-vars]{Variables}
|
|
\end{quote}
|
|
|
|
\begin{quote}
|
|
3.3 \hyperref[bp-functions]{Functions}
|
|
\end{quote}
|
|
|
|
\begin{quote}
|
|
3.4 \hyperref[bp-graphs]{Graphs}
|
|
\end{quote}
|
|
|
|
\subsubsection{3.1 Compiling}\label{compiling}
|
|
|
|
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.
|
|
|
|
Do \emph{not} submit broken blueprints to source control. If you must
|
|
store them on source control, shelve them instead.
|
|
|
|
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.
|
|
|
|
\subsubsection{3.2 Variables}\label{variables}
|
|
|
|
The words \texttt{variable} and \texttt{property} may be used
|
|
interchangeably.
|
|
|
|
\paragraph{Sections}\label{sections-3}
|
|
|
|
\begin{quote}
|
|
3.2.1 \hyperref[bp-vars]{Naming}
|
|
\end{quote}
|
|
|
|
\begin{quote}
|
|
3.2.2 \hyperref[bp-vars-editable]{Editable}
|
|
\end{quote}
|
|
|
|
\begin{quote}
|
|
3.2.3 \hyperref[bp-vars-categories]{Categories}
|
|
\end{quote}
|
|
|
|
\begin{quote}
|
|
3.2.4 \hyperref[bp-vars-access]{Access}
|
|
\end{quote}
|
|
|
|
\begin{quote}
|
|
3.2.5 \hyperref[bp-vars-advanced]{Advanced}
|
|
\end{quote}
|
|
|
|
\begin{quote}
|
|
3.2.6 \hyperref[bp-vars-transient]{Transient}
|
|
\end{quote}
|
|
|
|
\begin{quote}
|
|
3.2.7 \hyperref[bp-vars-config]{Config}
|
|
\end{quote}
|
|
|
|
\paragraph{3.2.1 Naming}\label{naming}
|
|
|
|
\subparagraph{3.2.1.1 Nouns}\label{nouns}
|
|
|
|
All non-boolean variable names must be clear, unambiguous, and
|
|
descriptive nouns.
|
|
|
|
\subparagraph{3.2.1.2 PascalCase}\label{pascalcase-1}
|
|
|
|
All non-boolean variables should be in the form of
|
|
\hyperref[terms-cases]{PascalCase}.
|
|
|
|
3.2.1.2e Examples:
|
|
|
|
\begin{itemize}
|
|
\tightlist
|
|
\item
|
|
\texttt{Score}
|
|
\item
|
|
\texttt{Kills}
|
|
\item
|
|
\texttt{TargetPlayer}
|
|
\item
|
|
\texttt{Range}
|
|
\item
|
|
\texttt{CrosshairColor}
|
|
\item
|
|
\texttt{AbilityID}
|
|
\end{itemize}
|
|
|
|
\subparagraph{\texorpdfstring{3.2.1.3 Boolean \texttt{b}
|
|
Prefix}{3.2.1.3 Boolean b Prefix}}\label{boolean-b-prefix}
|
|
|
|
All booleans should be named in PascalCase but prefixed with a lowercase
|
|
\texttt{b}.
|
|
|
|
Example: Use \texttt{bDead} and \texttt{bEvil}, \textbf{not}
|
|
\texttt{Dead} and \texttt{Evil}.
|
|
|
|
UE4 Blueprint editors know not to include the \texttt{b} in
|
|
user-friendly displays of the variable.
|
|
|
|
\subparagraph{3.2.1.4 Boolean Names}\label{boolean-names}
|
|
|
|
3.2.1.4.1 General And Independent State Information
|
|
|
|
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 \texttt{Is}. This is reserved for
|
|
functions.
|
|
|
|
Example: Use \texttt{bDead} and \texttt{bHostile} \textbf{not}
|
|
\texttt{bIsDead} and \texttt{bIsHostile}.
|
|
|
|
Try to not use verbs such as \texttt{bRunning}. Verbs tend to lead to
|
|
complex states.
|
|
|
|
3.2.1.4.2 Complex States
|
|
|
|
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.
|
|
|
|
Example: When defining a weapon, do \textbf{not} use \texttt{bReloading}
|
|
and \texttt{bEquipping} if a weapon can't be both reloading and
|
|
equipping. Define an enumeration named \texttt{EWeaponState} and use a
|
|
variable with this type named \texttt{WeaponState} instead. This makes
|
|
it far easier to add new states to weapons.
|
|
|
|
Example: Do \textbf{not} use \texttt{bRunning} if you also need
|
|
\texttt{bWalking} or \texttt{bSprinting}. This should be defined as an
|
|
enumeration with clearly defined state names.
|
|
|
|
\subparagraph{3.2.1.5 Considered Context}\label{considered-context}
|
|
|
|
All variable names must not be redundant with their context as all
|
|
variable references in Blueprint will always have context.
|
|
|
|
3.2.1.5e Examples:
|
|
|
|
Consider a Blueprint called \texttt{BP\_PlayerCharacter}.
|
|
|
|
\textbf{Bad}
|
|
|
|
\begin{itemize}
|
|
\tightlist
|
|
\item
|
|
\texttt{PlayerScore}
|
|
\item
|
|
\texttt{PlayerKills}
|
|
\item
|
|
\texttt{MyTargetPlayer}
|
|
\item
|
|
\texttt{MyCharacterName}
|
|
\item
|
|
\texttt{CharacterSkills}
|
|
\item
|
|
\texttt{ChosenCharacterSkin}
|
|
\end{itemize}
|
|
|
|
All of these variables are named redundantly. It is implied that the
|
|
variable is representative of the \texttt{BP\_PlayerCharacter} it
|
|
belongs to because it is \texttt{BP\_PlayerCharacter} that is defining
|
|
these variables.
|
|
|
|
\textbf{Good}
|
|
|
|
\begin{itemize}
|
|
\tightlist
|
|
\item
|
|
\texttt{Score}
|
|
\item
|
|
\texttt{Kills}
|
|
\item
|
|
\texttt{TargetPlayer}
|
|
\item
|
|
\texttt{Name}
|
|
\item
|
|
\texttt{Skills}
|
|
\item
|
|
\texttt{Skin}
|
|
\end{itemize}
|
|
|
|
\subparagraph{\texorpdfstring{3.2.1.6 Do \emph{Not} Include Atomic Type
|
|
Names}{3.2.1.6 Do Not Include Atomic Type Names}}\label{do-not-include-atomic-type-names}
|
|
|
|
Atomic or primitive variables are variables that represent data in their
|
|
simplest form, such as booleans, integers, floats, and enumerations.
|
|
|
|
Strings and vectors are considered atomic in terms of style when working
|
|
with Blueprints, however they are technically not atomic.
|
|
|
|
\begin{quote}
|
|
While vectors consist of three floats, vectors are often able to be
|
|
manipulated as a whole, same with rotators.
|
|
\end{quote}
|
|
|
|
\begin{quote}
|
|
Do \emph{not} consider Text variables as atomic, they are secretly
|
|
hiding localization functionality. The atomic type of a string of
|
|
characters is \texttt{String}, not \texttt{Text}.
|
|
\end{quote}
|
|
|
|
Atomic variables should not have their type name in their name.
|
|
|
|
Example: Use \texttt{Score}, \texttt{Kills}, and \texttt{Description}
|
|
\textbf{not} \texttt{ScoreFloat}, \texttt{FloatKills},
|
|
\texttt{DescriptionString}.
|
|
|
|
The only exception to this rule is when a variable represents `a number
|
|
of' something to be counted \emph{and} when using a name without a
|
|
variable type is not easy to read.
|
|
|
|
Example: A fence generator needs to generate X number of posts. Store X
|
|
in \texttt{NumPosts} or \texttt{PostsCount} instead of \texttt{Posts} as
|
|
\texttt{Posts} may potentially read as an Array of a variable type named
|
|
\texttt{Post}.
|
|
|
|
\subparagraph{3.2.1.7 Do Include Non-Atomic Type
|
|
Names}\label{do-include-non-atomic-type-names}
|
|
|
|
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 \texttt{Text} and \texttt{Name}
|
|
all qualify under this rule.
|
|
|
|
\begin{quote}
|
|
While an Array of an atomic variable type is a list of variables, Arrays
|
|
do not change the `atomicness' of a variable type.
|
|
\end{quote}
|
|
|
|
These variables should include their type name while still considering
|
|
their context.
|
|
|
|
If a class owns an instance of a complex variable, i.e.~if a
|
|
\texttt{BP\_PlayerCharacter} owns a \texttt{BP\_Hat}, it should be
|
|
stored as the variable type as without any name modifications.
|
|
|
|
Example: Use \texttt{Hat}, \texttt{Flag}, and \texttt{Ability}
|
|
\textbf{not} \texttt{MyHat}, \texttt{MyFlag}, and
|
|
\texttt{PlayerAbility}.
|
|
|
|
If a class does not own the value a complex variable represents, you
|
|
should use a noun along with the variable type.
|
|
|
|
Example: If a \texttt{BP\_Turret} has the ability to target a
|
|
\texttt{BP\_PlayerCharacter}, it should store its target as
|
|
\texttt{TargetPlayer} as when in the context of \texttt{BP\_Turret} it
|
|
should be clear that it is a reference to another complex variable type
|
|
that it does not own.
|
|
|
|
\subparagraph{3.2.1.8 Arrays}\label{arrays}
|
|
|
|
Arrays follow the same naming rules as above, but should be named as a
|
|
plural noun.
|
|
|
|
Example: Use \texttt{Targets}, \texttt{Hats}, and \texttt{EnemyPlayers},
|
|
\textbf{not} \texttt{TargetList}, \texttt{HatArray},
|
|
\texttt{EnemyPlayerArray}.
|
|
|
|
\paragraph{3.2.2 Editable Variables}\label{editable-variables}
|
|
|
|
All variables that are safe to change the value of in order to configure
|
|
behavior of a blueprint should be marked as \texttt{Editable}.
|
|
|
|
Conversely, all variables that are not safe to change or should not be
|
|
exposed to designers should \emph{not} be marked as editable, unless for
|
|
engineering reasons the variable must be marked as
|
|
\texttt{Expose\ On\ Spawn}.
|
|
|
|
Do not arbitrarily mark variables as \texttt{Editable}.
|
|
|
|
\subparagraph{3.2.2.1 Tooltips}\label{tooltips}
|
|
|
|
All \texttt{Editable} variables, including those marked editable just so
|
|
they can be marked as \texttt{Expose\ On\ Spawn}, should have a
|
|
description in their \texttt{Tooltip} fields that explains how changing
|
|
this value affects the behavior of the blueprint.
|
|
|
|
\subparagraph{3.2.2.2 Slider And Value
|
|
Ranges}\label{slider-and-value-ranges}
|
|
|
|
All \texttt{Editable} variables should make use of slider and value
|
|
ranges if there is ever a value that a variable should \emph{not} be set
|
|
to.
|
|
|
|
Example: A blueprint that generates fence posts might have an editable
|
|
variable named \texttt{PostsCount} and a value of -1 would not make any
|
|
sense. Use the range fields to mark 0 as a minimum.
|
|
|
|
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.
|
|
|
|
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.
|
|
|
|
\paragraph{3.2.3 Categories}\label{categories}
|
|
|
|
If a class has only a small number of variables, categories are not
|
|
required.
|
|
|
|
If a class has a moderate amount of variables (5-10), all
|
|
\texttt{Editable} variables should have a non-default category assigned.
|
|
A common category is \texttt{Config}.
|
|
|
|
If a class has a large amount of variables, all \texttt{Editable}
|
|
variables should be categorized into sub-categories using the category
|
|
\texttt{Config} as the base category. Non-editable variables should be
|
|
categorized into descriptive categories describing their usage.
|
|
|
|
\begin{quote}
|
|
You can define sub-categories by using the pipe character
|
|
\texttt{\textbar{}}, i.e.~\texttt{Config\ \textbar{}\ Animations}.
|
|
\end{quote}
|
|
|
|
Example: A weapon class set of variables might be organized as:
|
|
|
|
\begin{verbatim}
|
|
|-- Config
|
|
| |-- Animations
|
|
| |-- Effects
|
|
| |-- Audio
|
|
| |-- Recoil
|
|
| |-- Timings
|
|
|-- Animations
|
|
|-- State
|
|
|-- Visuals
|
|
\end{verbatim}
|
|
|
|
\paragraph{3.2.4 Variable Access Level}\label{variable-access-level}
|
|
|
|
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.
|
|
|
|
Blueprints do not have a defined concept of protected access currently.
|
|
|
|
Treat \texttt{Editable} variables as public variables. Treat
|
|
non-editable variables as protected variables.
|
|
|
|
\subparagraph{3.2.4.1 Private Variables}\label{private-variables}
|
|
|
|
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 \texttt{protected},
|
|
reserve private for when you absolutely know you want to restrict child
|
|
class usage.
|
|
|
|
\paragraph{3.2.5 Advanced Display}\label{advanced-display}
|
|
|
|
If a variable should be editable but often untouched, mark it as
|
|
\texttt{Advanced\ Display}. This makes the variable hidden unless the
|
|
advanced display arrow is clicked.
|
|
|
|
To find the \texttt{Advanced\ Display} option, it is listed as an
|
|
advanced displayed variable in the variable details list.
|
|
|
|
\paragraph{3.2.6 Transient Variables}\label{transient-variables}
|
|
|
|
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 who's value isn't
|
|
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.
|
|
|
|
Because of this, all transient variables should always be initialized as
|
|
zero or null. To do otherwise would result in hard to debug errors.
|
|
|
|
\paragraph{3.2.8 Config Variables}\label{config-variables}
|
|
|
|
Do not use the \texttt{Config\ Variable} 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
|
|
\texttt{Advanced\ Advanced\ Display} variables.
|
|
|
|
\subsubsection{3.3 Functions, Events, and Event
|
|
Dispatchers}\label{functions-events-and-event-dispatchers}
|
|
|
|
This section describes how you should author functions, events, and
|
|
event dispatchers. Everything that applies to functions also applies to
|
|
events, unless otherwise noted.
|
|
|
|
\paragraph{3.3.1 Function Naming}\label{function-naming}
|
|
|
|
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:
|
|
|
|
\begin{itemize}
|
|
\tightlist
|
|
\item
|
|
Is it a pure function?
|
|
\item
|
|
Is it fetching state information?
|
|
\item
|
|
Is it a handler?
|
|
\item
|
|
Is it an RPC?
|
|
\item
|
|
What is its purpose?
|
|
\end{itemize}
|
|
|
|
These questions and more can all be answered when functions are named
|
|
appropriately.
|
|
|
|
\paragraph{3.3.1.1 All Functions Should Be
|
|
Verbs}\label{all-functions-should-be-verbs}
|
|
|
|
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.
|
|
|
|
\texttt{OnRep} functions, event handlers, and event dispatchers are an
|
|
exception to this rule.
|
|
|
|
Good examples:
|
|
|
|
\begin{itemize}
|
|
\tightlist
|
|
\item
|
|
\texttt{Fire} - Good example if in a Character / Weapon class, as it
|
|
has context. Bad if in a Barrel / Grass / any ambiguous class.
|
|
\item
|
|
\texttt{Jump} - Good example if in a Character class, otherwise, needs
|
|
context.
|
|
\item
|
|
\texttt{Explode}
|
|
\item
|
|
\texttt{ReceiveMessage}
|
|
\item
|
|
\texttt{SortPlayerArray}
|
|
\item
|
|
\texttt{GetArmOffset}
|
|
\item
|
|
\texttt{GetCoordinates}
|
|
\item
|
|
\texttt{UpdateTransforms}
|
|
\item
|
|
\texttt{EnableBigHeadMode}
|
|
\item
|
|
\texttt{IsEnemy} -
|
|
\href{http://writingexplained.org/is-is-a-verb}{``Is'' is a verb.}
|
|
\end{itemize}
|
|
|
|
Bad examples:
|
|
|
|
\begin{itemize}
|
|
\tightlist
|
|
\item
|
|
\texttt{Dead} - Is Dead? Will deaden?
|
|
\item
|
|
\texttt{Rock}
|
|
\item
|
|
\texttt{ProcessData} - Ambiguous, these words mean nothing.
|
|
\item
|
|
\texttt{PlayerState} - Nouns are ambiguous.
|
|
\item
|
|
\texttt{Color} - Verb with no context, or ambiguous noun.
|
|
\end{itemize}
|
|
|
|
\paragraph{\texorpdfstring{3.3.1.2 Property RepNotify Functions Always
|
|
\texttt{OnRep\_Variable}}{3.3.1.2 Property RepNotify Functions Always OnRep\_Variable}}\label{property-repnotify-functions-always-onrep_variable}
|
|
|
|
All functions for replicated with notification variables should have the
|
|
form \texttt{OnRep\_Variable}. This is forced by the Blueprint editor.
|
|
If you are writing a C++ \texttt{OnRep} function however, it should also
|
|
follow this convention when exposing it to Blueprints.
|
|
|
|
\paragraph{3.3.1.3 Info Functions Returning Bool Should Ask
|
|
Questions}\label{info-functions-returning-bool-should-ask-questions}
|
|
|
|
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
|
|
\hyperref[bp-funcs-naming-verbs]{the verb rule}.
|
|
|
|
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.
|
|
|
|
Good examples:
|
|
|
|
\begin{itemize}
|
|
\tightlist
|
|
\item
|
|
\texttt{IsDead}
|
|
\item
|
|
\texttt{IsOnFire}
|
|
\item
|
|
\texttt{IsAlive}
|
|
\item
|
|
\texttt{IsSpeaking}
|
|
\item
|
|
\texttt{IsHavingAnExistentialCrisis}
|
|
\item
|
|
\texttt{IsVisible}
|
|
\item
|
|
\texttt{HasWeapon} -
|
|
\href{http://grammar.yourdictionary.com/parts-of-speech/verbs/Helping-Verbs.html}{``Has''
|
|
is a verb.}
|
|
\item
|
|
\texttt{WasCharging} -
|
|
\href{http://grammar.yourdictionary.com/parts-of-speech/verbs/Helping-Verbs.html}{``Was''
|
|
is past-tense of ``be''.} Use ``was'' when referring to `previous
|
|
frame' or `previous state'.
|
|
\item
|
|
\texttt{CanReload} -
|
|
\href{http://grammar.yourdictionary.com/parts-of-speech/verbs/Helping-Verbs.html}{``Can''
|
|
is a verb.}
|
|
\end{itemize}
|
|
|
|
Bad examples:
|
|
|
|
\begin{itemize}
|
|
\tightlist
|
|
\item
|
|
\texttt{Fire} - Is on fire? Will fire? Do fire?
|
|
\item
|
|
\texttt{OnFire} - Can be confused with event dispatcher for firing.
|
|
\item
|
|
\texttt{Dead} - Is dead? Will deaden?
|
|
\item
|
|
\texttt{Visibility} - Is visible? Set visibility? A description of
|
|
flying conditions?
|
|
\end{itemize}
|
|
|
|
\paragraph{\texorpdfstring{3.3.1.4 Event Handlers and Dispatchers Should
|
|
Start With
|
|
\texttt{On}}{3.3.1.4 Event Handlers and Dispatchers Should Start With On}}\label{event-handlers-and-dispatchers-should-start-with-on}
|
|
|
|
Any function that handles an event or dispatches an event should start
|
|
with \texttt{On} and continue to follow
|
|
\hyperref[bp-funcs-naming-verbs]{the verb rule}. The verb may move to
|
|
the end however if past-tense reads better.
|
|
|
|
\href{http://dictionary.cambridge.org/us/grammar/british-grammar/about-words-clauses-and-sentences/collocation}{Collocations}
|
|
of the word \texttt{On} are exempt from following the verb rule.
|
|
|
|
\texttt{Handle} is not allowed. It is `Unreal' to use \texttt{On}
|
|
instead of \texttt{Handle}, while other frameworks may prefer to use
|
|
\texttt{Handle} instead of \texttt{On}.
|
|
|
|
Good examples:
|
|
|
|
\begin{itemize}
|
|
\tightlist
|
|
\item
|
|
\texttt{OnDeath} - Common collocation in games
|
|
\item
|
|
\texttt{OnPickup}
|
|
\item
|
|
\texttt{OnReceiveMessage}
|
|
\item
|
|
\texttt{OnMessageRecieved}
|
|
\item
|
|
\texttt{OnTargetChanged}
|
|
\item
|
|
\texttt{OnClick}
|
|
\item
|
|
\texttt{OnLeave}
|
|
\end{itemize}
|
|
|
|
Bad examples:
|
|
|
|
\begin{itemize}
|
|
\tightlist
|
|
\item
|
|
\texttt{OnData}
|
|
\item
|
|
\texttt{OnTarget}
|
|
\item
|
|
\texttt{HandleMessage}
|
|
\item
|
|
\texttt{HandleDeath}
|
|
\end{itemize}
|
|
|
|
\paragraph{3.3.1.5 Remote Procedure Calls Should Be Prefixed With
|
|
Target}\label{remote-procedure-calls-should-be-prefixed-with-target}
|
|
|
|
Any time an RPC is created, it should be prefixed with either
|
|
\texttt{Server}, \texttt{Client}, or \texttt{Multicast}. No exceptions.
|
|
|
|
After the prefix, follow all other rules regarding function naming.
|
|
|
|
Good examples:
|
|
|
|
\begin{itemize}
|
|
\tightlist
|
|
\item
|
|
\texttt{ServerFireWeapon}
|
|
\item
|
|
\texttt{ClientNotifyDeath}
|
|
\item
|
|
\texttt{MulticastSpawnTracerEffect}
|
|
\end{itemize}
|
|
|
|
Bad examples:
|
|
|
|
\begin{itemize}
|
|
\tightlist
|
|
\item
|
|
\texttt{FireWeapon} - Does not indicate its an RPC of some kind.
|
|
\item
|
|
\texttt{ServerClientBroadcast} - Confusing.
|
|
\item
|
|
\texttt{AllNotifyDeath} - Use \texttt{Multicast}, never \texttt{All}.
|
|
\item
|
|
\texttt{ClientWeapon} - No verb, ambiguous.
|
|
\end{itemize}
|
|
|
|
\paragraph{3.3.2 All Functions Must Have Return
|
|
Nodes}\label{all-functions-must-have-return-nodes}
|
|
|
|
All functions must have return nodes, no exceptions.
|
|
|
|
Return nodes explicitly note that a function has finished its execution.
|
|
In a world where blueprints can be filled with \texttt{Sequence},
|
|
\texttt{ForLoopWithBreak}, and backwards reroute nodes, explicit
|
|
execution flow is important for readability, maintenance, and easier
|
|
debugging.
|
|
|
|
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.
|
|
|
|
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.
|
|
|
|
\paragraph{3.3.3 No Function Should Have More Than 50
|
|
Nodes}\label{no-function-should-have-more-than-50-nodes}
|
|
|
|
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.
|
|
|
|
The following nodes are not counted as they are deemed to not increase
|
|
function complexity:
|
|
|
|
\begin{itemize}
|
|
\tightlist
|
|
\item
|
|
Comment
|
|
\item
|
|
Route
|
|
\item
|
|
Cast
|
|
\item
|
|
Getting a Variable
|
|
\item
|
|
Breaking a Struct
|
|
\item
|
|
Function Entry
|
|
\item
|
|
Self
|
|
\end{itemize}
|
|
|
|
\paragraph{3.3.4 All Public Functions Should Have A
|
|
Description}\label{all-public-functions-should-have-a-description}
|
|
|
|
This rule applies more to public facing or marketplace blueprints, so
|
|
that others can more easily navigate and consume your blueprint API.
|
|
|
|
Simply, any function that has an access specificer of Public should have
|
|
its description filled out.
|
|
|
|
\paragraph{\texorpdfstring{3.3.5 All Custom Static Plugin
|
|
\texttt{BlueprintCallable} Functions Must Be Categorized By Plugin
|
|
Name}{3.3.5 All Custom Static Plugin BlueprintCallable Functions Must Be Categorized By Plugin Name}}\label{all-custom-static-plugin-blueprintcallable-functions-must-be-categorized-by-plugin-name}
|
|
|
|
If your project includes a plugin that defines \texttt{static}
|
|
\texttt{BlueprintCallable} functions, they should have their category
|
|
set to the plugin's name or a subset category of the plugin's name.
|
|
|
|
For example, \texttt{Zed\ Camera\ Interface} or
|
|
\texttt{Zed\ Camera\ Interface\ \textbar{}\ Image\ Capturing}.
|
|
|
|
\subsubsection{3.4 Blueprint Graphs}\label{blueprint-graphs}
|
|
|
|
This section covers things that apply to all Blueprint graphs.
|
|
|
|
\paragraph{3.4.1 No Spaghetti}\label{no-spaghetti}
|
|
|
|
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.
|
|
|
|
\paragraph{3.4.2 Align Wires Not Nodes}\label{align-wires-not-nodes}
|
|
|
|
Always align wires, not nodes. You can't 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
|
|
|
|
Good example: The tops of the nodes are staggered to keep a perfectly
|
|
straight white exec line.
|
|
\pandocbounded{\includegraphics[keepaspectratio]{styleguide_files/mediabag/bp-graphs-align-wire.png}}
|
|
|
|
Bad Example: The tops of the nodes are aligned creating a wiggly white
|
|
exec line.
|
|
\pandocbounded{\includegraphics[keepaspectratio]{styleguide_files/mediabag/bp-graphs-align-wire1.png}}
|
|
|
|
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.
|
|
\pandocbounded{\includegraphics[keepaspectratio]{styleguide_files/mediabag/bp-graphs-align-wire12.png}}
|
|
|
|
\paragraph{3.4.3 White Exec Lines Are Top
|
|
Priority}\label{white-exec-lines-are-top-priority}
|
|
|
|
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.
|
|
|
|
\paragraph{3.4.4 Graphs Should Be Reasonably
|
|
Commented}\label{graphs-should-be-reasonably-commented}
|
|
|
|
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 function's
|
|
goal, then they do not need to be commented as the function name and
|
|
description should suffice.
|
|
|
|
\paragraph{3.4.5 Graphs Should Handle Casting Errors Where
|
|
Appropriate}\label{graphs-should-handle-casting-errors-where-appropriate}
|
|
|
|
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' doesn't. A function
|
|
should also attempt a graceful recover after a failed cast if it's known
|
|
that the reference being casted could ever fail to be casted.
|
|
|
|
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.
|
|
|
|
\paragraph{3.4.6 Graphs Should Not Have Any Dangling / Loose / Dead
|
|
Nodes}\label{graphs-should-not-have-any-dangling-loose-dead-nodes}
|
|
|
|
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.
|
|
|
|
\textbf{\hyperref[table-of-contents]{⬆ Back to Top}}
|
|
|
|
\subsection{4. Static Meshes}\label{static-meshes}
|
|
|
|
This section will focus on Static Mesh assets and their internals.
|
|
|
|
\subsubsection{Sections}\label{sections-4}
|
|
|
|
\begin{quote}
|
|
4.1 \hyperref[s-uvs]{UVs}
|
|
\end{quote}
|
|
|
|
\begin{quote}
|
|
4.2 \hyperref[s-lods]{LODs}
|
|
\end{quote}
|
|
|
|
\begin{quote}
|
|
4.3 \hyperref[s-modular-snapping]{Modular Socketless Snapping}
|
|
\end{quote}
|
|
|
|
\begin{quote}
|
|
4.4 \hyperref[s-collision]{Must Have Collision}
|
|
\end{quote}
|
|
|
|
\begin{quote}
|
|
4.5 \hyperref[s-scaled]{Correct Scale}
|
|
\end{quote}
|
|
|
|
\subsubsection{4.1 Static Mesh UVs}\label{static-mesh-uvs}
|
|
|
|
If Linter is reporting bad UVs and you can't seem to track it down, open
|
|
the resulting \texttt{.log} file in your project's \texttt{Saved/Logs}
|
|
folder for exact details as to why it's failing. I am hoping to include
|
|
these messages in the Lint report in the future.
|
|
|
|
\paragraph{4.1.1 All Meshes Must Have
|
|
UVs}\label{all-meshes-must-have-uvs}
|
|
|
|
Pretty simple. All meshes, regardless how they are to be used, should
|
|
not be missing UVs.
|
|
|
|
\paragraph{4.1.2 All Meshes Must Not Have Overlapping UVs for
|
|
Lightmaps}\label{all-meshes-must-not-have-overlapping-uvs-for-lightmaps}
|
|
|
|
Pretty simple. All meshes, regardless how they are to be used, should
|
|
have valid non-overlapping UVs.
|
|
|
|
\subsubsection{4.2 LODs Should Be Set Up
|
|
Correctly}\label{lods-should-be-set-up-correctly}
|
|
|
|
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.
|
|
|
|
\subsubsection{4.3 Modular Socketless Assets Should Snap To The Grid
|
|
Cleanly}\label{modular-socketless-assets-should-snap-to-the-grid-cleanly}
|
|
|
|
This is a subjective check on a per-asset basis, however any modular
|
|
socketless assets should snap together cleanly based on the project's
|
|
grid settings.
|
|
|
|
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, Epic's requirement is that they snap cleanly when
|
|
the grid is set to 10 units or bigger.
|
|
|
|
\subsubsection{4.4 All Meshes Must Have
|
|
Collision}\label{all-meshes-must-have-collision}
|
|
|
|
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.
|
|
|
|
\subsubsection{4.5 All Meshes Should Be Scaled
|
|
Correctly}\label{all-meshes-should-be-scaled-correctly}
|
|
|
|
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.
|
|
|
|
\textbf{\hyperref[table-of-contents]{⬆ Back to Top}}
|
|
|
|
\subsection{5. Niagara}\label{niagara}
|
|
|
|
This section will focus on Niagara assets and their internals.
|
|
|
|
\subsubsection{Sections}\label{sections-5}
|
|
|
|
\begin{quote}
|
|
5.1 \hyperref[ng-rules]{Naming Rules}
|
|
\end{quote}
|
|
|
|
\subsubsection{5.1 No Spaces, Ever}\label{no-spaces-ever}
|
|
|
|
As mentioned in \hyperref[00]{00.1 Forbidden Identifiers}, 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.
|
|
|
|
(Original Contribution by
|
|
\href{https://github.com/Allar/ue5-style-guide/issues/58}{@dunenkoff\marginpar{\begin{footnotesize}{?quarto-cite:dunenkoff}\vspace{2mm}\par\end{footnotesize}}})
|
|
|
|
\textbf{\hyperref[table-of-contents]{⬆ Back to Top}}
|
|
|
|
\subsection{6. Levels / Maps}\label{levels-maps}
|
|
|
|
\hyperref[terms-level-map]{See Terminology Note} regarding ``levels'' vs
|
|
``maps''.
|
|
|
|
This section will focus on Level assets and their internals.
|
|
|
|
\subsubsection{Sections}\label{sections-6}
|
|
|
|
\begin{quote}
|
|
6.1 \hyperref[levels-no-errors-or-warnings]{No Errors Or Warnings}
|
|
\end{quote}
|
|
|
|
\begin{quote}
|
|
6.2 \hyperref[levels-lighting-should-be-built]{Lighting Should Be Built}
|
|
\end{quote}
|
|
|
|
\begin{quote}
|
|
6.3 \hyperref[evels-no-visible-z-fighting]{No Player Visible Z Fighting}
|
|
\end{quote}
|
|
|
|
\begin{quote}
|
|
6.4 \hyperref[evels-levels-mp-rules]{Marketplace Specific Rules}
|
|
\end{quote}
|
|
|
|
\subsubsection{6.1 No Errors Or Warnings}\label{no-errors-or-warnings}
|
|
|
|
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.
|
|
|
|
You can run a map check on an open level in the editor by using the
|
|
console command ``map check''.
|
|
|
|
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.
|
|
|
|
\subsubsection{6.2 Lighting Should Be
|
|
Built}\label{lighting-should-be-built}
|
|
|
|
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.
|
|
|
|
\subsubsection{6.3 No Player Visible Z
|
|
Fighting}\label{no-player-visible-z-fighting}
|
|
|
|
Levels should not have any
|
|
\href{https://en.wikipedia.org/wiki/Z-fighting}{z-fighting} in all areas
|
|
visible to the player.
|
|
|
|
\subsubsection{6.4 Marketplace Specific
|
|
Rules}\label{marketplace-specific-rules}
|
|
|
|
If a project is to be sold on the UE4 Marketplace, it must follow these
|
|
rules.
|
|
|
|
\subsubsection{6.4.1 Overview Level}\label{overview-level}
|
|
|
|
If your project contains assets that should be visualized or demoed, you
|
|
must have a map within your project that contains the name ``Overview''.
|
|
|
|
This overview map, if it is visualizing assets, should be set up
|
|
according to
|
|
\href{http://help.epicgames.com/customer/en/portal/articles/2592186-marketplace-submission-guidelines-preparing-your-assets\#Required\%20Levels\%20and\%20Maps}{Epic's
|
|
guidelines}.
|
|
|
|
For example, \texttt{InteractionComponent\_Overview}.
|
|
|
|
\subsubsection{6.4.2 Demo Level}\label{demo-level}
|
|
|
|
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 Epic's
|
|
Content Examples project for good examples on how to do this.
|
|
|
|
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.
|
|
|
|
For example, \texttt{InteractionComponent\_Overview\_Demo},
|
|
\texttt{ExplosionKit\_Demo}.
|
|
|
|
\textbf{\hyperref[table-of-contents]{⬆ Back to Top}}
|
|
|
|
\subsection{7. Textures}\label{textures-1}
|
|
|
|
This section will focus on Texture assets and their internals.
|
|
|
|
\subsubsection{Sections}\label{sections-7}
|
|
|
|
\begin{quote}
|
|
7.1 \hyperref[textures-dimension]{Dimensions Are Powers of 2}
|
|
\end{quote}
|
|
|
|
\begin{quote}
|
|
7.2 \hyperref[textures-dimension]{Texture Density Should Be Uniform}
|
|
\end{quote}
|
|
|
|
\begin{quote}
|
|
7.3 \hyperref[textures-max-size]{Textures Should Be No Bigger than 8192}
|
|
\end{quote}
|
|
|
|
\begin{quote}
|
|
7.4 \hyperref[textures-textures-group]{Correct Texture Groups}
|
|
\end{quote}
|
|
|
|
\subsubsection{7.1 Dimensions Are Powers of
|
|
2}\label{dimensions-are-powers-of-2}
|
|
|
|
All textures, except for UI textures, must have its dimensions in
|
|
multiples of powers of 2. Textures do not have to be square.
|
|
|
|
For example, \texttt{128x512}, \texttt{1024x1024}, \texttt{2048x1024},
|
|
\texttt{1024x2048}, \texttt{1x512}.
|
|
|
|
\subsubsection{7.2 Texture Density Should Be
|
|
Uniform}\label{texture-density-should-be-uniform}
|
|
|
|
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.
|
|
|
|
For example, if a project's 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 project's
|
|
texture density.
|
|
|
|
\subsubsection{7.3 Textures Should Be No Bigger than
|
|
8192}\label{textures-should-be-no-bigger-than-8192}
|
|
|
|
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.
|
|
|
|
\subsubsection{7.4 Textures Should Be Grouped
|
|
Correctly}\label{textures-should-be-grouped-correctly}
|
|
|
|
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.
|
|
|
|
\textbf{\hyperref[table-of-contents]{⬆ Back to Top}}
|
|
|
|
|
|
|
|
|
|
\end{document}
|