0123456789012345678901234567890123456789012345678901234567890123456789 ====================================================================== Running the game without gameplay ====================================================================== When tracking down resource issues it usually makes sense to run a map without any gameplay to not be distracted by gametype specific textures being precached and the likes. This doesn't mean a map won't have to run well with gameplay though ;-) To play a map with the default dummy gametype you will have to open it like: open MyMapName?game=engine.gameinfo ====================================================================== Occlusion/ visibility ====================================================================== FIXEDVISIBILITY freezes the camera position from the visibility code's point of view. This means that you can still walk around as usual though the engine will only render objects that have been visible at the time the command was issued. Entering it again will disable it and return to normal rendering. The purpose of this command is to allow level designers to track down what got occluded and what didn't and also act as a sanity check to see how much got rendered in a large outdoor scene. E.g. you can type FIXEDVISIBILITY and then "ghost" up to get an overview of how much area was visible. ====================================================================== Rendering stats ====================================================================== STAT HARDWARE lists a couple of useful resources level designers should keep an eye on like e.g. NumPrimitives number of triangles in view NumTextures number of textures in view TextureBytes bytes of textures in view ====================================================================== Texture/ geometry resource usage ====================================================================== D3DRESOURCES and D3DRESOURCES ALL can be used to get a feeling for how much video memory is used by resources and how the usage is split up between geometry and textures. Below is a sample snippet of the output of D3DRESOURCES ALL. Log: Direct3D Detailed Texture Resource Usage Log: Log: KByte Type Name Log: -------------------------------------- Log: Log: 1024 RGB8 Uncompressed Lightmap Log: 682 DXT3 Texture HumanoidArchitecture.Bases.bas20HA Log: 320 DXT3 None Log: Log: Log: Direct3D Resource Usage Summary Log: Log: Resource Type Count Total Bytes Log: -------------------------------------- Log: Textures 111 31086110 Log: Vertex Streams 78 2649880 Log: Index Buffers 43 403554 Log: Other 0 0 Log: Log: Allocated D3D resources account for 31744 KBytes E.g. in the above example you can see that bas20HA is a 682 KByte Texture being uploaded to the card. Uncompressed Lightmap is shown for lightmaps if you have compression turned off and None is listed as the name if you have compression enabled (which should be the default). A lightmap size of 320 KByte indicates DXT3/5 as being used as the compression format instead of the prefered DXT1. All levels that haven't already gone out with UT2003 or any of its bonus packs should use DXT1 texture compression for lightmaps (it's a setting in the build menu). The Textures stat lists the number of all uploaded textures (including gameplay specific ones) and the size count following it is the amount of video memory taken up by them. The same goes for vertex streams and index buffers which equate to static mesh/ BSP usage. ====================================================================== Corrupted textures ====================================================================== Due to a bug "somewhere" (please let me know if you can reproduce it) textures might end up with either all or certain miplevels not being defined which can cause all sorts of visual artifacts on different implementations/ renderers. The best case scenario is the texture being black and the worst case being random garbage. All textures that have this problem need to be reimported. You can check whether your maps/ texture packages are affected by running ucc editor.checktextures ..\Textures\MyTexturePackage.utx or ucc editor.checktextures ..\Maps\MyMap.ut2 and a typical warning message looks like below. WARNING: Texture [AS-MotherShip.Gray] miplevel 0 is empty [out of 8]. ====================================================================== Compressing textures ====================================================================== All textures should be compressed by default. The correct compression format for textures not containing an alpha layer is DXT1 and for ones with alpha layer you should either choose DXT3 or DXT5. Textures used for projectors and detail textures require special care. Detail textures need to be imported with the "detail hack" checkbox set so their mipmaps can fade to gray and textures used for projectors need to be compressed via NVIDIA's photoshop plugin. The important option to pick during compression is "Border color (1 texel)" as it will make sure that textures won't "stretch" at the edges at lower texture resolutions or in the distance. The border color depends on whether you plan to use modulation in which case the border color should be 127,127,127 or brighten/ darken in which case the border color should be 0,0,0. NVIDIA's DXT texture compression plugin can be found at: http://developer.nvidia.com/object/ps_texture_compression_plugin.html ====================================================================== Overdraw ====================================================================== RMODE 8 is the rendering mode visualizing overdraw. Particles and coronas are usually the worst case offenders wrt to overdraw so you should make sure to always use alpha test and also make sure that the used area of a texture roughly equates what is being rendered. E.g. don't use a 256x256 texture with just a 5x5 dot in the middle! You will have to either use the overdraw button in the Editor or modify your UT2004.ini file (set all occurances of UseStencil=False to True) before running the game and typing "RMODE 8". RMODE 5 is the default rendering mode and RMODE 1 is wireframe. ====================================================================== Software rendering. ====================================================================== Starting with UT2004 we're officially supporting software rendering again and it will be a default fallback for compatibility reasons in cases of outdated drivers or incapable hardware (e.g. any of the Intel chips). Level designer should use the software renderer from time to time to verify that their level runs adequately with it and to verify that there are no visual artifacts. If there are visual artifacts the material should be checked for fallbacks and if there are none a fall- back should be added. Please post a screenshot of the artifact if this doesn't help. To use the software renderer you can conveniently start the game with ut2004 -software -noini which will set some sensible software rendering defaults and makes sure that the ini doesn't get saved so it's no hassle to just give it a try from time to time. ====================================================================== Fallback materials ====================================================================== Complex materials/ shaders should have fallbacks set in order for them to render correctly on low end machines like a GeForce 2. You can roughly emulate one by typing RENDEREMULATE GF2 on the console and reset back to normal by typing RENDEREMULATE NONE. Another good way to check whether a material needs a fallback is to look at it with the software renderer (see software rendering section). If in doubt, add a fallback. ====================================================================== DXT1 lightmaps ====================================================================== By default, lightmaps will be compressed as DXT3/5 textures though levels with either a lot of BSP or high resolution lightmaps should use DXT1 instead. This also applies to levels already running into resource issues (too many textures/ static meshes). The drawback of DXT1 is that NV10-NV25 (GF1-4) don't correctly display it which might cause slight banding artifacts if you don't have noisy base textures to hide it (though this is most likely the case). The upside is that DXT1 compressed textures are only half the size of DXT3/5 and also offer a slight increase in quality on all other cards (e.g. all Radeon, GeForce FX, Kyro, Xabre, ...). You can pick either DXT1 or DXT3/5 compression via the build settings. ====================================================================== 16 bit ====================================================================== The majority of our customers will have to play the game at 16 bit color depth which means that we have to make sure that all levels work with a 16 bit depth buffer without major z fighting. Visual artifacts in distant geometry can usually be worked around or improved but heavy z- fighting in gameplay important sections like sniper spots cannot be tolerated. ====================================================================== Scaleability options ====================================================================== The engine supports a whole slew of scaleability options to provide customers with low end machines with an option to run the game with decent performance. Most of them don't require any level designer interaction though high detail actors do. Level designers should flag non- gameplay relevant (aka no collision) decorative objects with bHighDetail and bSuperHighDetail. Basically you want the map to perform as good as possible at the lowest world geometry settings and medium detail settings should be a happy median between eye candy and performance. High detail settings are max eye candy though you'll still have to build your maps with the standard resource and polycount restrictions in mind. The engine will color bHighDetail static meshes orange and bSuperHigh- Detail static meshes red if you set ColorHighDetailMeshes to true in the Engine.GameEngine section of your UT2004.ini. This option requires static mesh batching to be turned on and therefore doesn't work in the Editor. This only colors static meshes though e.g. particle systems are another prime candidate for being flagged as high/ super- high detail. ====================================================================== Simplified collision ====================================================================== Static meshes with bBlockActors set should have a simplified collision model attached to them so players don't get caught up on small triangles and to speed up Karma ragdoll collision. A tutorial on how to set up simplified collision can be found at the below URL http://udn.epicgames.com/bin/view/Content/CollisionTutorial An easy way to ensure optimal level performance is to make sure that all static meshes/ actors that don't require collision have it disabled. E.g. unreachable meshes or meshes blocked via blocking volumes should have collision disabled via the Collision actor properties. ====================================================================== Collision flags ====================================================================== bCollideActors This flag determines whether an actor should have collision or not. Setting it to false disables all collision and setting it to true enables collision depending on the following flags. bBlockActors This flag determines whether another actor should be blocked by the current one. An example where bCollideActors is 'true' and bBlockActors is 'false', would occur with movers and triggers. You want a player to 'collide' and set off the trigger, but you most likely don't want the trigger to block the player. bBlockKarma This flag determines whether Karma objects like e.g. rag dolls should collide with the actor. bBlockNonZeroExtentTraces bBlockZeroExtentTraces Non zero extent traces are done for player movement, the shock rifle secondary fire, the redeemer and zero extent traces are used for the remaining projectiles, instant hit weapons and remaining collision like e.g. particles, decals, ... For static meshes, UseSimpleKarmaCollision UseSimpleBoxCollision UseSimpleLineCollision control whether to perform the much faster collision check against the simplified collision model as opposed to doing slow per triangle collision. UseSimpleBoxCollision determines whether to use the simplified collision for non zero extent traces (e.g. player movement) and UseSimpleLineCollision determines whether to use it for zero extent traces (e.g. instant hit weapons, most projectiles). UseSimpleKarma- Collision tells the engine to use the simplified collision model for karma rag- doll collision. Typical usage scenarios are: 1. Standard static mesh with simplified collision. bCollideActors=true bBlockActors=true bBlockKarma=true bBlockNonZeroExtentTraces=true bBlockZeroExtentTraces=true UseSimpleKarmaCollision=true UseSimpleBoxCollision=true UseSimpleLineCollision=false 2. Static mesh that is unreachable or doesn't need to collide bCollideActors=false bBlockActors=false bBlockKarma=false bBlockNonZeroExtentTraces=false bBlockZeroExtentTraces=false 3. Static mesh that uses a blocking volume for player collision bCollideActors=true bBlockActors=false bBlockKarma=false // depends on usage, most likely false bBlockNonZeroExtentTraces=false bBlockZeroExtentTraces=true UseSimpleKarmaCollision=true UseSimpleBoxCollision=true UseSimpleLineCollision=false and on the blocking volume bCollideActors=true bBlockActors=true bBlockKarma=true // should the opposite of SM's setting bBlockNonZeroExtentTraces=true bBlockZeroExtentTraces=false Disabling collision in the material property for static meshes that don't need collision at all is a memory saving. In certain cases, like e.g. the tower in the center of ONS-Torlan, the simplified collision model would be too high poly in order to be effectively used as simplified collision. In those scenarios you should build a lower polygon version of the static mesh and hide it by setting the following "Advanced" and "Display" flags: bHidden=true bUnlit=true bAcceptsProjectors=false bShadowCast=false bUseDynamicLights=false The "Collision" flags for the rendered static mesh should be bCollideActors=true bBlockActors=false bBlockKarma=false bBlockNonZeroExtentTraces=false bBlockZeroExtentTraces=false and for the collision static mesh bCollideActors=true bBlockActors=true bBlockKarma=true bBlockNonZeroExtentTraces=true bBlockZeroExtentTraces=true ====================================================================== EAX zone effects ====================================================================== The following link shows how you can add existing pre- canned reverbs to a level and also explains how you can tweak the settings if the presets don't sound good enough. http://udn.epicgames.com/pub/Content/ExampleMapsSounds/ You have to select Hardware 3D Audio + EAX on a card that supports at least EAX 2.0 to be able to hear the effects. All zones in UT2004 levels should be set up for EAX and the engine automatically picks an underwater reverb setting for water volumes. ====================================================================== copyrighted textures/ source art ====================================================================== Don't use copyrighted source art. ====================================================================== correct LODSet/ NormalLOD/ Mipmaps ====================================================================== All imported textures should have mipmaps! Also, make sure to correctly pick the LODSet after importing (e.g. world/ character/ ...) Some of the interface textures at the moment don't use LODSet_Interface which needs to be changed in order for them to not look blurry on low end machines. When importing a 1024x1024 or larger texture you should set its NormalLOD value to either 1 or 2 which causes it to drop miplevels at normal detail settings yet allow high end machines to display it at full quality. E.g. all character skins either have a NormalLOD of 1 or 2. ====================================================================== Testing at lower detail and texture resolution settings ====================================================================== Level designers should play their levels at different detail and texture resolution settings as the majority of customers will not be able to run the game on machines capable of displaying the levels at full detail. Lower texture resolution settings are expected to be kind of blurry, but it looks odd if a couple of textures are still high res for some reason. E.g. using a 256x256 texture on a large piece of geometry and a 1024x1024 texture on a small surface might work at highest detail settings though at normal and lower this looks really odd as one will be blurry and the other might still be sharp, which in contrast makes the blurry texture seem to have even less resolution. The same goes for other detail settings like world geometry detail levels. The contrast makes bad areas look worse and it is usually best for both visuals and performance to scale it so things look equally "bad" at low detail settings. ====================================================================== Useful console commands ====================================================================== SHOWSLOWOVERLAP Prints to log when the point-check inside AActor::IsOverlapping takes more than the supplied time. Very handy for finding when emitters etc have collision and shouldn't. Usage: SHOWSLOWOVERLAP TIME=0.5 Will then print any overlap checks that take more than 0.5ms SHOWSLOWOVERLAP SHOWSLOWOVERLAP TIME=0.0 Will turn it off again. Example message: Log: IOL: Testing: P:Mover47 - B:Emitter38 Time: 0.251598 In this case the bounding box (B) of Emitter38 is being checked against the static mesh primitive (P) of Mover47 and it is taking 0.25ms. Level designers should run their maps with this set to about 0.5ms and check the log for things that are overlapping but should not be. Particle emitters with collision accidentally turned on overlapping movers are a common one. FREEZEALL Like PLAYERSONLY, but freezes vehicles and ragdolls as well. ====================================================================== Script profiling ====================================================================== The engine collects number of calls and time spent in each script function which can be very valueable information when tuning script code. RESETPROFILE Resets profiling data (automatically happens on level changes) DUMPPROFILE Dumps the collected data to the log. See below for example output. PROFILINGSTACKDEPTH X Resets the profiling data sets the maximum stack depth of functions data to be collected. To go into a bit more detail on the option - without setting the stack depth (default is unlimited) the engine keeps track of how much time is spent in each function call so if you have something like A calls B calls C all three functions will be listed with A including the time spent in B & C and B including the time spent in C. This makes finding real hotspots hard so you can control which functions to list. A value of 1 for PROFILINGSTACKDEPTH only takes into account top level functions (this is what you want for an initial first impression) and higher values track more of the function call stack which is useful for more detailed analysis if you know exactly which functions calls which. The below is some sample output gathered playing CTF-Maul with a profiling stack depth of 1. Profile of 4317 ticks: Function usec/tick calls/tick ------------------------------------------- --------- ---------- XInterface.HudBase.DrawHUD 1235.4512 0.9819 Engine.Weapon.RenderOverlays 599.6781 0.7980 Engine.PlayerController.PlayerTick 115.2408 0.9998 XWeapons.Translauncher.RenderOverlays 73.0600 0.1726 Engine.HUD.DisplayMessages 65.7293 0.9998 Engine.ScoreBoard.DrawScoreboard 54.1904 0.0178 Engine.ShadowProjector.UpdateShadow 38.3015 6.1832 Engine.PlayerController.CalcFirstPersonView 20.9650 1.6125 ====================================================================== Feedback ====================================================================== => mailto:vogel@epicgames.com