Unreal Engine Best Practices and Coding Standards
unreal-enginegame-developmentcoding-standardsperformancetesting
Description
Comprehensive best practices and coding standards for Unreal Engine projects. Covers code organization, performance, security, testing, and common pitfalls to ensure maintainable, efficient, and robust game development.
Globs
**/*.{h,cpp,uasset,umap,ini}
---
description: Comprehensive best practices and coding standards for Unreal Engine projects. Covers code organization, performance, security, testing, and common pitfalls to ensure maintainable, efficient, and robust game development.
globs: **/*.{h,cpp,uasset,umap,ini}
---
# Unreal Engine Best Practices and Coding Standards
This document outlines best practices and coding standards for Unreal Engine projects. Following these guidelines will help ensure maintainability, efficiency, and robustness.
## 1. Code Organization and Structure
### 1.1 Directory Structure
* **`Source/`:** Contains all C++ source code.
* **`[GameName]/`:** Root directory for your game's code.
* **`Public/`:** Header files (.h) for classes and components.
* **`Private/`:** Implementation files (.cpp).
* **`[Feature]/`:** Subdirectories for specific game features (e.g., `Inventory`, `AI`, `UI`).
* **`Core/`:** Classes and functions shared across the project.
* **`UMG/`**: Code related to Unreal Motion Graphics (UI)
* **`Content/`:** Contains all assets (meshes, textures, materials, blueprints, etc.).
* **`[GameName]/`:** Root directory for your game's content.
* **`Characters/`:** Character assets.
* **`Environments/`:** Environment assets (meshes, textures, materials).
* **`UI/`:** User interface assets.
* **`Blueprints/`:** Blueprint classes and scripts.
* **`Materials/`:** Material assets.
* **`Textures/`:** Texture assets.
* **`Audio/`:** Audio assets.
* **`Animations/`:** Animation assets.
* **`Config/`:** Configuration files (e.g., `DefaultGame.ini`, `DefaultEngine.ini`).
* **`Plugins/`:** Plugin code and assets.
### 1.2 File Naming Conventions
* **C++ Classes:** Use descriptive names with prefixes indicating the class type.
* `A[ClassName]` for Actors (e.g., `ACharacter`, `APlayerController`).
* `U[ClassName]` for UObjects (e.g., `UInventoryComponent`, `UGameInstance`).
* `F[StructName]` for Structs (e.g., `FHitResult`, `FVector`).
* `E[EnumName]` for Enums (e.g., `EMovementMode`, `EInventoryItemType`).
* `I[InterfaceName]` for Interfaces (e.g., `IInteractable`, `IUsable`).
* **Blueprints:**
* `BP_[AssetName]` (e.g., `BP_Character`, `BP_Door`).
* **Assets:** Use descriptive names with prefixes indicating asset type.
* `SM_[AssetName]` for Static Meshes (e.g., `SM_Table`, `SM_Chair`).
* `T_[AssetName]` for Textures (e.g., `T_Ground_Albedo`, `T_Wall_Normal`).
* `M_[AssetName]` for Materials (e.g., `M_Rock`, `M_Water`).
* `MI_[AssetName]` for Material Instances (e.g., `MI_Rock_Dark`, `MI_Water_Shallow`).
* `S_[AssetName]` for Sounds (e.g., `S_Explosion`, `S_Footstep`).
* `Anim_[AssetName]` for Animations (e.g., `Anim_Run`, `Anim_Jump`).
* `Mat_[AssetName]` for Matinee Sequences (Legacy Animation).
* **Levels:**
* `[LevelName]_Level` or `[LevelName]` (e.g., `MainMenu_Level`, `Gameplay`).
### 1.3 Module Organization
* **Game Module:** The main module containing the game's core logic.
* **Feature Modules:** Modules dedicated to specific game features (e.g., `InventoryModule`, `AIModule`).
* **Plugin Modules:** Modules packaged as plugins, offering reusable functionality.
### 1.4 Component Architecture
* **Favor Composition over Inheritance:** Use components to add functionality to actors.
* **Create Reusable Components:** Design components to be generic and adaptable.
* **Use Interfaces for Communication:** Define interfaces for components to interact with each other.
* **Avoid God Components:** Break down complex functionality into smaller, more manageable components.
* **Encapsulate Logic:** Keep component logic self-contained and avoid tight coupling.
### 1.5 Code Splitting Strategies
* **Feature-Based Splitting:** Organize code by game features.
* **Module-Based Splitting:** Create separate modules for distinct functionalities.
* **Async Loading:** Load assets and levels asynchronously to avoid hitches.
* **Level Streaming:** Divide large levels into smaller, streamed sub-levels.
* **Object Pooling:** Reuse frequently created and destroyed objects to reduce garbage collection.
## 2. Common Patterns and Anti-patterns
### 2.1 Design Patterns
* **Singleton:** For classes with only one instance (e.g., `GameInstance`).
* **Observer:** For event-driven communication between actors and components.
* **Factory:** For creating objects without specifying their concrete classes.
* **Command:** For encapsulating actions as objects, enabling undo/redo functionality.
* **Strategy:** For defining a family of algorithms and making them interchangeable.
* **Decorator:** For dynamically adding responsibilities to an object.
* **Adapter:** For adapting the interface of a class to another interface clients expect.
* **Object Pool:** Reuse objects to avoid frequent allocation and deallocation, especially useful for projectiles or particle effects.
### 2.2 Recommended Approaches for Common Tasks
* **Actor Spawning:** Use `GetWorld()->SpawnActor<>()` to spawn actors dynamically.
* **Input Handling:** Use Enhanced Input System for flexible and configurable input mappings.
* **Timers:** Use `GetWorldTimerManager()` for timed events and actions.
* **Collision Handling:** Use collision components and event delegates for collision detection.
* **Networking:** Use Unreal Engine's built-in networking system for multiplayer games.
* **Animation:** Leverage Animation Blueprints and State Machines for complex character animations.
* **UI Design:** Utilize UMG (Unreal Motion Graphics) for creating dynamic user interfaces.
### 2.3 Anti-patterns and Code Smells
* **God Classes/Actors:** Avoid overly large classes with too many responsibilities.
* **Spaghetti Code:** Avoid complex and unstructured code that is difficult to understand and maintain.
* **Magic Numbers:** Avoid hardcoded values without clear explanations.
* **Copy-Pasted Code:** Refactor duplicated code into reusable functions or classes.
* **Tight Coupling:** Minimize dependencies between classes and components.
* **Memory Leaks:** Ensure proper memory management to avoid memory leaks.
* **Excessive Casting:** Minimize the use of `Cast<>` as it can impact performance. Consider using interfaces or dynamic dispatch instead.
* **Polling:** Avoid constantly checking for conditions; use events or delegates instead.
* **Tick Abuse:** Avoid performing expensive operations in the `Tick()` function; use timers or asynchronous tasks.
* **Not using the Actor Component System:** Neglecting to leverage components leads to monolithic, inflexible Actor classes.
### 2.4 State Management
* **Game Instance:** For storing global game state that persists across levels.
* **Game Mode:** For managing game rules and player interactions within a level.
* **Player State:** For storing player-specific information (e.g., score, inventory).
* **Actor State:** For storing the state of individual actors (e.g., health, position).
* **Use Data Assets:** For storing configurable game data (e.g., weapon stats, enemy parameters).
* **State Tree:** For handling complex AI behavior.
* **Gameplay Abilities:** For managing player abilities and interactions using the Gameplay Ability System (GAS).
### 2.5 Error Handling
* **Use `ensure()` for Debug Assertions:** Use `ensure()` to check for conditions that should always be true during development.
* **Use `check()` for Critical Assertions:** Use `check()` for conditions that must be true in all builds.
* **Use `try-catch` for Exception Handling:** Use `try-catch` blocks to handle exceptions in critical code sections.
* **Log Errors and Warnings:** Use `UE_LOG()` to log errors and warnings for debugging and monitoring.
* **Handle Potential Null Pointers:** Always check for null pointers before accessing object members.
* **Implement Recovery Mechanisms:** Provide mechanisms to recover from errors gracefully (e.g., retry logic, fallback behavior).
* **Validate Data:** Implement robust input and data validation to prevent unexpected errors.
## 3. Performance Considerations
### 3.1 Optimization Techniques
* **Profiling:** Use Unreal Engine's profiling tools (e.g., Unreal Insights, Stat commands) to identify performance bottlenecks.
* **LODs (Level of Detail):** Use LODs to reduce the complexity of meshes at a distance.
* **Occlusion Culling:** Use occlusion culling to hide objects that are not visible.
* **Distance Culling:** Use distance culling to remove objects that are too far away.
* **HLODs (Hierarchical Level of Detail):** Use HLODs to combine multiple static meshes into a single mesh.
* **Instanced Static Meshes:** Use instanced static meshes to render multiple copies of the same mesh efficiently.
* **Material Optimization:** Optimize material complexity to reduce pixel cost.
* **Texture Optimization:** Use appropriate texture resolutions and compression formats.
* **Blueprint Nativization:** Convert Blueprint logic to C++ for improved performance.
* **Asynchronous Loading:** Load assets and levels asynchronously to avoid hitches.
* **Object Pooling:** Reuse frequently created and destroyed objects to reduce garbage collection.
* **Avoid Dynamic Allocation:** Minimize dynamic memory allocation during runtime.
* **Optimize Collision:** Simplify collision geometry and disable unnecessary collision checks.
* **Use Niagara:** Use the Niagara particle system for efficient particle effects.
* **Implement Adaptive Resolution:** Dynamically adjust the resolution based on performance.
* **Use GPU Profiling tools:** Tools like RenderDoc can help you debug what is happening on the GPU and pin point bottlenecks.
### 3.2 Memory Management
* **Use Smart Pointers:** Use `TSharedPtr` and `TWeakPtr` for automatic memory management.
* **Avoid Circular Dependencies:** Prevent circular dependencies between smart pointers.
* **Unload Unused Assets:** Unload assets that are no longer needed to free up memory.
* **Garbage Collection:** Understand and optimize garbage collection behavior.
* **Asset References:** Use asset references carefully to avoid unnecessary asset loading.
* **Texture Streaming:** Use texture streaming to load only the necessary texture mipmaps.
* **Minimize Asset Duplication:** Avoid creating duplicate assets; reuse existing ones whenever possible.
* **Monitor Memory Usage:** Regularly monitor memory usage to identify potential leaks or excessive consumption.
### 3.3 Rendering Optimization
* **Minimize Draw Calls:** Reduce the number of unique meshes and materials.
* **Optimize Shaders:** Simplify shader complexity to reduce rendering time.
* **Use Post-Processing Effects Sparingly:** Post-processing effects can be expensive; use them judiciously.
* **Optimize Lighting:** Use baked lighting whenever possible to reduce runtime lighting calculations.
* **Shadow Optimization:** Optimize shadow settings to reduce shadow rendering cost.
* **Use Mobile Rendering Features:** Utilize mobile rendering features for improved performance on mobile devices.
* **Consider Nanite Carefully:** For next-gen fidelity, use Nanite, but be aware of its overhead on lower-end platforms.
* **Virtual Shadow Maps:** Use virtual shadow maps to improve shadow quality and performance in large open worlds.
### 3.4 Package Size Optimization
* **Compress Assets:** Use asset compression to reduce package size.
* **Remove Unused Assets:** Delete unused assets from the project.
* **Texture Compression:** Use appropriate texture compression formats.
* **Audio Compression:** Use appropriate audio compression formats.
* **Blueprint Stripping:** Strip debug information from Blueprints in release builds.
* **Cook Only Necessary Assets:** Ensure that only necessary assets are cooked for the target platform.
* **Use Pak File Compression:** Employ compression when creating .pak files for deployment.
### 3.5 Lazy Loading
* **Stream Levels:** Load and unload levels dynamically based on player location.
* **Load Assets On-Demand:** Load assets only when they are needed.
* **Use Async Load Asset:** Use the `Async Load Asset` node in Blueprints or `LoadObjectAsync` in C++ to load assets asynchronously.
* **Lazy Loading Proxies:** Create proxy objects that load the full asset only when accessed.
* **Subobject loading:** Defer loading of certain UObject subobjects until needed.
## 4. Security Best Practices
### 4.1 Common Vulnerabilities
* **Code Injection:** Prevent code injection by validating all input data.
* **Denial of Service (DoS):** Protect against DoS attacks by limiting resource usage.
* **Man-in-the-Middle (MitM):** Use encryption to protect data in transit.
* **Data Tampering:** Prevent data tampering by using checksums and digital signatures.
* **Save Game Manipulation:** Protect save game data from modification to prevent cheating.
### 4.2 Input Validation
* **Validate All Input Data:** Validate all input data from players and external sources.
* **Sanitize Input Data:** Sanitize input data to remove potentially malicious characters or code.
* **Limit Input Length:** Limit the length of input strings to prevent buffer overflows.
* **Use Regular Expressions:** Use regular expressions to validate input patterns.
* **Implement Whitelists:** Use whitelists to define allowed characters and patterns.
### 4.3 Authentication and Authorization
* **Use Secure Authentication Methods:** Use secure authentication methods such as OAuth 2.0 or JWT.
* **Implement Role-Based Access Control (RBAC):** Use RBAC to control access to different features and resources.
* **Use Strong Passwords:** Enforce the use of strong passwords.
* **Implement Multi-Factor Authentication (MFA):** Use MFA for added security.
* **Store Credentials Securely:** Store user credentials securely using encryption and salting.
* **Avoid Storing Secrets in Code:** Use configuration files or environment variables to store sensitive information.
### 4.4 Data Protection
* **Encrypt Sensitive Data:** Encrypt sensitive data at rest and in transit.
* **Use Secure Communication Protocols:** Use HTTPS for secure communication over the network.
* **Protect Save Game Data:** Encrypt save game data to prevent cheating.
* **Implement Data Backups:** Regularly back up data to prevent data loss.
* **Comply with Data Privacy Regulations:** Comply with data privacy regulations such as GDPR and CCPA.
* **Avoid Exposing Debug Information in Release Builds:** Disable or remove debug information in release builds.
### 4.5 Secure API Communication
* **Use API Keys:** Use API keys to authenticate API requests.
* **Implement Rate Limiting:** Implement rate limiting to prevent abuse of API endpoints.
* **Use Input Validation:** Utilize robust input validation on APIs
* **Use Secure Communication Protocols:** Use HTTPS for secure communication over the network.
* **Validate API Responses:** Validate API responses to ensure data integrity.
* **Log API Requests and Responses:** Log API requests and responses for auditing and monitoring.
## 5. Testing Approaches
### 5.1 Unit Testing
* **Test Individual Components:** Write unit tests for individual components and classes.
* **Use a Testing Framework:** Use a testing framework such as Unreal Engine's built-in Automation System or third-party frameworks.
* **Write Clear and Concise Tests:** Write tests that are easy to understand and maintain.
* **Test Edge Cases:** Test edge cases and boundary conditions.
* **Use Mock Objects:** Use mock objects to isolate components during testing.
* **Test Driven Development:** Consider using Test Driven Development (TDD) principles.
* **Focus on Core Logic:** Prioritize testing core logic and critical functionalities.
### 5.2 Integration Testing
* **Test Interactions Between Components:** Write integration tests to test the interactions between different components and classes.
* **Test Game Logic:** Test the overall game logic and flow.
* **Test Data Flow:** Test the flow of data between different systems.
* **Simulate Realistic Scenarios:** Simulate realistic game scenarios during integration testing.
### 5.3 End-to-End Testing
* **Test the Entire Game:** Test the entire game from start to finish.
* **Use Automated Testing Tools:** Use automated testing tools to simulate player interactions.
* **Test on Different Platforms:** Test on different platforms to ensure compatibility.
* **Test with Real Players:** Test with real players to get feedback on gameplay and usability.
### 5.4 Test Organization
* **Organize Tests by Feature:** Organize tests by game features or modules.
* **Create a Test Suite:** Create a test suite that can be run automatically.
* **Use a Consistent Naming Convention:** Use a consistent naming convention for tests.
* **Document Tests:** Document tests to explain their purpose and functionality.
* **Keep Tests Up-to-Date:** Keep tests up-to-date with code changes.
### 5.5 Mocking and Stubbing
* **Use Mock Objects:** Use mock objects to simulate dependencies during testing.
* **Use Stub Functions:** Use stub functions to replace complex or external functions.
* **Isolate Components:** Isolate components during testing to avoid unintended interactions.
* **Use a Mocking Framework:** Use a mocking framework such as Google Mock or EasyMock.
## 6. Common Pitfalls and Gotchas
### 6.1 Frequent Mistakes
* **Incorrect Asset Management:** Failing to properly manage and reference assets.
* **Over-Reliance on Blueprints:** Overusing Blueprints for complex logic, leading to performance issues.
* **Ignoring Performance Considerations:** Neglecting to optimize code and assets for performance.
* **Poor Memory Management:** Creating memory leaks and excessive garbage collection.
* **Inadequate Error Handling:** Failing to handle errors and exceptions gracefully.
* **Lack of Testing:** Not writing adequate unit and integration tests.
* **Incorrect use of transform:** Using world transform directly, instead of relative transform for attached components.
* **Not using the Garbage Collector Properly:** Not understanding when and how the Unreal Engine garbage collector reclaims memory.
### 6.2 Edge Cases
* **Platform-Specific Issues:** Encountering platform-specific bugs or limitations.
* **Device-Specific Issues:** Encountering device-specific performance issues.
* **Localization Issues:** Encountering issues with text localization and internationalization.
* **Save Game Corruption:** Dealing with corrupted save game data.
* **Network Latency:** Handling network latency and packet loss in multiplayer games.
### 6.3 Version-Specific Issues
* **API Changes:** Dealing with API changes between Unreal Engine versions.
* **Deprecated Features:** Using deprecated features that may be removed in future versions.
* **Compatibility Issues:** Encountering compatibility issues between different Unreal Engine versions.
* **Shader Model Differences:** Accounting for differences in shader models across different UE versions.
### 6.4 Compatibility Concerns
* **Plugin Compatibility:** Ensuring compatibility between different plugins.
* **Hardware Compatibility:** Ensuring compatibility with different hardware configurations.
* **Operating System Compatibility:** Ensuring compatibility with different operating systems.
* **Third-Party Library Compatibility:** Ensuring compatibility with third-party libraries and SDKs.
### 6.5 Debugging Strategies
* **Use the Unreal Engine Debugger:** Use the Unreal Engine debugger to step through code and inspect variables.
* **Use Logging Statements:** Use logging statements to track the flow of execution and identify errors.
* **Use Breakpoints:** Set breakpoints in the code to pause execution at specific points.
* **Use the Visual Logger:** Use the Visual Logger to visualize game data and events.
* **Use Unreal Insights:** Use Unreal Insights to profile performance and identify bottlenecks.
* **Crash Reporting:** Implement crash reporting to collect crash logs and diagnose issues.
## 7. Tooling and Environment
### 7.1 Recommended Development Tools
* **Visual Studio:** For C++ development on Windows.
* **XCode:** For C++ development on macOS.
* **Rider for Unreal Engine:** Cross-platform IDE for Unreal Engine development with C++ and Blueprints.
* **Substance Painter:** For creating and texturing materials.
* **Blender/Maya/3ds Max:** For creating 3D models and animations.
* **Perforce/Git:** For version control.
* **RenderDoc/PIX:** For GPU debugging and profiling.
### 7.2 Build Configuration
* **Use Development Builds:** Use development builds for debugging and testing.
* **Use Shipping Builds:** Use shipping builds for release.
* **Configure Build Settings:** Configure build settings such as optimization level and debug information.
* **Use Build Automation:** Use build automation tools to automate the build process.
* **Set up Build Targets:** Properly configure build targets based on desired device platform (desktop, mobile, console, etc.)
### 7.3 Linting and Formatting
* **Use a Code Linter:** Use a code linter to enforce code style and identify potential errors.
* **Use a Code Formatter:** Use a code formatter to automatically format code.
* **Follow the Unreal Engine Coding Standard:** Follow the Unreal Engine coding standard for consistency.
* **Configure Editor Settings:** Configure editor settings to automatically format code on save.
### 7.4 Deployment
* **Package the Game:** Package the game for the target platform.
* **Test the Packaged Game:** Test the packaged game thoroughly before release.
* **Use a Deployment Platform:** Use a deployment platform such as Steam or the Epic Games Store.
* **Follow Platform-Specific Requirements:** Follow platform-specific requirements for deployment.
### 7.5 CI/CD Integration
* **Use a CI/CD System:** Use a CI/CD system such as Jenkins, Travis CI, or GitLab CI.
* **Automate Builds and Tests:** Automate builds and tests as part of the CI/CD pipeline.
* **Integrate with Version Control:** Integrate the CI/CD system with the version control system.
* **Automate Deployment:** Automate deployment to the target platform as part of the CI/CD pipeline.
* **Trigger Builds on Code Changes:** Configure the CI/CD system to trigger builds automatically on code changes.