Gamemakin UE5 Guide de Style() {
Une approche plutôt raisonnable de l'Unreal Engine 5
Fortement inspiré par le Airbnb Javascript Style Guide.
Ce dépôt est maintenant situé à l'adresse https://github.com/Allar/ue5-style-guide. La branche par défaut de ce dépôt a été renommée en main
.
Une documentation plus technique concernant Linter et le guide de style peut être trouvée sur notre page ReadTheDocs.
Gamemakin LLC dispose d'un channel public Discord à l'adresse http://discord.gamemak.in avec un canal #linter si vous souhaitez discuter de tout ce qui concerne le guide de style et le plugin Linter.
Chaque section de ce guide de style est numérotée pour faciliter les références et les liens. Vous pouvez créer un lien direct vers n'importe quelle section en ajoutant simplement une balise dièse et le numéro de la section à la fin de http://ue4.style.
Par exemple, si vous voulez envoyer quelqu'un au premier paragraphe de ce guide de style, vous devez ajouter #0.1
, ce qui donne http://ue4.style#0.1.
Si vous avez créé un fork ou une traduction notable qui ne peut pas faire l'objet d'une demande de transfert dans ce dépôt, veuillez soumettre une pull request pour ajouter le fork ou la traduction ici.
- Traduction coréenne par ymkim50
- Traduction en russe par CosmoMyzrailGorynych
- Traduction japonaise par akenatsu
- Traduction en chinois par Beijing Skylens Tech
- Traduction Portugais Brésilien par danlvr
- Traduction française par Arnaud58
Le mot "Carte" (map) fait référence à ce qui est communément appelé "niveau" (level) dans UE4, et les deux termes sont synonymes. Voir l'historique de ce terme ici.
Un Identifiant
est tout ce qui sert de "nom". Par exemple le nom d'un asset, d'un matériau, d'une propriété de blueprint, d'une variable, un nom de dossier, de ligne de table de données, etc....
Il y a plusieurs façons différentes dont vous pouvez NoterLesMotsQuandNommer
. Voici quelques types de casses courantes :
Met une majuscule à chaque mot et supprime tous les espaces, par exemple
DesertEagle
,GuideDeStyle
,UneSerieDeMots
.La première lettre est toujours en minuscule mais tous les mots suivants commencent par une majuscule, par exemple
desertEagle
,guideDeStyle
,uneSerieDeMots
.Les mots peuvent commencer arbitrairement en majuscules ou en minuscules mais les mots sont séparés par un trait de soulignement, par exemple
desert_Eagle
,Guide_De_Style
,une_Serie_de_Mots
.
Dans la plupart des contextes, les mots "variable" et "propriété" sont interchangeables. S'ils sont tous deux utilisés ensemble dans le même contexte cependant :
Fait généralement référence à une variable définie dans une classe. Par exemple, si BP_Tonneau
avait une variable bExploser
, bExploser
peut être désigné comme une propriété de BP_Tonneau
.
Dans le contexte d'une classe, il est souvent utilisé pour préciser l'accès à des données définies précédemment.
Fait généralement référence à une variable définie comme un argument de fonction ou une variable locale à l'intérieur d'une fonction.
Lorsqu'il est dans le contexte d'une classe, il est souvent utilisé pour transmettre une information sur sa définition et sur son type.
Ces principes ont été adaptés du guide de style idomatic JS.
Si vous travaillez sur un projet ou avec une équipe qui a un guide de style préexistant, il faut le respecter. En cas d'incohérence entre un guide de style existant et le présent guide, il convient de s'en remettre au guide existant.
Les guides de style doivent être des documents évolutifs. Vous devez proposer des changements de style à un guide de style existant ainsi qu'à ce guide si vous pensez que le changement est bénéfique pour tous le monde.
0.2 L'ensemble de la structure, des assets et du code de tout projet Unreal Engine 4 doit donner l'impression qu'une seule personne l'a créé, peu importe le nombre de personnes qui y ont contribué.
Passer d'un projet à un autre ne devrait pas entraîner un réapprentissage du style et de la structure. Le fait de se conformer à un guide de style élimine les approximations et les ambiguïtés inutiles.
Elle permet également une création et une maintenance plus productives, car il n'est pas nécessaire de réfléchir au style. Il suffit de suivre les instructions. Ce guide de style est écrit en tenant compte des meilleures pratiques, ce qui signifie qu'en suivant ce guide de style, vous minimiserez également les problèmes difficiles de maintenance de code.
Si vous voyez quelqu'un travailler soit contre un guide de style, soit sans guide de style, essayez de le corriger.
Lorsque vous travaillez au sein d'une équipe ou discutez au sein d'une communauté telle que Unreal Slackers, il est bien plus facile d'aider et de demander de l'aide lorsque les gens sont cohérents. Personne n'aime aider à démêler les spaghettis d'un Blueprint de quelqu'un d'autre ou de s'occuper d'assets dont les noms sont incompréhensibles.
Si vous aidez quelqu'un dont le travail est conforme à un guide de style différent mais cohérent et sain, vous devriez pouvoir vous y adapter. S'ils ne se conforment à aucun guide de style, veuillez les diriger ici.
Lorsque vous rejoignez une équipe Unreal Engine 4, l'une de vos premières questions devrait être "Avez-vous un guide de style ?". Si la réponse est non, vous devriez être sceptique quant à leur capacité à travailler en équipe.
Gamemakin LLC n'est pas un avocat, mais s'il vous plaît, n'introduisez pas d'actions et de comportements illégaux dans un projet, y compris mais sans s'y limiter :
- Ne distribuez pas de contenu dont vous n'avez pas les droits
- N'enfreignez pas les droits d'auteur ou les marques déposées de quelqu'un d'autre
- Ne pas voler de contenu
- Respecter les restrictions de licence sur le contenu, par exemple, citer quand les citations sont requises
@TODO : Faire de cette section 1 et mettre à jour ce document en conséquence. ou pas ?
Dans tout Identifiant
de quelque nature que ce soit, ne jamais utiliser les éléments suivants, à moins d'y être absolument contraint :
- Espace blanc de quelque nature que ce soit
- Des barres obliques inversées
- Symboles, par exemple
#!@$%
- Tout caractère Unicode
Tout Identifiant
devrait s'efforcer de n'avoir que les caractères suivants lorsque cela est possible (RegEx [A-Za-z0-9_]+
)
- ABCDEFGHIJKLMNOPQRSTUVWXYZ
- abcdefghijklmnopqrstuvwxyz
- 1234567890
- _ (avec parcimonie)
Le raisonnement est le suivant : cela assurera la plus grande compatibilité de toutes les données sur toutes les plateformes à travers tous les outils, et aidera à prévenir les temps d'arrêt dus à une manipulation de caractères potentiellement mauvaise pour les identifiants dans le code que vous ne contrôlez pas.
Les conventions de nommage doivent être traitées comme des lois. Un projet qui se conforme à une convention de nommage est capable de gérer, rechercher, analyser et maintenir ses ressources avec une facilité incroyable.
La plupart des noms sont préfixées, les préfixes étant généralement un acronyme du type d'asset suivi d'un trait de soulignement.
Tous les assets doivent avoir un Nom de base. Un nom de base représente un regroupement d'assets apparentés. Tout assets faisant partie de ce groupe doit respecter la norme duPrefix_NomBaseAsset_Varient_Suffix
.
Le bon sens et le modèle Prefix_NomBaseAsset_Varient_Suffix
est généralement suffisant pour s'assurer de créer un bon nom d'asset. Voici quelques règles détaillées concernant chaque élément.
Le Préfixe
et le Suffixe
doivent être déterminés par le type d'asset à travers les tableaux suivantes Modificateurs de Nom d'Asset.
NomBaseAsset
doit être un nom court et facilement reconnaissable lié au contexte de ce groupe d'asset. Par exemple, si vous avez un personnage nommé Bob, tous les asset de Bob auront pour NomBaseAsset
Bob
.
Pour les variations uniques et spécifiques des assets, Varient
est un nom court et facilement reconnaissable qui représente un regroupement d'assets qui sont un sous-ensemble du nom de base d'un asset. Par exemple, si Bob a plusieurs skins, ces skins doivent toujours utiliser Bob
comme NomBaseAsset
mais inclure une Varient
facilement reconnaissable. Un skin "Evil" sera appelé "Bob_Evil" et un skin "Retro" sera appelé "Bob_Retro".
Pour les variations uniques mais génériques des ressources, Varient
est un nombre à deux chiffres commençant par 01
. Par exemple, si vous avez un artiste d'environnement qui génère des rochers, ils seront nommés Rock_01
, Rock_02
, Rock_03
, etc. À part de rares exceptions, vous ne devriez jamais avoir besoin d'un numéro de varient à trois chiffres. Si vous avez plus de 100 assets, vous devriez envisager de les organiser avec des noms de base différents ou d'utiliser plusieurs noms de varients.
Selon la façon dont vos varients d'assets sont créées, vous pouvez enchaîner les noms de variantes. Par exemple, si vous créez des ressources de revêtement de sol pour un projet Arch Viz, vous devriez utiliser le nom de base Flooring
avec des variantes enchaînées telles que Flooring_Marble_01
, Flooring_Maple_01
, Flooring_Tile_Squares_01
.
Type d'Asset | Nom de l'Asset |
---|---|
Skeletal Mesh | SK_Bob |
Materiaux | M_Bob |
Texture (Diffuse/Albedo) | T_Bob_D |
Texture (Normal) | T_Bob_N |
Texture (Evil Diffuse) | T_Bob_Evil_D |
Type d'Asset | Nom de l'Asset |
---|---|
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 |
Lorsque vous nommez un asset, utilisez ces tableaux pour déterminer le préfixe et le suffixe à utiliser avec le nom de base des assets.
1.2.1 Les Plus Courant
1.2.2 Animations
1.2.4 Blueprints
1.2.5 Matériaux
1.2.6 Textures
1.2.7 Divers
1.2.8 Paper 2D
1.2.9 Physique
1.2.10 Sons
1.2.11 Interface utilisateur
1.2.12 Effets
Type d'Asset | Préfixe | Suffixe | Notes |
---|---|---|---|
Level / Map | Devrait se trouver dans un dossier appelé Maps ou Levels | ||
Level (Persistent) | _P | ||
Level (Audio) | _Audio | ||
Level (Lighting) | _Lighting | ||
Level (Geometry) | _Geo | ||
Level (Gameplay) | _Gameplay | ||
Blueprint | BP_ | ||
Material | M_ | ||
Static Mesh | S_ | Beaucoup utilise SM_ Nous utilisons S_ | |
Skeletal Mesh | SK_ | ||
Texture | T_ | _? | Voir Textures |
Particle System | PS_ | ||
Widget Blueprint | WBP_ |
Type d'Asset | Préfixe | Suffixe | Notes |
---|---|---|---|
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_ | ||
Skeletal Mesh | SK_ | ||
Skeleton | SKEL_ |
Type d'Asset | Préfixe | Suffixe | Notes |
---|---|---|---|
AI Controller | AIC_ | ||
Behavior Tree | BT_ | ||
Blackboard | BB_ | ||
Decorator | BTDecorator_ | ||
Service | BTService_ | ||
Task | BTTask_ | ||
Environment Query | EQS_ | ||
EnvQueryContext | EQS_ | Context |
Type d'Asset | Préfixe | Suffixe | Notes |
---|---|---|---|
Blueprint | BP_ | ||
Blueprint Component | BP_ | Component | Voir BP_InventoryComponent |
Blueprint Function Library | BPFL_ | ||
Blueprint Interface | BPI_ | ||
Blueprint Macro Library | BPML_ | N'utilisez pas de bibliothèques de macro si possible | |
Enumeration | E | Pas d'underscore | |
Structure | F or S | Pas d'underscore | |
Tutorial Blueprint | TBP_ | ||
Widget Blueprint | WBP_ |
Type d'Asset | Préfixe | Suffixe | Notes |
---|---|---|---|
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 |
Type d'Asset | Préfixe | Suffixe | Notes |
---|---|---|---|
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_ | _* | Voir notes à propos du Regroupement. |
Texture Cube | TC_ | ||
Media Texture | MT_ | ||
Render Target | RT_ | ||
Cube Render Target | RTC_ | ||
Texture Light Profile | TLP |
Il est courant de regrouper plusieurs couches de données d'un matériau dans une seule texture. Par exemple, l'ajout de l'Émissive (Emissive), de la Rugosité (Roughness) et de l'Occlusion ambiante (Ambient Occlusion) en tant que canaux rouge, vert, bleu d'une texture. Pour déterminer le suffixe, il suffit d'empiler les lettres des suffixe données ci-dessus, par exemple _ERO
.
Il est généralement acceptable d'inclure une couche Alpha/Opacité dans le canal alpha de votre Diffuse/Albedo et comme c'est une pratique courante, l'ajout de
A
au suffixe_D
est facultatif.
Il n'est pas recommandé d'inclure 4 canaux de données dans une texture (RGBA), à l'exception d'un masque Alpha/Opacité dans le canal alpha du Diffuse/Albedo, car une texture avec un canal alpha est plus couteuse qu'une texture sans canal alpha.
Type d'Asset | Préfixe | Suffixe | Notes |
---|---|---|---|
Animated Vector Field | VFA_ | ||
Camera Anim | CA_ | ||
Color Curve | Curve_ | _Color | |
Curve Table | Curve_ | _Table | |
Data Asset | *_ | Le préfixe doit être basé sur la classe | |
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 | Devraient être réparés dès que possible | ||
Sprite Sheet | SS_ | ||
Static Vector Field | VF_ | ||
Substance Graph Instance | SGI_ | ||
Substance Instance Factory | SIF_ | ||
Touch Interface Setup | TI_ | ||
Vector Curve | Curve_ | _Vector |
Type d'Asset | Préfixe | Suffixe | Notes |
---|---|---|---|
Paper Flipbook | PFB_ | ||
Sprite | SPR_ | ||
Sprite Atlas Group | SPRG_ | ||
Tile Map | TM_ | ||
Tile Set | TS_ |
Type d'Asset | Préfixe | Suffixe | Notes |
---|---|---|---|
Physical Material | PM_ | ||
Physics Asset | PHYS_ | ||
Destructible Mesh | DM_ |
Type d'Asset | Préfixe | Suffixe | Notes |
---|---|---|---|
Dialogue Voice | DV_ | ||
Dialogue Wave | DW_ | ||
Media Sound Wave | MSW_ | ||
Reverb Effect | Reverb_ | ||
Sound Attenuation | ATT_ | ||
Sound Class | Pas de préfixe/suffixe. Doit être placé dans un dossier appelé SoundClasses | ||
Sound Concurrency | _SC | Doit être nommé d'après une SoundClasses | |
Sound Cue | A_ | _Cue | |
Sound Mix | Mix_ | ||
Sound Wave | A_ |
Type d'Asset | Préfixe | Suffixe | Notes |
---|---|---|---|
Font | Font_ | ||
Slate Brush | Brush_ | ||
Slate Widget Style | Style_ | ||
Widget Blueprint | WBP_ |
Type d'Asset | Préfixe | Suffixe | Notes |
---|---|---|---|
Particle System | PS_ | ||
Material (Post Process) | PP_ |
⬆ Retourner à la table des matières
Tout aussi important que les noms des assets, la manière de structurer le répertoire d'un projet doit être considéré faisant preuve de loi. Les conventions de nommage des assets et la structure des répertoires vont de pair, et une violation de l'une ou l'autre provoque un chaos important.
Il existe plusieurs façons de répartir le contenu d'un projet UE5. Dans ce style, nous préférons ici utilisé les capacités de filtrage et de recherche du navigateur de contenu afin de trouver des assets d'un type spécifique plutôt qu'une structure qui regroupe les assets de même types dans un même dossier.
Si vous utilisez la préfixation comme ci-dessus, utiliser des dossiers qui contiennet des assets de types similaires tels que
Meshes
,Textures
etMatériaux
est redondant car les types d'asset sont déjà à la fois triés par préfixe et peuvent être filtrés par le navigateur de contenu.
|-- Content |-- GenericShooter |-- Art | |-- Industrial | | |-- Ambient | | |-- Machinery | | |-- Pipes | |-- Nature | | |-- Ambient | | |-- Foliage | | |-- Rocks | | |-- Trees | |-- Office |-- Characters | |-- Bob | |-- Common | | |-- Animations | | |-- Audio | |-- Jack | |-- Steve | |-- Zoe |-- Core | |-- Characters | |-- Engine | |-- GameModes | |-- Interactables | |-- Pickups | |-- Weapons |-- Effects | |-- Electrical | |-- Fire | |-- Weather |-- Maps | |-- Campaign1 | |-- Campaign2 |-- MaterialLibrary | |-- Debug | |-- Metal | |-- Paint | |-- Utility | |-- Weathering |-- Placeables | |-- Pickups |-- Weapons |-- Common |-- Pistols | |-- DesertEagle | |-- RocketPistol |-- Rifles
Les raisons de cette structure sont énumérées dans les sous-sections suivantes.
2.4 Levels
2.5 Core
Voici les règles communes pour nommer tout dossier dans la structure de contenu.
2.1.1 Toujours utiliser le PascalCase *
PascalCase consiste à commencer un nom par une majuscule, puis, au lieu d'utiliser des espaces, chaque mot suivant commence également par une majuscule. Par exemple, DesertEagle
, PistoletLaser
, et UneSerieDeMots
.
Voir Casses.
Pour renforcer 2.1.1, n'utilisez jamais d'espaces. Les espaces peuvent faire échouer divers outils d'ingénierie et de scripts. Idéalement, la racine de votre projet ne contient pas non plus d'espaces et ressemble à D:\Projet
plutot que C:\Users\Mon Nom\Mes Documents\Unreal Projects
.
Si l'un des personnages de votre jeu s'appelle 'Zoë', le nom de son dossier doit être Zoe
. Les caractères Unicode peuvent être pires que les Espaces pour les outils d'ingénierie et certaines parties de UE4 et 5 ne supportent pas non plus les caractères Unicode dans les chemins.
Dans le même ordre d'idées, si votre projet présente des problèmes inexpliqués et que le nom d'utilisateur de votre ordinateur comporte un caractère Unicode (c'est-à-dire que votre nom est Zoë
), tout projet situé dans votre dossier My Documents
souffrira de ce problème. Souvent, il suffit de déplacer votre projet dans un dossier tel que D:\Project
pour résoudre ces problèmes mystérieux.
L'utilisation de caractères autres que a-z
, A-Z
, et 0-9
tels que @
, -
, _
, ,
, *
, et #
peut également conduire à des problèmes inattendus et difficiles à suivre sur d'autres plateformes, contrôle de source, et outils d'ingénierie plus faibles.
Toutes les ressources d'un projet doivent se trouver dans un dossier portant le nom du projet. Par exemple, si votre projet s'appelle "Generic Shooter", tout son contenu doit se trouver dans Content/GenericShooter
.
Le dossier
Developers
ne contient pas les ressources sur lesquelles votre projet repose, et n'est donc pas spécifique au projet. Voir Developer Folders pour plus de détails à ce sujet.
Il y a de multiples raisons pour cette approche.
Souvent dans les guides de style de code, il est écrit qu'il ne faut pas polluer l'espace de nom global et ceci suit le même principe. Lorsque les assets sont autorisés à exister en dehors d'un dossier de projet, il devient souvent beaucoup plus difficile de faire respecter une structure stricte, car les assets qui ne sont pas dans un dossier encouragent le mauvais comportement consistant à ne pas organiser les autres assets.
Chaque assets doit avoir un objectif, sinon il n'a pas sa place dans un projet. Si un assets est un test expérimental et ne doit pas être utilisé par le projet, il doit être placé dans un dossier Developer
.
Lorsqu'on travaille sur plusieurs projets, il est courant qu'une équipe copie des assets d'un projet à l'autre si elle a réalisé quelque chose de communs aux deux. Dans ce cas, la façon la plus simple d'effectuer la copie est d'utiliser la fonction Migrer du navigateur de contenu, car elle copie non seulement la ressource sélectionnée, mais aussi toutes ses dépendances.
Ce sont ces dépendances qui vont facilement vous causer des problèmes. Si les assets de deux projets n'ont pas de dossier de niveau supérieur et qu'ils ont des assets nommés de manière similaire ou déjà migrés, une nouvelle migration peut accidentellement effacer les modifications apportées aux assets existants.
C'est également la principale raison pour laquelle le personnel du marketplace d'Epic applique la même politique aux assets soumis.
Après une migration, les ressources peuvent être fusionnées en toute sécurité à l'aide de l'outil "Remplacer les références" du navigateur de contenu, avec la précision supplémentaire que les assets n'appartenant pas au dossier de premier niveau d'un projet sont clairement en attente de fusion. Une fois les ressources fusionnées et entièrement migrées, il ne devrait plus y avoir de dossier de premier niveau dans votre arborescence de contenu. Cette méthode est garantie à 100% pour que toutes les migrations qui se produisent soient totalement sûres.
Supposons que vous ayez créé un "master material" dans un projet et que vous souhaitiez l'utiliser dans un autre projet, vous avez donc migré cet asset. Si cet asset n'est pas dans un dossier de niveau supérieur, il peut avoir un nom comme Content/MaterialLibrary/M_Master
. Si le projet cible n'a pas déjà un "master material", cela devrait fonctionner sans problème.
Au fur et à mesure que le travail sur l'un ou les deux projets progresse, leurs "master material" respectifs peuvent être modifiés pour être adaptés à leurs projets spécifiques dans le cadre d'un développement normal.
Le problème se pose lorsque, par exemple, un artiste a créé pour un projet un bel ensemble modulaire générique de static meshes et que quelqu'un souhaite inclure cet ensemble de static meshes dans le second projet. Si l'artiste qui a créé les ressources a utilisé des instances de matériaux basées sur Content/MaterialLibrary/M_Master
comme il en a reçu l'instruction, lorsqu'une migration est effectuée, il y a une grande chance de conflit pour la ressource Content/MaterialLibrary/M_Master
précédemment migrée.
Ce problème peut être difficile à prévoir et à prendre en compte. La personne qui migre les static meshes peut ne pas être la même que celle qui est familière avec le développement du "master material" des deux projets, et elle peut même ne pas être consciente que les static meshes en question reposent sur des instances de matériau qui reposent ensuite sur le "master material". L'outil Migrate a cependant besoin de toute la chaîne de dépendances pour fonctionner, et il sera donc obligé de saisir Content/MaterialLibrary/M_Master
lorsqu'il copiera ces assets vers l'autre projet et il écrasera l'asset existant.
C'est à ce moment-là que si les "master material" des deux projets sont incompatibles d'une manière ou d'une autre, vous risquez de casser toute la bibliothèque de matériaux d'un projet ainsi que toutes les autres dépendances qui ont déjà été migrées, simplement parce que les assets n'ont pas été stockés dans un dossier de niveau supérieur. La simple migration de static meshes devient maintenant une tâche très laide.
Une extension de 2.2.2, si un membre de l'équipe décide d'ajouter du contenu d'un Samples, des fichiers de Templates, ou des assets qu'ils ont achetés sur le marché, il est garanti, tant que le dossier de niveau supérieur de votre projet est nommé de manière unique, que ces nouveaux assets n'interféreront pas avec votre projet.
Vous ne pouvez pas faire confiance au contenu du Marketplace pour se conformer entièrement à la [règle du dossier de premier niveau](n° 2.2). Il existe de nombreuses ressources dont la majorité du contenu se trouve dans un dossier de premier niveau, mais qui contiennent également des échantillons de contenu Epic éventuellement modifiés ainsi que des fichiers de niveau polluant le dossier global Content
.
En adhérant à 2.2, le pire conflit du Marketplace que vous pouvez avoir est si deux assets utilisent le même Samples d'Epic. Si toutes vos ressources se trouvent dans un dossier spécifique au projet, y compris le contenu des Samples que vous avez déplacé dans votre dossier, votre projet ne sera jamais inquiété par les problèmes lié à l'importation d'assets.
Si votre projet prévoit de publier un DLC ou s'il est associé à plusieurs sous-projets qui peuvent être transférés ou simplement ne pas être inclus lors d'une compilation, les ressources relatives à ces projets doivent avoir leur propre dossier de contenu de niveau supérieur. Cela facilite grandement la compilation du DLC séparément au contenu du projet principal. Les sous-projets peuvent également être migrés vers et hors du projet avec un minimum d'effort. Si vous devez modifier le matériau d'un asset ou ajouter un comportement très spécifique de remplacement d'asset dans un patch, vous pouvez facilement placer ces modifications dans un dossier de patch et travailler en toute sécurité sans risquer de casser le projet principal.
Au cours du développement d'un projet, il est très courant que les membres de l'équipe disposent d'une sorte de "bac à sable" où ils peuvent expérimenter librement sans risquer de compromettre le projet principal. Comme ce travail peut être continu, ces membres de l'équipe peuvent souhaiter placer leurs ressources sur le serveur de contrôle des sources du projet. Toutes les équipes n'ont pas besoin d'utiliser des dossiers de développeurs, mais celles qui le font rencontrent souvent un problème commun avec les ressources soumises au contrôle de source.
Il est très facile pour un membre de l'équipe d'utiliser accidentellement des ressources qui ne sont pas prêtes à être utilisées, ce qui causera des problèmes une fois ces ressources supprimées. Par exemple, un artiste peut être en train d'itérer sur un ensemble modulaire de Static Meshes et encore en train de travailler sur la dimension et le maillage du meshe. Si un Level Designer voit ces ressources dans le dossier principal du projet, il peut les utiliser dans tout le niveau sans savoir qu'elles peuvent être modifiées et/ou supprimées. Cela entraîne une quantité massive de retravail à résoudre pour tous les membres de l'équipe.
Si ces ressources modulaires étaient placées dans un dossier de développeur, le Level Designer n'aurait jamais eu de raison de les utiliser et le problème ne se serait jamais posé. Le navigateur de contenu dispose d'options d'affichage spécifiques qui masquent les dossiers Developer (ils sont masqués par défaut), ce qui rend impossible l'utilisation accidentelle des ressources Developer dans des conditions normales.
Une fois que les ressources sont prêtes à être utilisées, il suffit à l'artiste de les déplacer dans le dossier spécifique au projet et de corriger les redirecteurs. Il s'agit essentiellement de faire passer les ressources de la phase expérimentale à la phase de production.
2.4 Tous les fichiers Levels* appartiennent à un dossier appelé Maps
Les fichiers de carte sont incroyablement spéciaux et il est courant que chaque projet ait son propre système de dénomination des cartes, surtout s'il travaille avec des sous-niveaux ou des streaming level. Quel que soit le système d'organisation des cartes mis en place pour un projet donné, tous les niveaux doivent se trouver dans le dossier /Content/Project/Maps
.
Pouvoir dire à quelqu'un d'ouvrir une carte spécifique sans avoir à expliquer où elle se trouve est un grand gain de temps et une amélioration générale de la "qualité de vie". Il est courant que les niveaux se trouvent dans des sous-dossiers de Maps
, comme Maps/Campaign1/
ou Maps/Arenas
, mais la chose la plus importante ici est qu'ils existent tous dans /Content/Project/Maps
.
Cela simplifie également le travail de construction pour les ingénieurs. La manipulation des niveaux dans un processus de construction peut être extrêmement frustrante s'ils doivent fouiller dans des dossiers arbitraires pour les trouver. Si les cartes d'une équipe se trouvent toutes au même endroit, il est beaucoup plus difficile de ne pas compiller une carte par accident lors d'un build. Cela simplifie également les scripts de construction d'éclairage ainsi que les processus d'assurance qualité.
Utilisez le dossier /Content/Project/Core
pour les actifs qui sont absolument fondamentaux pour le fonctionnement d'un projet. Par exemple, les Blueprints de base GameMode
, Character
, PlayerController
, GameState
, PlayerState
, et les Blueprints associés devraient se trouver ici.
Cela crée un message très clair "ne touchez pas à ça" pour les autres membres de l'équipe. Les non-ingénieurs devraient avoir très peu de raisons d'entrer dans le dossier Core
. En suivant le bon style de structure de code, les concepteurs devraient faire leurs modifications de gameplay dans les classes enfant qui exposent les fonctionnalités. Les Levels Designers devraient utiliser des Blueprints préfabriqués dans des dossiers désignés au lieu d'abuser potentiellement des classes de base.
Par exemple, si votre projet nécessite des collectables qui peuvent être placés dans un niveau, il devrait exister une classe de base Pickup (collectable en français) dans Core/Pickups
qui définit le comportement de base pour un collectable. Des collectables spécifiques, tels que la santé ou les munitions, devraient exister dans un dossier tel que /Content/Project/Placeables/Pickups/
. Les concepteurs de jeux peuvent définir et modifier les collectables dans ce dossier comme bon leur semble, mais ils ne doivent pas toucher à Core/Pickups
car ils pourraient involontairement casser les collectables de tout le projet.
Tous les assets sont des assets.
Tous les noms d'assets sont nommés en tenant compte du type d'asset. Ces dossiers n'offrent que des informations redondantes et l'utilisation de ces dossiers peut facilement être remplacée par le système de filtrage robuste et facile à utiliser que fournit le navigateur de contenu.
Vous voulez voir seulement les Static Mesh dans Environnement/Rocks/
? Activez simplement le filtre Static Mesh. Si tous les assets sont nommés correctement, ils seront également triés par ordre alphabétique, indépendamment des préfixes. Vous souhaitez afficher à la fois les Static Mesh et les Skeletals Meshes ? Il suffit d'activer les deux filtres. Ceci élimine le besoin de potentiellement devoir sélectionner deux dossiers dans l'arborescence du navigateur de contenu.
Cela alonge également le nom du filepath de manière inutile. Le préfixe
S_
pour un Static Mesh n'a que deux caractères, alors queMeshes/
en a sept.
Ne pas le faire permet également d'éviter que quelqu'un mette un Static Mesh ou une texture dans un dossier Materials
.
Ceci peut être considéré comme une pseudo-exception à 2.6.
Il y a certains types d'assets qui possèdent un énorme volume de fichiers liés où chaque asset a un but unique. Les deux plus cas les courants sont les assets d'animation et les assets audio. Si vous avez plus de 15 de ces ressources qui vont ensemble, elles doivent être regroupées.
Par exemple, les animations qui sont partagées par plusieurs personnages doivent être placées dans Characters/Communs/Animations
et peuvent avoir des sous-dossiers tels que Locomotion
ou Cinematic
.
Ceci ne s'applique pas aux assets tels que les textures et les matériaux. Il est courant qu'un dossier
Rocks
contienne une grande quantité de textures s'il y a une grande quantité de roches, cependant ces textures ne sont généralement liées qu'à quelques roches spécifiques et doivent être nommées de manière appropriée. Même si ces textures font partie d'une Bibliothèque de Matériaux.
Si votre projet fait usage de "master materials", de "layered materials" ou de toute forme de matériaux ou de textures réutilisables qui n'appartiennent à aucun sous-ensemble d'assets, ces assets doivent être situés dans Content/Project/MaterialLibrary
.
De cette façon, tous les matériaux "globaux" ont un endroit où vivre et sont facilement localisables.
Cela rend également très facile l'application d'une politique d'utilisation exclusive des instances de matériaux dans un projet. Si tous les assets doivent utiliser des instances de matériaux, seul des instances de matériaux peuvent exister dans ce dossier. Vous pouvez facilement vérifier cela en recherchant les matériaux de base dans n'importe quel dossier qui n'est pas
MaterialLibrary
.
Le dossier MaterialLibrary
n'est pas forcément composée uniquement de matériaux. Des textures utilitaires partagées, des "material functions" et d'autres choses de cette nature devraient être stockées ici aussi dans des dossiers qui désignent leur but. Par exemple, les textures de bruit devraient être situées dans MaterialLibrary/Utility
.
Tous les matériaux de test ou de débogage doivent se trouver dans MaterialLibrary/Debug
. Cela permet de retirer facilement les matériaux de débogage d'un projet avant de l'expédier et de voir clairement si les assets en production les utilisent en regardant si des erreurs de référence sont affichées.
Il ne devrait pas y avoir de dossiers vides. Ils encombrent le navigateur de contenu.
Si vous constatez que le navigateur de contenu contient un dossier vide que vous ne pouvez pas supprimer, procédez comme suit :
- Vérifiez que vous utilisez le contrôle des sources.
- Exécutez immédiatement "Fix Up Redirectors" sur votre projet.
- Naviguez jusqu'au dossier sur le disque et supprimez les assets qui s'y trouvent.
- Fermez l'éditeur.
- Assurez-vous que l'état de votre contrôle de source est synchronisé (par exemple, si vous utilisez Perforce, exécutez un travail hors ligne de réconciliation sur votre répertoire de contenu).
- Ouvrez l'éditeur. Confirmez que tout fonctionne comme prévu. Si ce n'est pas le cas, revenez en arrière, trouvez ce qui n'a pas fonctionné et réessayez.
- Assurez-vous que le dossier a disparu.
- Soumettre les changements au contrôle de source.
⬆ Retourner à la table des matières
Cette section se concentre sur les Blueprint et leurs éléments internes. Dans la mesure du possible, les règles de style sont conformes au Epic's Coding Standard.
N'oubliez pas : le Blueprinting supporte mal les gaffes, méfiez-vous ! (Phrase de KorkuVeren)
3.1 Compiling
3.2 Variables
3.3 Functions
3.4 Graphs
Tous les blueprints doivent être compilés sans aucun avertissement ni aucune erreur. Vous devez corriger immédiatement les avertissements et les erreurs des blueprints car ils peuvent rapidement se transformer en un comportement inattendu très effrayant.
Ne soumettez pas les blueprints cassés au contrôle de source. Si vous devez les stocker dans le contrôle de source, mettez-les plutôt en attente.
Les blueprints cassés peuvent causer des problèmes qui se manifestent d'autres manières, comme des références cassées, un comportement inattendu, des échecs de compilation et des recompilations fréquentes et inutiles. Un blueprint cassé a le pouvoir de casser votre jeu entier.
Les mots variable
et propriété
peuvent être utilisés de manière interchangeable.
3.2.1 Nommage
3.2.2 Editable
3.2.3 Catégories
3.2.4 Accès
3.2.5 Avancé
3.2.6 Temporaires
3.2.7 Config
Tous les noms de variables non booléennes doivent être des substantifs clairs, non ambigus et descriptifs.
Toutes les variables non booléennes doivent être sous la forme PascalCase.
Score
Kills
TargetPlayer
Range
CrosshairColor
AbilityID
Tous les booléens doivent être nommés en PascalCase mais préfixés par un b
minuscule.
Exemple : Utilisez bDead
et bEvil
, et non Dead
et Evil
.
Les éditeurs de Blueprint de UE4 savent qu'il ne faut pas inclure le b
dans les affichages conviviaux de la variable.
Tous les booléens doivent être nommés comme des adjectifs descriptifs lorsque cela est possible s'ils représentent des informations générales. N'incluez pas les mots qui expriment la variable comme une question, tels que Is
. Ceci est réservé aux fonctions.
Exemple : Utilisez bDead
et bHostile
et non bIsDead
et bIsHostile
.
Essayez de ne pas utiliser de verbes tels que bRunning
. Les verbes ont tendance à conduire à des états complexes.
Ne pas utiliser de booléens pour représenter des états complexes et/ou dépendants. Cela rend compliqué l'ajout et la suppression d'états et n'est pas facilement lisible. Utilisez plutôt une énumération dans ce cas là.
Exemple : Lors de la définition d'une arme, ne pas utiliser bReloading
et bEquipping
si une arme ne peut pas être à la fois rechargée et équipée. Définissez une énumération nommée EWeaponState
et utilisez plutôt une variable de ce type nommée WeaponState
. Cela rend beaucoup plus facile l'ajout de nouveaux états aux armes.
Exemple : Ne pas utiliser bRunning
si vous avez aussi besoin de bWalking
ou bSprinting
. Cela devrait être défini comme une énumération avec des noms d'états clairement définis.
Tous les noms de variables ne doivent pas être redondants avec leur contexte car toutes les références de variables dans Blueprint auront toujours un contexte.
Considérons un Blueprint appelé BP_PlayerCharacter
.
Mauvais
PlayerScore
PlayerKills
MyTargetPlayer
MyCharacterName
CharacterSkills
ChosenCharacterSkin
Toutes ces variables sont nommées de manière redondante. Il est sous-entendu que la variable est représentative du BP_PlayerCharacter
auquel elle appartient car c'est BP_PlayerCharacter
qui définit ces variables.
Bon
Score
Kills
TargetPlayer
Name
Skills
Skin
Les variables atomiques ou primitives sont des variables qui représentent des données dans leur forme la plus simple, comme les booléens, les entiers, les flottants et les énumérations.
Les chaînes de caractères et les vecteurs sont considérés comme atomiques en termes de style lorsqu'on travaille avec Blueprints, mais ils ne le sont pas techniquement.
Alors que les vecteurs sont composés de trois flottants, les vecteurs peuvent souvent être manipulés comme un tout, de même que les "Rotators".
Ne considérez pas les variables Text comme atomiques, elles cachent secrètement la fonctionnalité de localisation. Le type atomique d'une chaîne de caractères est
String
, pasText
.
Les variables atomiques ne doivent pas avoir leur nom de type dans leur nom.
Exemple : Utilisez Score
, Kills
, et Description
et non ScoreFloat
, FloatKills
, DescriptionString
.
La seule exception à cette règle est lorsqu'une variable représente "un nombre de" quelque chose à compter et lorsque l'utilisation d'un nom sans type de variable n'est pas facile à lire.
Exemple : Un générateur de clôture doit générer un nombre X de poteaux. Enregistrez X dans NumPosts
ou PostsCount
au lieu de Posts
car Posts
peut potentiellement être lu comme un tableau d'un type de variable nommé Post
.
Les variables non atomiques ou complexes sont des variables qui représentent des données comme une collection de variables atomiques. Les structures, les classes, les interfaces et les primitives au comportement caché telles que Text
et Name
répondent toutes à cette règle.
Alors qu'un tableau d'un type de variable atomique est une liste de variables, les tableaux ne modifient pas le caractère atomique d'un type de variable.
Ces variables doivent inclure leur nom de type tout en tenant compte de leur contexte.
Si une classe possède une instance d'une variable complexe, par exemple si un BP_PlayerCharacter
possède un BP_Hat
, elle doit être stockée comme type de variable sans modification de nom.
Exemple : Utilisez Hat
, Flag
, et Ability
et non MyHat
, MyFlag
, et PlayerAbility
.
Si une classe ne possède pas la variable qui est dans une variable complexe, vous devez compléter le nom avec le type de variable.
Exemple : Si une BP_Turret
a la capacité de cibler un BP_PlayerCharacter
, elle devrait stocker sa variable en tant que TargetPlayer
car dans le contexte de BP_Turret
, il devrait être clair qu'il s'agit d'une référence à un autre type de variable complexe qu'elle ne possède pas.
Les tableaux suivent les mêmes règles de dénomination que ci-dessus, mais doivent être nommés comme un nom pluriel et être préfixé de the
Exemple : Utilisez theTargets
, theHats
, et theEnemyPlayers
, et non TargetList
, HatArray
, EnemyPlayerArray
.
Toutes les variables dont on peut changer la valeur en toute sécurité afin de configurer le comportement d'un blueprint doivent être marquées comme Editable
.
Inversement, toutes les variables que l'on est psa sûres de changer ou qui ne doivent pas être exposées aux concepteurs ne doivent pas être marquées comme modifiables, à moins que pour des raisons techniques, la variable doive être marquée comme Expose On Spawn
.
Ne marquez pas arbitrairement les variables comme Editable
.
Toutes les variables Editable
, y compris celles marquées editable juste pour qu'elles puissent être marquées comme Expose On Spawn
, devraient avoir une description dans leurs champs Tooltip
qui explique comment le changement de cette valeur affecte le comportement du blueprint.
Toutes les variables Editable
devraient utiliser un curseur et une plage de valeurs s'il y a une valeur qui ne devrait pas être définie pour cette variable.
Exemple : Si un blueprint qui génère des poteaux de clôture a une variable éditable PostsCount
, cela n'aurait pas de sens de pouvoir lui donner une valeur de -1. Utilisez le champ plage pour définir 0 comme valeur minimale.
Si la variable modifiable est utilisée dans un script de construction, il convient de définir une plage de curseurs appropriée afin d'éviter de définir accidentellement une valeur si grande qu'elle fait planter l'éditeur.
Une plage de valeurs ne doit être définie que si les limites de la valeur sont connues. La plage de valeurs du curseur empêche la saisie accidentelle d'un trop grand nombre de valeurs, mais une plage de valeurs non définies peut être utilisée pour spécifier des valeurs en dehors de la plage du curseur. Cette valeur est considérée comme "dangereuse" mais elle est toujours valable.
Si une classe comporte un petit nombre de variables, l'utilisation de catégories n'est pas obligatoire.
Si une classe a un nombre modéré de variables (5-10), toutes les variables Editable
se verront attribuer une catégorie autre que celle par défaut. Une catégorie commune à assigner est Config
.
Si une classe a un grand nombre de variables, toutes les variables éditables
doivent être classées en sous-catégories en utilisant la catégorie Config
comme catégorie de base. Les variables non modifiables doivent être classées dans une catégorie descriptive décrivant leur utilisation.
Les sous-catégories peuvent être définies en utilisant le caractère pipe
|
. c'est-à-direConfig | Animations
.
Exemple : Une configuration variable pour une classe d'arme peut être structurée comme suit :
|-- Config
| |-- Animations
| |-- Effects
| |-- Audio
| |-- Recoil
| |-- Timings
|-- Animations
|-- State
|-- Visuals
En C++, les variables ont le concept de niveaux d'accès. Public signifie que du code extérieur à la classe peut accéder à la variable. Protégé signifie que seule la classe et toutes les classes filles peuvent accéder à cette variable en interne. Privé signifie que seule cette classe et aucune classe enfant n'a accès à cette variable.
Les Blueprints ne définissent pas actuellement le concept de contrôle de l'accès à Protected.
Les variables Editable
sont traitées comme des variables publiques. Traiter les variables non éditables comme des variables protégées.
Ne marquez pas une variable comme privée à moins qu'elle ne soit utilisée uniquement au sein de la classe dans laquelle elle est définie et qu'elle ne soit pas utilisé dans une classe enfant. Gardez les variables privées jusqu'à ce qu'elles soient marquées protégées
, ceci est à faire quand vous savez absolument que vous voulez restreindre leur utilisation aux classes enfants.
Si une variable est Editable
, mais que vous ne changez pas souvent sa valeur, vous devriez cocher la case Advanced Display
. La variable sera ainsi masquée, sauf si vous cliquez sur la flèche d'affichage étendu.
Pour rechercher l'option Advanced Display
, elle apparaîtra dans la liste détaillée des variables en tant que Advanced Display
.
Une variable temporaire est une variable qui a une valeur initiale à zéro ou null, sans qu'il soit nécessaire de sauvegarder et de charger la valeur. Ceci est utile pour les références à d'autres objets ou acteurs dont les valeurs ne sont pas connues avant l'exécution. Cela empêche l'éditeur d'enregistrer cette référence et accélère l'enregistrement et le chargement des classes Blueprint.
Pour cette raison, toutes les variables temporaires doivent toujours être initialisées à zéro ou à une valeur nulle. Sinon, il sera difficile de déboguer les erreurs.
L'indicateur Config Variable
ne doit pas être utilisé. Celà rend difficile pour le concepteur de contrôler le comportement du blueprint. Les variables de configuration ne doivent être utilisées en C++ que pour les variables qui sont rarement modifiées. Considérez-les comme des variables d'affichage très très avancé
.
Cette section décrit comment créer des fonctions, des événements et des réparsiteurs d'événements. Sauf indication contraire, tout ce qui s'applique aux fonctions s'applique également aux événements.
La dénomination des fonctions, des événements et des répartiteurs d'événements est très importante. En vous basant uniquement sur le nom, vous serez en mesure de faire quelques prédictions sur la fonction. Par exemple :
- S'agit-il d'une fonction pure ?
- Obtient-il des informations sur l'État ?
- C'est un manipulateur ?
- S'agit-il d'un RPC ?
- Quel est son objectif ?
Tant que la fonction est correctement nommée, toutes ces questions peuvent trouver une réponse.
3.3.1.1 Toutes les fonctions doivent être des verbes ! #
Toutes les fonctions et tous les événements effectuent une action, comme récupérer des informations, calculer des données ou faire exploser quelque chose. Par conséquent, toutes les fonctions doivent commencer par un verbe. Ils doivent être aussi verbeux que possible pour le moment. Ils devraient également avoir un certain contexte quant à ce que la fonction fait.
La fonction OnRep
, les gestionnaires d'événements et les répartiseurs d'événements sont des exceptions à cette règle.
De bons exemples :
Fire
- Bon exemple pour les classes de personnages et d'armes, car il correspond au contexte dans lequel elle se trouve ; Mauvais exemple pour les classes Barrel/Grass et autres classes ambiguës.Jump
- Bon exemple si dans une classe de personnage, sinon le contexte est nécessaire.Explode
ReceiveMessage
SortPlayerArray
GetArmOffset
GetCoordinates
UpdateTransforms
EnableBigHeadMode
IsEnemy
- "Is" est un verbe.
Des mauvais exemple :
Dead
- Est-il mort ? Vous êtes sur le point de mourir ?Rock
- Est-ce un rocher ?ProcessData
- Vague, ces mots ne veulent rien dire.PlayerState
- Le nom est ambigu, ces mots ne veulent rien dire.Color
- Verbe sans contexte, substantif ambigu.
Toutes les fonctions qui sont répliquées dans une variable de notification doivent être de la forme OnRep_Variable
. Ceci est appliqué par l'éditeur de Blueprint. Cependant, si vous avez écrit une fonction C++ OnRep
, vous devez suivre cette règle lorsque vous la publiez dans les Blueprints.
3.3.1.3 Les fonctions d'information qui retournent Bool doivent être sous forme de questions ! #
Lorsqu'on écrit une fonction qui ne change pas l'état, ne met à jour aucun objet, mais récupère simplement une information, un état ou un oui/non pour un bool, elle doit être sous forme de question. En même temps, il doit suivre les règles des verbes.
C'est très important, car s'il ne s'agit pas d'une question, vous pouvez supposer que la fonction exécute une action et renvoie le résultat de cette action, qu'elle soit réussie ou non.
De bons exemples :
IsDead
IsOnFire
IsAlive
IsSpeaking
IsHavingAnExistentialCrisis
IsVisible
HasWeapon
- "Has" est un verbe.WasCharging
- "Was" est le passé de "be". Use "was" when referring to 'previous frame' or 'previous state'.CanReload
- "Can" est un verbe.
Des mauvais exemple :
Fire
- Est-il en feu ? Renvoyer quelqu'un ? Brûler ?OnFire
- peut être confondu avec le répartiteur d'événements pour la mise à feu.Dead
- Est-il mort ? Est-il sur le point de mourir ?Visibility
- Visible ? Rendre visible ? Description des conditions de vol ?
Les gestionnaires d'événements et les fonctions telles que les répartiteurs d'événements doivent commencer par On
, et le reste doit suivre les règles des verbes. Cependant, il peut être préférable de déplacer le verbe à la fin si cela se lit bien comme une phrase passée.
Les verbes de liaison du mot "On" ne sont pas soumis aux règles des verbes.
L'utilisation de Handle
n'est pas autorisée. Dans Unreal', utilisez
Onau lieu de
Handle, mais dans d'autres frameworks, il peut être préférable d'utiliser
Handleau lieu de
On`.
De bons exemples :
OnDeath
- une phrase de concaténation de jeu communeOnPickup
OnReceiveMessage
OnMessageRecieved
OnTargetChanged
OnClick
OnLeave
Des mauvais exemple :
OnData
OnTarget
HandleMessage
HandleDeath
Chaque fois que vous créez un RPC, il doit être préfixé par Server
, Client
, ou Multicast
. Il n'y a pas d'exception.
Après le préfixe, toutes les autres règles de dénomination des fonctions doivent être respectées.
De bons exemples :
ServerFireWeapon
ClientNotifyDeath
MulticastSpawnTracerEffect
Des mauvais exemple :
FireWeapon
- N'indique aucun type de RPC.ServerClientBroadcast
- Confusion.AllNotifyDeath
- UtilisezMulticast
, jamaisAll
.ClientWeapon
- Pas un verbe, ambiguë.
Le nœud de retour est requis pour toutes les fonctions. Il n'y a pas d'exception.
Dans un monde où les Blueprints sont remplis de nœuds Sequence
, ForLoopWithBreak
, et backward reroute, un flux d'exécution explicite est important pour la lisibilité, la maintenance, et la facilité de débogage. Le flux est important pour la lisibilité, la maintenance et la facilité de débogage.
Le compilateur Blueprint peut suivre le flux d'exécution et, avec le nœud Return, il avertit s'il y a un retour non géré ou un mauvais flux dans une branche du code.
Des erreurs accidentelles dans le flux de code peuvent se produire dans des situations où le programmeur ajoute une clause for, ou ajoute une logique après la fin de la boucle for, provoquant le retour prématuré de l'itération de la boucle. Les avertissements du compilateur Blueprint vous alerteront immédiatement sur tous ces problèmes.
Tout d'abord, une fonction ne doit pas comporter plus de 50 nœuds. Une fonction aussi importante doit être divisée en plusieurs fonctions plus petites pour des raisons de lisibilité et de facilité de maintenance.
Les nœuds énumérés ci-dessous ne comptent pas, car ils n'ajoutent pas de complexité à la fonction :
- Comment
- Route
- Cast
- Getting a Variable
- Breaking a Struct
- Function Entry
- Self
Cette règle s'applique à de nombreux plans publics ou du marché. Par conséquent, si cette règle est respectée, l'utilisateur de l'API blueprint pourra l'utiliser plus facilement, guidé par la description.
Simplement, les fonctions dont la spécification d'accès est définie comme publique doivent avoir une description complète de leur fonctionnement, etc.
3.3.5 Toutes les fonctions statiques personnalisées du plugin BlueprintCallable
doivent être classées par nom de plugin
Si votre projet contient des fonctions définies static
et BlueprintCallable
, comme des plugins, alors leur catégorie doit être définie comme le nom du plugin ou une catégorie de sous-ensemble du nom du plugin.
Par exemple, Zed Camera Interface
ou Zed Camera Interface | Image Capturing
.
((Exposer les éléments de gameplay aux Blueprints))
Cette section décrit les problèmes qui s'appliquent à tous les Blueprint graphs.
Positionnez les fils de manière à ce que les points de départ et d'arrivée soient clairs. Pas la peine de démêler les fils dans votre tête pour comprendre le graphe. Dans les sections suivantes, nous consacrons une grande partie du document à la réduction des spaghettis.
Vous devez toujours aligner les fils, et non les nœuds. Vous ne pouvez pas toujours contrôler la taille et la position des nœuds, mais vous pouvez toujours contrôler la position des nœuds et donc des fils. Une ligne droite de fils rend le flux plus facile à suivre. Vous pouvez redresser le fil en sélectionnant le nœud et en utilisant la commande "Straigten Connections" (Touche de raccourci : Q).
Bon exemple : le haut du nœud a été déplacé pour que la ligne blanche du fil conducteur reste droite :
Mauvais exemple : les sommets des nœuds sont alignés, mais les lignes blanches des fils conducteurs sont inégales et ondulées :
Exemple acceptable : certains nœuds peuvent ne pas fonctionner correctement quelle que soit la façon dont vous utilisez l'outil d'alignement. Dans ces situations, rapprochez les nœuds les uns des autres pour minimiser l'ondulation :
Lorsqu'on a le choix entre redresser un fil d'exécution blanc et redresser un fil de données, il faut redresser le fil d'exécution blanc.
Les blocs de nœuds doivent être entourés de nœuds de commentaires décrivant leur comportement général. Afin de rendre les nœuds individuels lisibles et compréhensibles, toutes les fonctions devraient être mieux nommées, et chaque groupe de nœuds qui sert un objectif devrait avoir son objectif décrit dans un bloc de commentaires. Si une fonction ne comporte pas beaucoup de blocs de nœuds, et s'il est clair que les nœuds fournissent directement l'objectif de la fonction, alors le nom de la fonction et sa description sont suffisants, et aucun commentaire n'est nécessaire.
Si vous supposez que l'intégration d'une fonction ou d'un événement est toujours réussie, vous devez signaler correctement l'échec de la logique lorsque l'intégration échoue. Cela indique aux autres ce qui s'est passé, c'est-à-dire que ce qui est "censé fonctionner" a échoué. Si une référence de distribution est connue pour avoir le potentiel d'échouer une distribution, la fonction doit essayer de se rétablir normalement même après une erreur de cast.
Cela ne signifie pas que chaque nœud de distribution doit traiter cette erreur. Dans de nombreux cas, notamment en cas de collisions, une erreur de distribution entraîne la fin du flux d'exécution de manière élégante.
Chaque nœud de chaque graphe Blueprint doit avoir un but. Les nœuds de plan directeur qui traînent et qui n'ont pas d'utilité ou qui ne sont pas exécutés ne doivent pas être conservés.
⬆ Retourner à la table des matières
Cette section se concentre sur les Static Meshes et leurs composants internes.
4.1 UVs
4.2 LODs
4.5 Échelle correcte
Si Linter rapporte des UVs incorrects et que vous ne pouvez pas en trouver la cause, ouvrez le fichier .log
dans le dossier Saved/Logs
de votre projet et trouvez la raison exacte de l'échec. Je vais essayer d'inclure ces messages dans les prochains rapports Lint.
C'est très simple. Quelle que soit la façon dont vous l'utilisez, chaque maillage doit avoir des UV.
4.1.2 Les UV de tous les Meshes ne doivent pas se chevaucher car ils sont également utilisés pour les Lightmaps
C'est très simple. Tous les Meshes doivent avoir des UV valides et sans chevauchement, quelle que soit la façon dont ils sont utilisés.
((Création et utilisation des LODs))
Il s'agit d'une vérification subjective de base pour chaque projet, mais en règle générale, vous devez définir des LOD approprié pour les meshes qui sont affichés à des distances proches et lointaines.
Il s'agit d'une vérification subjective de base par asset, mais les assets sans socket d'un module doivent s'adapter parfaitement aux paramètres de la grille du projet.
La décision de s'adapter à une grille de puissances de 2 ou à une grille de 10 unités est laissée à l'appréciation du projet. Toutefois, lors de la création de ressources sans module pour le Marketplace, Epic exige que l'adaptation soit nette si la grille est définie sur plus de 10 unités.
Qu'un asset soit utilisé ou non pour la collision dans un niveau, tous les meshes doivent avoir un réglage de collision approprié. Cela aidera le moteur UE4 lors du calcul des limites, de l'occlusion, de l'éclairage, etc. Les collisions doivent également correspondre aux meshes.
Il s'agit d'une vérification subjective de base par projet, mais tous les assets doivent être correctement mis à l'échelle pour le projet. Le concepteur de niveau ou l'auteur du plan n'a pas besoin d'ajuster l'échelle du maillage pour le voir dans l'éditeur. Les meshes de mise à l'échelle du moteur doivent être traités comme un remplacement d'échelle, et non comme une correction d'échelle.
⬆ Retourner à la table des matières
Cette section se concentre sur les Niagara et leurs composants internes.
Comme mentionné dans 00.1 Identifiants interdits, les espaces et tous les caractères d'espace blanc sont interdits dans les identifiants. Cela est particulièrement vrai pour les systèmes Niagara, car cela rend le travail nettement plus difficile, voire impossible, lorsque l'on travaille avec HLSL ou d'autres script dans Niagara et que l'on essaie de référencer un identifiant.
(Contribution originale par @dunenkoff)
⬆ Retourner à la table des matières
Voir Niveaux/Cartes pour les termes clés à propos des "niveaux" et des "cartes".
Cette section se concentre sur les Levels et leurs composants internes.
Tous les niveaux doivent être chargés sans erreur ni avertissement. Si un niveau contient des erreurs ou des avertissements, il doit être corrigé immédiatement pour éviter les problèmes en cascade.
Vous pouvez vérifier la carte du niveau que vous avez ouvert dans l'éditeur en utilisant la commande "map check" dans la console.
Note : Linter est plus strict que le contrôle de l'éditeur actuel. Il rattrapera toutes les erreurs de chargement que l'éditeur résout lui-même.
Au cours du développement, il peut arriver que les niveaux ne comportent pas d'éclairage, ce qui n'est pas grave. Cependant, s'il s'agit de distributions, de constructions de test/interne/expédition ou d'autres constructions, vous devez toujours faire une construction d'éclairage.
Le niveau doit éliminer les z-combats dans toutes les zones visibles par le joueur.
Si vous souhaitez vendre votre projet sur la place de marché UE4, vous devez respecter les règles suivantes
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 Epic's guidelines.
For example, InteractionComponent_Overview
.
Si votre projet contient des assets qui doivent être visualisés ou montrés, il est obligatoire de créer une carte nommée "Overview" dans votre projet.
Cette carte "Overview" sera utilisée si les assets sont visualisés dans les directives d'Epic. submission-guidelines-preparing-your-assets#Required%20Levels%20and%20Maps).
Par exemple, InteractionComponent_Overview
.
⬆ Retourner à la table des matières
Cette section se concentre sur les Textures et leurs composants internes.
Toutes les textures, à l'exception des textures d'interface utilisateur, doivent avoir une puissance de deux dans leurs dimensions. En outre, les textures ne doivent pas nécessairement être carrées.
Par exemple, 128x512
, 1024x1024
, 2048x1024
, 1024x2048
, 1x512
.
Toutes les textures doivent être dimensionnées pour convenir à leur cas d'utilisation standard. La densité de texture appropriée varie d'un projet à l'autre, mais toutes les textures d'un même projet doivent avoir une densité constante.
Par exemple, si la densité de texture du projet est de 8 pixels par unité, alors la texture appliquée à un cube de 100x100 unités devrait être de 1024x1024, soit une puissance de 2, la plus proche de la densité de texture du projet.
À moins qu'il n'y ait une raison très explicite, les textures ne devraient pas être plus grandes que 8192. Dans de nombreux cas, l'utilisation de textures plus grandes que cela est simplement un gaspillage de ressources.
Chaque texture possède une propriété de groupe de textures qui est utilisée pour les LODs. Et il doit être réglé correctement en fonction de l'utilisation. Par exemple, toutes les textures de l'interface utilisateur doivent appartenir au groupe des textures de l'interface utilisateur.
⬆ Retourner à la table des matières
Copyright (c) 2016 Gamemakin LLC
Voir LICENSE
⬆ Retourner à la table des matières
Nous vous recommandons de forker ce guide et de modifier les règles pour les adapter au guide de style de votre équipe. Vous pouvez suggérer des modifications au guide de style ci-dessous. Cela permettra de s'assurer qu'il n'y a pas de conflits lors de la fusion, et que le guide de style est mis à jour régulièrement.