3D and Unreal Engine knowledge
Disclaimer: This is solely our experience. We may have understood various things incorrectly. Read with skepticism. Please send a message if there are any corrections to be made.
- Lighting is really, really performance- and size-heavy. It should be a top priority to optimize and design around.
- Double check the scale of objects/environment relative to the player’s height/size and perspective. Make sure to have logical rules for scaling any objects, depending on the context (3rd person game, top-down game, first-person game, etc.).
- The more setting tweaks you can add to your options menu, the better, both for performance and user friendliness. It’s impossible for a small team to test on a large range of devices, so expose the options for users to change settings to suit their device. However, keep in mind the design of the settings screen (add pages if necessary). Having too many settings to choose from can be overwhelming, and if a user needs to change something but has difficulty navigating the settings pages, they may simply give up and quit.
- If you are working in a team with multiple people editing maps (or any binary file for that matter), find a method to keep track of who is accessing what asset, and “lock” it. UE is working on a method to do this automatically (through Perforce?), but that’s in the future. Especially if you are working with Blueprints (which are binaries), it’s important to not allow multiple people to work on the same asset at a time because you will constantly overwrite each others’ work and lose progress. A terrible workaround is for a worker to save their work as a duplicate file and commit it to their branch/master, and have the person in charge manually merge the files by copy-pasting them. This is terrible because: 1) it’s really hard to see anything in Blueprints, 2) it introduces another location for human error, 3) UE will crash and/or be super laggy.
- MSI Afterimage + RivaStat is useful for looking at performance of your game using Shipping packaging settings
- Blueprints (the visual scripting system), while definitely usable, are not ideal for getting things done cleanly/efficiently. If possible, find a C++ programmer on the team who can externalize mechanics/designs to Blueprints for the game designer (but otherwise program everything in C++). Since Blueprints is a wrapper for C++, its performance is a lot worse than native C++ code. It also takes up a lot more hard drive space. UE ships with an option to “nativize” Blueprints (convert them to native C++ code), but: 1) it is very buggy (we were unable to nativize our Blueprints), 2) when packaging up the game, it will include both the nativized code and the original Blueprints, so the size of coding assets will “double” (not exactly double, nativized code may be bigger or smaller than the Blueprints).
- Blueprints have a “Delay” node where you can tell the program to wait X seconds before executing the next instruction. USE WITH CAUTION. It is impossible to kill/pause/keep track of these delays. Use a Timer whenever possible because you can keep track of the function and thus kill/pause/restart it whenever you need. Example: If you are trying to script a voice acting line progression (say line 1, wait 5 seconds, say line 2, wait 2 seconds), it might be natural/easiest to think of just using Delays. But what if a player hits the Pause menu in between lines 1 and 2? Or they exit the level? Line 2 will still continue because there’s no way to tell the progression to stop.
- For anything in-game where the state can change (and you possibly need to keep track of it, perhaps for loading levels), create a function attached to the object that can set the state of the object (reset, completed, anything in between).
- Are you confused why your code doesn’t seem to be running properly, or it skips over some of your nodes for no reason, and there are no error messages? Add a Delay node with .2-1s right before the failing node! Why? No real clue, though it might be that the next node is trying to execute before the previous ones allow it, which makes everything down the chain of command fail. Silently.
- Open Level = Reset everything within the level to its default settings. Load/Unload stream level will keep the state of everything. So if you opened a box and then did an “Open Level”, the box will appear closed. If you opened a box, went to Level 2, then went to Level 1, all via Load/Unload Stream Level, then the opened box will remain open.
- Disable VSync and Frame Rate Smoothing when you are profiling the game, otherwise your numbers will be strange.
- Test ALL graphics quality settings during optimization/design/art/QA/etc. phases. It is possible that different quality settings will need special custom settings, because the defaults might make things strange. One example is the River in SCU, where in the original version, if you put the Graphics Quality to Low, you could not see anything because everything was a neon teal color. We had to add special settings for post-processing changes for various graphics quality levels.
- PROBLEM: Migrate a blueprint from project_OLD to the project_NEW and deleting variables from the blueprint in project_NEW may give reference warnings (https://cdn.discordapp.com/attachments/510617082015121409/767417140390658048/unknown.png)
- Solution: Move the blueprint into another folder, run fix refs in the folder that the file originally lived in, then move the file back into its original home (https://answers.unrealengine.com/questions/591891/ghost-references-from-deleted-variable.html)
- ✴️NOTE: Touching anything in the editor has a high chance of making lots of files be “modified”. If you are sure that you did not do anything in those other files, make sure not to save all files. Who knows what you might accidentally be overwriting!!!
- PROBLEM: UE loves its default settings. Within project settings and in a new project, there will already be some post-processing settings enabled. If you want to completely remove a post-processing option (e.g. motion blur), make sure to DISABLE it in project settings AND ENABLE IT with a value of 0 in your scene’s post-processing volume
- Need to delete or move files around in your project? Well, you’re almost out of luck. You can attempt to do it from outside the editor, but it may crash the editor or corrupt everything. You can also try to do it from within the editor, but it will also crash the editor 80% of the time. Good luck keeping your project clean :)
- Are you using Starter Content in your shipped game? By default, the entire folder will not be included in your packaged game, and UE will not automatically copy over the used asset to folders that are included. You will have to copy the file over yourself manually. This is despite the fact that UE says they only include all files that are used in-game. (Unlike Unity, where you have to manually list files to ignore, though since UE isn’t doing its job as promised, at least the Unity workflow will ensure the files are in the package. Your packaged game might just be kind of large.)
- If you aren’t using anything VR-related, go into the plugins settings and disable them before building the game. If they are enabled, regardless of their use in-game, they will be packaged with your game, and your game might try to run in VR if a player has a VR headset plugged in.
- When you “build” or “bake” or “cook” lighting, you are creating a lookup table (atlas, map, dictionary) for how a texture should look based on the scene lighting. This will only update _BuiltData.uasset files. YOU ONLY NEED TO SAVE THIS FILE. Building lighting WILL NOT modify the map file (even though UE will tell you that you can save the map file).
- Dynamic lights are super expensive! These are lights where calculations of how the light interacts with the world is done in real-time. If you have a dynamic/movable object that needs to be lit up, and a stationary light is insufficient, add a dynamic light with a SMALL light attenuation cone. Have it just big enough to light up the object, and the supplement the environment lighting with invisible static lights! It’s A-OK to place invisible static lights in locations without any obvious light source. You are just supplementing the indirect lighting with some cheap hacks :). Try not to overlap your dynamic light attenuation cones too much. It will kill performance very quickly.
- When importing models into UE, make sure to have artist set up the LODs since it is super easy/quick. For UE, the default import will be LOD0. This means that at any distance, as long as the object is rendered, all of the vertices in their original detail will also be rendered, regardless of whether the viewer can see all that detail. You want at least 2 LODs so that at a far distance, fewer vertices need to be rendered.
- https://docs.unrealengine.com/en-US/Engine/Content/Types/StaticMeshes/HowTo/AutomaticLODGeneration/index.html details how to set up the LODs
- Aim for shader instruction count per material to be <250 instructions
- We read this somewhere on some forum post, but since our materials are fairly simple, we weren’t concerned with this. Higher instruction count means more computation power required to draw the pixel, so performance will plummet if instructions are too complicated.
- Cheat on the graphics wherever you can! Do you really need a fully transparent window, or can you use an opaque texture with an image of what’s behind it? Translucent/transparent textures are very expensive because the pixels have to be drawn multiple times.
- Make sure all your walls and objects are perfectly aligned without lazy overlapping. If you are making a room with four walls, those four walls should fit perfectly together like a gingerbread house! If you do not, there is high chance of mysterious issues down the line, like light bleeding or pixel-wide holes. There may be something to be said for performance optimization here as well, though it is possible that the engine/camera is smart enough to cull/not draw the overlapping (and invisible) mesh.
- Skysphere = background/backdrop. It does not produce light on its own. It is just your fake sky! Skysphere + skylight = indirect lighting. You need the skylight to get pretend light from the pretend sky to affect your (pretend?) objects! This is how you light up your dynamic/movable objects without putting a dynamic light in front of every dynamic object.
- Skylight has the ability to “recapture” the sky so that if you change your skysphere, you can update how the indirect lighting should look. HOWEVER, this is an expensive operation (your game will freeze for a frame or three), so do it during a loading screen. Also, Skylight automatically runs a [re]capture when it is spawned, so if it is spawned before your skysphere, then you will need to recapture the sky again. *Is there a way to force the Skylight to spawn after the Skysphere?*
- Merge your individual props into larger meshes and/or make use of instanced meshes whenever possible. This will generally save on computational resources. Do you always use the same shelves with the same books in them? That can be one prop, rather than individual props for the shelves and every book inside. Merging props/corners may also assist with light bleeding issues.
Questions or Comments?
Feel free to send in any AG-related questions! Our Ask Box is always open.
Thanks so much for all of your amazing support, and stay safe out there!