https://wiki.tripwireinteractive.com/api.php?action=feedcontributions&user=Keith&feedformat=atomTripwire Interactive Wiki - User contributions [en]2024-03-28T18:15:54ZUser contributionsMediaWiki 1.40.0https://wiki.tripwireinteractive.com/index.php?title=Red_Orchestra_2:_Heroes_Of_Stalingrad/LevelDesign/RO2DestructionSystem&diff=1535Red Orchestra 2: Heroes Of Stalingrad/LevelDesign/RO2DestructionSystem2012-07-30T12:36:10Z<p>Keith: /* ROStaticMeshDestructible */</p>
<hr />
<div>=Red Orchestra 2 Destructible Setup Guide=<br />
<br />
Red Orchestra 2 has a number of tools to facilitate destructible environments and/or objectives. This document is to serve as a means to understand how to set up the systems and why you would want to use each of the tools available.<br />
<br />
The topics covered in this document will be:<br />
<br />
*ROStaticMeshDestructible<br />
*ROStaticMeshReplicationInfo<br />
*ROObjectiveSatchel<br />
*ROStaticMeshObstacle<br />
*ROStaticMeshSatchelObstacle<br />
*RODestructible<br />
<br />
==ROStaticMeshDestructible==<br />
<br />
[[Image:ROStaticMeshDestructible_In_A_Map_Wireframe.jpg|thumb|300px|center|frame|ROStaticMeshDestructible in a Map]]<br />
<br />
[[Image:ROStaticMeshDestructible_In_The_Tree.jpg|thumb|300px|center|frame|In the Tree]]<br />
<br />
===Setup of ROStaticMeshDestuctible map actors===<br />
<br />
1) Select the base static mesh that will appear to the players in it's “undestroyed” state<br />
<br />
2) Select the map actor in the actor tree<br />
<br />
3) RMB → Add ROStaticMeshDestructible Here<br />
<br />
[[Image:ROStaticMeshDestructible_Add_To_Map.jpg|thumb|300px|center|Add to Map]]<br />
<br />
4) Open the properties of the newly place actor and find the StaticMeshComponent section of ROStaticMeshDestructible (Properties → ROStaticMeshDestructible → Destructible Mesh Component → StaticMeshComponent → Static Mesh) and replace the default static with the one selected in step 1. This is what is shown to the level designer in the editor.<br />
<br />
[[Image:ROStaticMeshDestructible_Add_To_Map_C.jpg|thumb|300px|center|Add to Map]]<br />
<br />
5) Open the RODestructibleStaticMeshComponent section of the properties<br />
<br />
[[Image:ROStaticMeshDestructible_Properties_Component_D.jpg|thumb|300px|center|Destructible Properties]]<br />
<br />
6) Add at least two entries to the Destructible Assets list<br />
<br />
7) In the 0 section put the same base mesh as that of the Static Mesh. This is what will be shown to the players at runtime. NOTE: Use the Material Override to override the material that will be rendered in game. The LODMaterial Override should be used to override the materials on the LODs of the StaticMesh, if it exists, that will be rendered in game.<br />
<br />
8) In the 1 section put the destructed stage of the base static mesh. NOTE: You can add more than two stages but for each stage the lighting system will have to make a shadow map which can cause some bloat in map size. <br />
<br />
9) Under the Accepted Damage Types add the damage types you'd like to have effect the ROStaticMeshDestructible<br />
<br />
[[Image:ROStaticMeshDestructible_Properties_Component_C.jpg|thumb|300px|center|Accepted DamageType Example]]<br />
<br />
10) Set the appropriate value for Starting Health. If you'd like a tank to be able to run over the actor, give it a starting health of 1<br />
<br />
11) Set an appropriate emitter for the Destruction Emitter Template. This is what will be shown to the players when it changes states. The emitter will be spawned at the origin of the Static Mesh itself.<br />
<br />
12) Use the Destruction Emitter Offset values to adjust the spawn origin of the static mesh the origin of the Static Mesh being used is not in a good place for spawning an emitter<br />
<br />
13) If you would like the destructible to become active and interact with world space on destruction, set the Physics Static Mesh. NOTE: If you are going to have an active physics actors spawn instead of a destruction phase static mesh, leave the section in Step 8 empty.<br />
<br />
14) If there is cover that you would like to activate/deactivate upon stage change, you can add the cover references here. NOTE: ROStaticMeshDestructible and cover node must be in the same level. Usually the persistent. Use the Lock properties to allow selecting the cover node in the map without change the property window<br />
<br />
15) If you'd like to have multiple destructible static meshes to destroy even if they are not directly touched by the damage, add references to the ROStaticMeshDestructible to the Grouped Destructibles section of the properties. <br />
<br />
[[Image:ROStaticMeshDestructible_Properties_Component_D.jpg|thumb|300px|center|Other ROStaticMeshDestructible Properties]]<br />
<br />
==RODestructionReplicationInfo==<br />
<br />
The purpose of this actor is to provide a lighter weight replication solution for destructible actors in a map; instead of sending a lot of information from the server to the client to change the state of a destructible actor in a map this actor sends just the Integer value of the destructible in info structure. This makes it a little bit more intensive for the server when a large number of destructible map actors change state simultaneously but should not bog down the net code. <br />
<br />
===Rules of Thumb===<br />
<br />
1) No more than 300 destructible actors in each RODestructibleReplicationInfo actor<br />
<br />
2) Maps are not suggested to exceed 500 destructible actors<br />
<br />
3) No limitation of the number of RODestructibleReplicationInfo <br />
<br />
4) The RODestructibleReplicationInfo actor must be in the same level as the ROStaticMeshDestructible, usually the Persistent level.<br />
<br />
===Setting Up RODestructibleReplicationInfo Actors===<br />
<br />
1) Find and place a RODestructibleReplicationInfo Actor in your map<br />
<br />
[[Image:RODestructionReplicationInfo_Actor_In_A_Map.jpg|thumb|300px|center|RODestructibleReplicationInfo in a Map]]<br />
<br />
[[Image:RODestructionReplicationInfo_Actor_In_The_Tree.jpg|thumb|300px|center|RODestructibleReplicationInfo in the Actor tree]]<br />
<br />
2) Open the properties of the RODestructibleReplicationInfo actor and lock the properties<br />
<br />
[[Image:RODestructionReplicationInfo_Properties.jpg|thumb|300px|center|RODestructibleReplicationInfo Properties]]<br />
<br />
3) Open the Scene manager<br />
<br />
[[Image:SceneManager.jpg|thumb|300px|center|UE3 Scene Manager]]<br />
<br />
4) Select the persistent level<br />
<br />
5) Use the pulldown to select ROStaticMeshDestructible in the filter<br />
<br />
6) Add the appropriate number of slots to the replication actor (not exceeding 300)<br />
<br />
7) Select the first ROStaticMeshDestructible<br />
<br />
8) Add it to the first entry in the RODestructibleReplicationInfo actor<br />
<br />
9) Repeat steps 7-9 until you've either added all the ROStaticMeshDestructible actors in the map to the RODestructibleReplicationInfo actor or you've added 300 to the actor<br />
<br />
==Objective Based Destructible==<br />
This section covers how to setup objective based destructible solutions. <br />
<br />
===ROObjectiveSatchel===<br />
<br />
The purpose of the ROObjectiveSatchel is to allow for the capability for level designers to have objectives that “capture” upon destruction. It also allows for “proximity” capturing via a ROPlaceableVolume and otherwise functions 100% like a standard ROObjective.<br />
<br />
Setup of ROObjectiveSatchel<br />
<br />
1) Open the content browser and select a static mesh that you'd like to use for a ROObjectiveSatchel. Ideally this mesh will have it's origin centered on the object correctly (center, bottom-center, corner, etc).<br />
<br />
2) Find the ROObjectiveSatchel in the actor tree and place one in your map where you'd like the satchel objective to be<br />
<br />
3) Open the properties of the ROObjectiveSatchel and Expand the StaticMeshComponent section and replace the Static Mesh field with the mesh selected in Step 1<br />
<br />
[[Image:ROObjectiveSatchel_Properties_B.jpg|thumb|300px|center|Satchel Objective StaticMesh Properties]]<br />
<br />
4) Add at least two entries to the Destructible Assets list<br />
<br />
[[Image:ROObjectiveSatchel_Properties_A.jpg|thumb|300px|center|Satchel Objective Destructible Properties]]<br />
<br />
5) In the 0 section put the same base mesh as that of the Static Mesh. This is what will be shown to the players at runtime. NOTE: Use the Material Override to override the material that will be rendered in game. The LODMaterial Override should be used to override the materials on the LODs of the StaticMesh, if it exists, that will be rendered in game.<br />
<br />
6) In the 1 section put the destructed stage of the base static mesh. NOTE: You can add more than two stages but for each stage the lighting system will have to make a shadow map which can cause some bloat in map size. <br />
<br />
[[Image:ROObjectiveSatchel_Properties_D.jpg|thumb|300px|center|Satchel Objective Objective Properties]]<br />
<br />
7) Expand the ROObjective section and fill that out:<br />
<br />
Obj Index – this is a unique value that assigns the alphabetical assignment to the objective<br />
<br />
Obj Rep Index – this is a unique value that is used in replication. Usually this has the same value as the object name. For example, if the objective name is ROObjective_1 the Obj Rep Index will be 1<br />
<br />
Obj Name – this is localize name of the objective<br />
<br />
Obj Secondary Name – this is a internally used field that will be rendered on the overhead map. Any value here will be ignored in game. Best to leave it blank<br />
<br />
Obj Volume – this is the ROPlaceableVolume that is assigned to this objective for “proximity” capturing<br />
<br />
Map Zone Texture – this is a texture that is used as an overlay for the overhead map when the objective becomes active<br />
<br />
Minimum Capture Time – this time, in seconds, is the the amount of time it will take to capture the objective<br />
<br />
Initial Obj State – use the pulldown to select the initial defender state of the objective. NOTE: Neutral objective assignment for a ROObjectiveSatchel is not supported<br />
<br />
Lock Down Time 16/32/64 – these fields are deprecated and values assigned will not do anything<br />
<br />
Countdown Time – this is the amount of time the objective is active in the Countdown game mode, counted in seconds<br />
<br />
Is Key Objective – this bit is used in Countdown and gives an additional reinforcement for the commander<br />
<br />
Enable Lockdown – this bit is used to enable the procedural lockdown system in RO2<br />
<br />
Axis/Allies Priority – this is the order in which the AI will attack or defend the objectives. <br />
<br />
===RODamageOtherVolume===<br />
<br />
There is an additional supporting actor called a RODamageOtherVolume that allows of dropping the Satchel weapon (equipment for the engineering role) inside the volume. This overcomes the limitation that occurs when the origin of the SatchelObjective mesh is in a location to be “touched” by the explosion radius. For example, if the physical objective is inside a brick building but you'd like for the ability for the players to drop the satchel near the building and still destroy the objective.<br />
<br />
[[Image:RODamageOtherVolume_Properties.jpg|thumb|300px|center|DamageOtherVolume Properties]]<br />
<br />
Victim Actor: This points to the ROObjectiveSatchel that you'd like have accept the damage<br />
<br />
Damage Scale: A scale value of the damage applied to the Victim Actor<br />
<br />
Damage Types: The accepted damage types<br />
<br />
Ignore Damage Types: The damage types that should be ignored (usually to filter out subclasses of a damage type that won't damage the objective but the parent class will)<br />
<br />
==ROStaticMeshObstacle==<br />
<br />
These map actors are used to block off sections of NavMesh/Gamespace so that AI and players do not access certain areas of the map. Ideal use is when differentiating player loads between 16/32/64p matches<br />
<br />
===Setup of ROStaticMeshObstacle===<br />
<br />
1) Select a static mesh from the content browser<br />
<br />
2) Select ROStaticMeshObstacle from the Actor tree (Actor -> NavMeshObstacle -> ROStaticMeshObstacle)<br />
<br />
3) RMB -> Place ROStaticMeshObstacle here<br />
<br />
This should give you the static mesh you selected in Step 1 as a ROStaticMeshObstacle<br />
<br />
4) Select the newly create ROStaticMeshObstacle in the map<br />
<br />
5) Open Kismet and attach the ROStaticMeshObstacle to a Toggle action. Toggle ON to have it active Toggle OFF to have inactive<br />
<br />
What toggling does:<br />
<br />
A) Turns on/off navmesh beneath it's bounding box <br />
<br />
B) Turn on/off collision of the StaticMesh actor<br />
<br />
==ROStaticMeshSatchelObstacle==<br />
==RODestructible==<br />
<br />
This actor has been antiquated and removed from the Actor tree</div>Keithhttps://wiki.tripwireinteractive.com/index.php?title=Red_Orchestra_2:_Heroes_Of_Stalingrad/LevelDesign/RO2DestructionSystem&diff=1534Red Orchestra 2: Heroes Of Stalingrad/LevelDesign/RO2DestructionSystem2012-07-30T12:30:09Z<p>Keith: /* RODestructible */</p>
<hr />
<div>=Red Orchestra 2 Destructible Setup Guide=<br />
<br />
Red Orchestra 2 has a number of tools to facilitate destructible environments and/or objectives. This document is to serve as a means to understand how to set up the systems and why you would want to use each of the tools available.<br />
<br />
The topics covered in this document will be:<br />
<br />
*ROStaticMeshDestructible<br />
*ROStaticMeshReplicationInfo<br />
*ROObjectiveSatchel<br />
*ROStaticMeshObstacle<br />
*ROStaticMeshSatchelObstacle<br />
*RODestructible<br />
<br />
==ROStaticMeshDestructible==<br />
<br />
[[Image:ROStaticMeshDestructible_In_A_Map_Wireframe.jpg|thumb|300px|center|frame|ROStaticMeshDestructible in a Map]]<br />
<br />
[[Image:ROStaticMeshDestructible_In_The_Tree.jpg|thumb|300px|center|frame|In the Tree]]<br />
<br />
===Setup of ROStaticMeshDestuctible map actors===<br />
<br />
1) Select the base static mesh that will appear to the players in it's “undestroyed” state<br />
<br />
2) Select the map actor in the actor tree<br />
<br />
3) RMB → Add ROStaticMeshDestructible Here<br />
<br />
[[Image:ROStaticMeshDestructible_Add_To_Map.jpg|thumb|300px|center|Add to Map]]<br />
<br />
4) Open the properties of the newly place actor and find the StaticMeshComponent section of ROStaticMeshDestructible (Properties → ROStaticMeshDestructible → Destructible Mesh Component → StaticMeshComponent → Static Mesh) and replace the default static with the one selected in step 1. This is what is shown to the level designer in the editor.<br />
<br />
[[Image:ROStaticMeshDestructible_Add_To_Map_C.jpg|thumb|300px|center|Add to Map]]<br />
<br />
5) Open the RODestructibleStaticMeshComponent section of the properties<br />
<br />
[[Image:ROStaticMeshDestructible_Properties.jpg|thumb|300px|center|Destructible Properties]]<br />
<br />
6) Add at least two entries to the Destructible Assets list<br />
<br />
7) In the 0 section put the same base mesh as that of the Static Mesh. This is what will be shown to the players at runtime. NOTE: Use the Material Override to override the material that will be rendered in game. The LODMaterial Override should be used to override the materials on the LODs of the StaticMesh, if it exists, that will be rendered in game.<br />
<br />
8) In the 1 section put the destructed stage of the base static mesh. NOTE: You can add more than two stages but for each stage the lighting system will have to make a shadow map which can cause some bloat in map size. <br />
<br />
9) Under the Accepted Damage Types add the damage types you'd like to have effect the ROStaticMeshDestructible<br />
<br />
[[Image:ROStaticMeshDestructible_Properties_Component_C.jpg|thumb|300px|center|Accepted DamageType Example]]<br />
<br />
10) Set the appropriate value for Starting Health. If you'd like a tank to be able to run over the actor, give it a starting health of 1<br />
<br />
11) Set an appropriate emitter for the Destruction Emitter Template. This is what will be shown to the players when it changes states. The emitter will be spawned at the origin of the Static Mesh itself.<br />
<br />
12) Use the Destruction Emitter Offset values to adjust the spawn origin of the static mesh the origin of the Static Mesh being used is not in a good place for spawning an emitter<br />
<br />
13) If you would like the destructible to become active and interact with world space on destruction, set the Physics Static Mesh. NOTE: If you are going to have an active physics actors spawn instead of a destruction phase static mesh, leave the section in Step 8 empty.<br />
<br />
14) If there is cover that you would like to activate/deactivate upon stage change, you can add the cover references here. NOTE: ROStaticMeshDestructible and cover node must be in the same level. Usually the persistent. Use the Lock properties to allow selecting the cover node in the map without change the property window<br />
<br />
15) If you'd like to have multiple destructible static meshes to destroy even if they are not directly touched by the damage, add references to the ROStaticMeshDestructible to the Grouped Destructibles section of the properties. <br />
<br />
[[Image:ROStaticMeshDestructible_Properties_Component_D.jpg|thumb|300px|center|Other ROStaticMeshDestructible Properties]]<br />
<br />
==RODestructionReplicationInfo==<br />
<br />
The purpose of this actor is to provide a lighter weight replication solution for destructible actors in a map; instead of sending a lot of information from the server to the client to change the state of a destructible actor in a map this actor sends just the Integer value of the destructible in info structure. This makes it a little bit more intensive for the server when a large number of destructible map actors change state simultaneously but should not bog down the net code. <br />
<br />
===Rules of Thumb===<br />
<br />
1) No more than 300 destructible actors in each RODestructibleReplicationInfo actor<br />
<br />
2) Maps are not suggested to exceed 500 destructible actors<br />
<br />
3) No limitation of the number of RODestructibleReplicationInfo <br />
<br />
4) The RODestructibleReplicationInfo actor must be in the same level as the ROStaticMeshDestructible, usually the Persistent level.<br />
<br />
===Setting Up RODestructibleReplicationInfo Actors===<br />
<br />
1) Find and place a RODestructibleReplicationInfo Actor in your map<br />
<br />
[[Image:RODestructionReplicationInfo_Actor_In_A_Map.jpg|thumb|300px|center|RODestructibleReplicationInfo in a Map]]<br />
<br />
[[Image:RODestructionReplicationInfo_Actor_In_The_Tree.jpg|thumb|300px|center|RODestructibleReplicationInfo in the Actor tree]]<br />
<br />
2) Open the properties of the RODestructibleReplicationInfo actor and lock the properties<br />
<br />
[[Image:RODestructionReplicationInfo_Properties.jpg|thumb|300px|center|RODestructibleReplicationInfo Properties]]<br />
<br />
3) Open the Scene manager<br />
<br />
[[Image:SceneManager.jpg|thumb|300px|center|UE3 Scene Manager]]<br />
<br />
4) Select the persistent level<br />
<br />
5) Use the pulldown to select ROStaticMeshDestructible in the filter<br />
<br />
6) Add the appropriate number of slots to the replication actor (not exceeding 300)<br />
<br />
7) Select the first ROStaticMeshDestructible<br />
<br />
8) Add it to the first entry in the RODestructibleReplicationInfo actor<br />
<br />
9) Repeat steps 7-9 until you've either added all the ROStaticMeshDestructible actors in the map to the RODestructibleReplicationInfo actor or you've added 300 to the actor<br />
<br />
==Objective Based Destructible==<br />
This section covers how to setup objective based destructible solutions. <br />
<br />
===ROObjectiveSatchel===<br />
<br />
The purpose of the ROObjectiveSatchel is to allow for the capability for level designers to have objectives that “capture” upon destruction. It also allows for “proximity” capturing via a ROPlaceableVolume and otherwise functions 100% like a standard ROObjective.<br />
<br />
Setup of ROObjectiveSatchel<br />
<br />
1) Open the content browser and select a static mesh that you'd like to use for a ROObjectiveSatchel. Ideally this mesh will have it's origin centered on the object correctly (center, bottom-center, corner, etc).<br />
<br />
2) Find the ROObjectiveSatchel in the actor tree and place one in your map where you'd like the satchel objective to be<br />
<br />
3) Open the properties of the ROObjectiveSatchel and Expand the StaticMeshComponent section and replace the Static Mesh field with the mesh selected in Step 1<br />
<br />
[[Image:ROObjectiveSatchel_Properties_B.jpg|thumb|300px|center|Satchel Objective StaticMesh Properties]]<br />
<br />
4) Add at least two entries to the Destructible Assets list<br />
<br />
[[Image:ROObjectiveSatchel_Properties_A.jpg|thumb|300px|center|Satchel Objective Destructible Properties]]<br />
<br />
5) In the 0 section put the same base mesh as that of the Static Mesh. This is what will be shown to the players at runtime. NOTE: Use the Material Override to override the material that will be rendered in game. The LODMaterial Override should be used to override the materials on the LODs of the StaticMesh, if it exists, that will be rendered in game.<br />
<br />
6) In the 1 section put the destructed stage of the base static mesh. NOTE: You can add more than two stages but for each stage the lighting system will have to make a shadow map which can cause some bloat in map size. <br />
<br />
[[Image:ROObjectiveSatchel_Properties_D.jpg|thumb|300px|center|Satchel Objective Objective Properties]]<br />
<br />
7) Expand the ROObjective section and fill that out:<br />
<br />
Obj Index – this is a unique value that assigns the alphabetical assignment to the objective<br />
<br />
Obj Rep Index – this is a unique value that is used in replication. Usually this has the same value as the object name. For example, if the objective name is ROObjective_1 the Obj Rep Index will be 1<br />
<br />
Obj Name – this is localize name of the objective<br />
<br />
Obj Secondary Name – this is a internally used field that will be rendered on the overhead map. Any value here will be ignored in game. Best to leave it blank<br />
<br />
Obj Volume – this is the ROPlaceableVolume that is assigned to this objective for “proximity” capturing<br />
<br />
Map Zone Texture – this is a texture that is used as an overlay for the overhead map when the objective becomes active<br />
<br />
Minimum Capture Time – this time, in seconds, is the the amount of time it will take to capture the objective<br />
<br />
Initial Obj State – use the pulldown to select the initial defender state of the objective. NOTE: Neutral objective assignment for a ROObjectiveSatchel is not supported<br />
<br />
Lock Down Time 16/32/64 – these fields are deprecated and values assigned will not do anything<br />
<br />
Countdown Time – this is the amount of time the objective is active in the Countdown game mode, counted in seconds<br />
<br />
Is Key Objective – this bit is used in Countdown and gives an additional reinforcement for the commander<br />
<br />
Enable Lockdown – this bit is used to enable the procedural lockdown system in RO2<br />
<br />
Axis/Allies Priority – this is the order in which the AI will attack or defend the objectives. <br />
<br />
===RODamageOtherVolume===<br />
<br />
There is an additional supporting actor called a RODamageOtherVolume that allows of dropping the Satchel weapon (equipment for the engineering role) inside the volume. This overcomes the limitation that occurs when the origin of the SatchelObjective mesh is in a location to be “touched” by the explosion radius. For example, if the physical objective is inside a brick building but you'd like for the ability for the players to drop the satchel near the building and still destroy the objective.<br />
<br />
[[Image:RODamageOtherVolume_Properties.jpg|thumb|300px|center|DamageOtherVolume Properties]]<br />
<br />
Victim Actor: This points to the ROObjectiveSatchel that you'd like have accept the damage<br />
<br />
Damage Scale: A scale value of the damage applied to the Victim Actor<br />
<br />
Damage Types: The accepted damage types<br />
<br />
Ignore Damage Types: The damage types that should be ignored (usually to filter out subclasses of a damage type that won't damage the objective but the parent class will)<br />
<br />
==ROStaticMeshObstacle==<br />
<br />
These map actors are used to block off sections of NavMesh/Gamespace so that AI and players do not access certain areas of the map. Ideal use is when differentiating player loads between 16/32/64p matches<br />
<br />
===Setup of ROStaticMeshObstacle===<br />
<br />
1) Select a static mesh from the content browser<br />
<br />
2) Select ROStaticMeshObstacle from the Actor tree (Actor -> NavMeshObstacle -> ROStaticMeshObstacle)<br />
<br />
3) RMB -> Place ROStaticMeshObstacle here<br />
<br />
This should give you the static mesh you selected in Step 1 as a ROStaticMeshObstacle<br />
<br />
4) Select the newly create ROStaticMeshObstacle in the map<br />
<br />
5) Open Kismet and attach the ROStaticMeshObstacle to a Toggle action. Toggle ON to have it active Toggle OFF to have inactive<br />
<br />
What toggling does:<br />
<br />
A) Turns on/off navmesh beneath it's bounding box <br />
<br />
B) Turn on/off collision of the StaticMesh actor<br />
<br />
==ROStaticMeshSatchelObstacle==<br />
==RODestructible==<br />
<br />
This actor has been antiquated and removed from the Actor tree</div>Keithhttps://wiki.tripwireinteractive.com/index.php?title=Red_Orchestra_2:_Heroes_Of_Stalingrad/LevelDesign/RO2DestructionSystem&diff=1533Red Orchestra 2: Heroes Of Stalingrad/LevelDesign/RO2DestructionSystem2012-07-30T12:29:36Z<p>Keith: /* ROStaticMeshObstacle */</p>
<hr />
<div>=Red Orchestra 2 Destructible Setup Guide=<br />
<br />
Red Orchestra 2 has a number of tools to facilitate destructible environments and/or objectives. This document is to serve as a means to understand how to set up the systems and why you would want to use each of the tools available.<br />
<br />
The topics covered in this document will be:<br />
<br />
*ROStaticMeshDestructible<br />
*ROStaticMeshReplicationInfo<br />
*ROObjectiveSatchel<br />
*ROStaticMeshObstacle<br />
*ROStaticMeshSatchelObstacle<br />
*RODestructible<br />
<br />
==ROStaticMeshDestructible==<br />
<br />
[[Image:ROStaticMeshDestructible_In_A_Map_Wireframe.jpg|thumb|300px|center|frame|ROStaticMeshDestructible in a Map]]<br />
<br />
[[Image:ROStaticMeshDestructible_In_The_Tree.jpg|thumb|300px|center|frame|In the Tree]]<br />
<br />
===Setup of ROStaticMeshDestuctible map actors===<br />
<br />
1) Select the base static mesh that will appear to the players in it's “undestroyed” state<br />
<br />
2) Select the map actor in the actor tree<br />
<br />
3) RMB → Add ROStaticMeshDestructible Here<br />
<br />
[[Image:ROStaticMeshDestructible_Add_To_Map.jpg|thumb|300px|center|Add to Map]]<br />
<br />
4) Open the properties of the newly place actor and find the StaticMeshComponent section of ROStaticMeshDestructible (Properties → ROStaticMeshDestructible → Destructible Mesh Component → StaticMeshComponent → Static Mesh) and replace the default static with the one selected in step 1. This is what is shown to the level designer in the editor.<br />
<br />
[[Image:ROStaticMeshDestructible_Add_To_Map_C.jpg|thumb|300px|center|Add to Map]]<br />
<br />
5) Open the RODestructibleStaticMeshComponent section of the properties<br />
<br />
[[Image:ROStaticMeshDestructible_Properties.jpg|thumb|300px|center|Destructible Properties]]<br />
<br />
6) Add at least two entries to the Destructible Assets list<br />
<br />
7) In the 0 section put the same base mesh as that of the Static Mesh. This is what will be shown to the players at runtime. NOTE: Use the Material Override to override the material that will be rendered in game. The LODMaterial Override should be used to override the materials on the LODs of the StaticMesh, if it exists, that will be rendered in game.<br />
<br />
8) In the 1 section put the destructed stage of the base static mesh. NOTE: You can add more than two stages but for each stage the lighting system will have to make a shadow map which can cause some bloat in map size. <br />
<br />
9) Under the Accepted Damage Types add the damage types you'd like to have effect the ROStaticMeshDestructible<br />
<br />
[[Image:ROStaticMeshDestructible_Properties_Component_C.jpg|thumb|300px|center|Accepted DamageType Example]]<br />
<br />
10) Set the appropriate value for Starting Health. If you'd like a tank to be able to run over the actor, give it a starting health of 1<br />
<br />
11) Set an appropriate emitter for the Destruction Emitter Template. This is what will be shown to the players when it changes states. The emitter will be spawned at the origin of the Static Mesh itself.<br />
<br />
12) Use the Destruction Emitter Offset values to adjust the spawn origin of the static mesh the origin of the Static Mesh being used is not in a good place for spawning an emitter<br />
<br />
13) If you would like the destructible to become active and interact with world space on destruction, set the Physics Static Mesh. NOTE: If you are going to have an active physics actors spawn instead of a destruction phase static mesh, leave the section in Step 8 empty.<br />
<br />
14) If there is cover that you would like to activate/deactivate upon stage change, you can add the cover references here. NOTE: ROStaticMeshDestructible and cover node must be in the same level. Usually the persistent. Use the Lock properties to allow selecting the cover node in the map without change the property window<br />
<br />
15) If you'd like to have multiple destructible static meshes to destroy even if they are not directly touched by the damage, add references to the ROStaticMeshDestructible to the Grouped Destructibles section of the properties. <br />
<br />
[[Image:ROStaticMeshDestructible_Properties_Component_D.jpg|thumb|300px|center|Other ROStaticMeshDestructible Properties]]<br />
<br />
==RODestructionReplicationInfo==<br />
<br />
The purpose of this actor is to provide a lighter weight replication solution for destructible actors in a map; instead of sending a lot of information from the server to the client to change the state of a destructible actor in a map this actor sends just the Integer value of the destructible in info structure. This makes it a little bit more intensive for the server when a large number of destructible map actors change state simultaneously but should not bog down the net code. <br />
<br />
===Rules of Thumb===<br />
<br />
1) No more than 300 destructible actors in each RODestructibleReplicationInfo actor<br />
<br />
2) Maps are not suggested to exceed 500 destructible actors<br />
<br />
3) No limitation of the number of RODestructibleReplicationInfo <br />
<br />
4) The RODestructibleReplicationInfo actor must be in the same level as the ROStaticMeshDestructible, usually the Persistent level.<br />
<br />
===Setting Up RODestructibleReplicationInfo Actors===<br />
<br />
1) Find and place a RODestructibleReplicationInfo Actor in your map<br />
<br />
[[Image:RODestructionReplicationInfo_Actor_In_A_Map.jpg|thumb|300px|center|RODestructibleReplicationInfo in a Map]]<br />
<br />
[[Image:RODestructionReplicationInfo_Actor_In_The_Tree.jpg|thumb|300px|center|RODestructibleReplicationInfo in the Actor tree]]<br />
<br />
2) Open the properties of the RODestructibleReplicationInfo actor and lock the properties<br />
<br />
[[Image:RODestructionReplicationInfo_Properties.jpg|thumb|300px|center|RODestructibleReplicationInfo Properties]]<br />
<br />
3) Open the Scene manager<br />
<br />
[[Image:SceneManager.jpg|thumb|300px|center|UE3 Scene Manager]]<br />
<br />
4) Select the persistent level<br />
<br />
5) Use the pulldown to select ROStaticMeshDestructible in the filter<br />
<br />
6) Add the appropriate number of slots to the replication actor (not exceeding 300)<br />
<br />
7) Select the first ROStaticMeshDestructible<br />
<br />
8) Add it to the first entry in the RODestructibleReplicationInfo actor<br />
<br />
9) Repeat steps 7-9 until you've either added all the ROStaticMeshDestructible actors in the map to the RODestructibleReplicationInfo actor or you've added 300 to the actor<br />
<br />
==Objective Based Destructible==<br />
This section covers how to setup objective based destructible solutions. <br />
<br />
===ROObjectiveSatchel===<br />
<br />
The purpose of the ROObjectiveSatchel is to allow for the capability for level designers to have objectives that “capture” upon destruction. It also allows for “proximity” capturing via a ROPlaceableVolume and otherwise functions 100% like a standard ROObjective.<br />
<br />
Setup of ROObjectiveSatchel<br />
<br />
1) Open the content browser and select a static mesh that you'd like to use for a ROObjectiveSatchel. Ideally this mesh will have it's origin centered on the object correctly (center, bottom-center, corner, etc).<br />
<br />
2) Find the ROObjectiveSatchel in the actor tree and place one in your map where you'd like the satchel objective to be<br />
<br />
3) Open the properties of the ROObjectiveSatchel and Expand the StaticMeshComponent section and replace the Static Mesh field with the mesh selected in Step 1<br />
<br />
[[Image:ROObjectiveSatchel_Properties_B.jpg|thumb|300px|center|Satchel Objective StaticMesh Properties]]<br />
<br />
4) Add at least two entries to the Destructible Assets list<br />
<br />
[[Image:ROObjectiveSatchel_Properties_A.jpg|thumb|300px|center|Satchel Objective Destructible Properties]]<br />
<br />
5) In the 0 section put the same base mesh as that of the Static Mesh. This is what will be shown to the players at runtime. NOTE: Use the Material Override to override the material that will be rendered in game. The LODMaterial Override should be used to override the materials on the LODs of the StaticMesh, if it exists, that will be rendered in game.<br />
<br />
6) In the 1 section put the destructed stage of the base static mesh. NOTE: You can add more than two stages but for each stage the lighting system will have to make a shadow map which can cause some bloat in map size. <br />
<br />
[[Image:ROObjectiveSatchel_Properties_D.jpg|thumb|300px|center|Satchel Objective Objective Properties]]<br />
<br />
7) Expand the ROObjective section and fill that out:<br />
<br />
Obj Index – this is a unique value that assigns the alphabetical assignment to the objective<br />
<br />
Obj Rep Index – this is a unique value that is used in replication. Usually this has the same value as the object name. For example, if the objective name is ROObjective_1 the Obj Rep Index will be 1<br />
<br />
Obj Name – this is localize name of the objective<br />
<br />
Obj Secondary Name – this is a internally used field that will be rendered on the overhead map. Any value here will be ignored in game. Best to leave it blank<br />
<br />
Obj Volume – this is the ROPlaceableVolume that is assigned to this objective for “proximity” capturing<br />
<br />
Map Zone Texture – this is a texture that is used as an overlay for the overhead map when the objective becomes active<br />
<br />
Minimum Capture Time – this time, in seconds, is the the amount of time it will take to capture the objective<br />
<br />
Initial Obj State – use the pulldown to select the initial defender state of the objective. NOTE: Neutral objective assignment for a ROObjectiveSatchel is not supported<br />
<br />
Lock Down Time 16/32/64 – these fields are deprecated and values assigned will not do anything<br />
<br />
Countdown Time – this is the amount of time the objective is active in the Countdown game mode, counted in seconds<br />
<br />
Is Key Objective – this bit is used in Countdown and gives an additional reinforcement for the commander<br />
<br />
Enable Lockdown – this bit is used to enable the procedural lockdown system in RO2<br />
<br />
Axis/Allies Priority – this is the order in which the AI will attack or defend the objectives. <br />
<br />
===RODamageOtherVolume===<br />
<br />
There is an additional supporting actor called a RODamageOtherVolume that allows of dropping the Satchel weapon (equipment for the engineering role) inside the volume. This overcomes the limitation that occurs when the origin of the SatchelObjective mesh is in a location to be “touched” by the explosion radius. For example, if the physical objective is inside a brick building but you'd like for the ability for the players to drop the satchel near the building and still destroy the objective.<br />
<br />
[[Image:RODamageOtherVolume_Properties.jpg|thumb|300px|center|DamageOtherVolume Properties]]<br />
<br />
Victim Actor: This points to the ROObjectiveSatchel that you'd like have accept the damage<br />
<br />
Damage Scale: A scale value of the damage applied to the Victim Actor<br />
<br />
Damage Types: The accepted damage types<br />
<br />
Ignore Damage Types: The damage types that should be ignored (usually to filter out subclasses of a damage type that won't damage the objective but the parent class will)<br />
<br />
==ROStaticMeshObstacle==<br />
<br />
These map actors are used to block off sections of NavMesh/Gamespace so that AI and players do not access certain areas of the map. Ideal use is when differentiating player loads between 16/32/64p matches<br />
<br />
===Setup of ROStaticMeshObstacle===<br />
<br />
1) Select a static mesh from the content browser<br />
<br />
2) Select ROStaticMeshObstacle from the Actor tree (Actor -> NavMeshObstacle -> ROStaticMeshObstacle)<br />
<br />
3) RMB -> Place ROStaticMeshObstacle here<br />
<br />
This should give you the static mesh you selected in Step 1 as a ROStaticMeshObstacle<br />
<br />
4) Select the newly create ROStaticMeshObstacle in the map<br />
<br />
5) Open Kismet and attach the ROStaticMeshObstacle to a Toggle action. Toggle ON to have it active Toggle OFF to have inactive<br />
<br />
What toggling does:<br />
<br />
A) Turns on/off navmesh beneath it's bounding box <br />
<br />
B) Turn on/off collision of the StaticMesh actor<br />
<br />
==ROStaticMeshSatchelObstacle==<br />
==RODestructible==</div>Keithhttps://wiki.tripwireinteractive.com/index.php?title=Red_Orchestra_2:_Heroes_Of_Stalingrad/LevelDesign/RO2DestructionSystem&diff=1495Red Orchestra 2: Heroes Of Stalingrad/LevelDesign/RO2DestructionSystem2012-07-25T14:48:50Z<p>Keith: </p>
<hr />
<div>=Red Orchestra 2 Destructible Setup Guide=<br />
<br />
Red Orchestra 2 has a number of tools to facilitate destructible environments and/or objectives. This document is to serve as a means to understand how to set up the systems and why you would want to use each of the tools available.<br />
<br />
The topics covered in this document will be:<br />
<br />
*ROStaticMeshDestructible<br />
*ROStaticMeshReplicationInfo<br />
*ROObjectiveSatchel<br />
*ROStaticMeshObstacle<br />
*ROStaticMeshSatchelObstacle<br />
*RODestructible<br />
<br />
==ROStaticMeshDestructible==<br />
<br />
[[Image:ROStaticMeshDestructible_In_A_Map_Wireframe.jpg|thumb|300px|center|frame|ROStaticMeshDestructible in a Map]]<br />
<br />
[[Image:ROStaticMeshDestructible_In_The_Tree.jpg|thumb|300px|center|frame|In the Tree]]<br />
<br />
===Setup of ROStaticMeshDestuctible map actors===<br />
<br />
1) Select the base static mesh that will appear to the players in it's “undestroyed” state<br />
<br />
2) Select the map actor in the actor tree<br />
<br />
3) RMB → Add ROStaticMeshDestructible Here<br />
<br />
[[Image:ROStaticMeshDestructible_Add_To_Map.jpg|thumb|300px|center|Add to Map]]<br />
<br />
4) Open the properties of the newly place actor and find the StaticMeshComponent section of ROStaticMeshDestructible (Properties → ROStaticMeshDestructible → Destructible Mesh Component → StaticMeshComponent → Static Mesh) and replace the default static with the one selected in step 1. This is what is shown to the level designer in the editor.<br />
<br />
[[Image:ROStaticMeshDestructible_Add_To_Map_C.jpg|thumb|300px|center|Add to Map]]<br />
<br />
5) Open the RODestructibleStaticMeshComponent section of the properties<br />
<br />
[[Image:ROStaticMeshDestructible_Properties.jpg|thumb|300px|center|Destructible Properties]]<br />
<br />
6) Add at least two entries to the Destructible Assets list<br />
<br />
7) In the 0 section put the same base mesh as that of the Static Mesh. This is what will be shown to the players at runtime. NOTE: Use the Material Override to override the material that will be rendered in game. The LODMaterial Override should be used to override the materials on the LODs of the StaticMesh, if it exists, that will be rendered in game.<br />
<br />
8) In the 1 section put the destructed stage of the base static mesh. NOTE: You can add more than two stages but for each stage the lighting system will have to make a shadow map which can cause some bloat in map size. <br />
<br />
9) Under the Accepted Damage Types add the damage types you'd like to have effect the ROStaticMeshDestructible<br />
<br />
[[Image:ROStaticMeshDestructible_Properties_Component_C.jpg|thumb|300px|center|Accepted DamageType Example]]<br />
<br />
10) Set the appropriate value for Starting Health. If you'd like a tank to be able to run over the actor, give it a starting health of 1<br />
<br />
11) Set an appropriate emitter for the Destruction Emitter Template. This is what will be shown to the players when it changes states. The emitter will be spawned at the origin of the Static Mesh itself.<br />
<br />
12) Use the Destruction Emitter Offset values to adjust the spawn origin of the static mesh the origin of the Static Mesh being used is not in a good place for spawning an emitter<br />
<br />
13) If you would like the destructible to become active and interact with world space on destruction, set the Physics Static Mesh. NOTE: If you are going to have an active physics actors spawn instead of a destruction phase static mesh, leave the section in Step 8 empty.<br />
<br />
14) If there is cover that you would like to activate/deactivate upon stage change, you can add the cover references here. NOTE: ROStaticMeshDestructible and cover node must be in the same level. Usually the persistent. Use the Lock properties to allow selecting the cover node in the map without change the property window<br />
<br />
15) If you'd like to have multiple destructible static meshes to destroy even if they are not directly touched by the damage, add references to the ROStaticMeshDestructible to the Grouped Destructibles section of the properties. <br />
<br />
[[Image:ROStaticMeshDestructible_Properties_Component_D.jpg|thumb|300px|center|Other ROStaticMeshDestructible Properties]]<br />
<br />
==RODestructionReplicationInfo==<br />
<br />
The purpose of this actor is to provide a lighter weight replication solution for destructible actors in a map; instead of sending a lot of information from the server to the client to change the state of a destructible actor in a map this actor sends just the Integer value of the destructible in info structure. This makes it a little bit more intensive for the server when a large number of destructible map actors change state simultaneously but should not bog down the net code. <br />
<br />
===Rules of Thumb===<br />
<br />
1) No more than 300 destructible actors in each RODestructibleReplicationInfo actor<br />
<br />
2) Maps are not suggested to exceed 500 destructible actors<br />
<br />
3) No limitation of the number of RODestructibleReplicationInfo <br />
<br />
4) The RODestructibleReplicationInfo actor must be in the same level as the ROStaticMeshDestructible, usually the Persistent level.<br />
<br />
===Setting Up RODestructibleReplicationInfo Actors===<br />
<br />
1) Find and place a RODestructibleReplicationInfo Actor in your map<br />
<br />
[[Image:RODestructionReplicationInfo_Actor_In_A_Map.jpg|thumb|300px|center|RODestructibleReplicationInfo in a Map]]<br />
<br />
[[Image:RODestructionReplicationInfo_Actor_In_The_Tree.jpg|thumb|300px|center|RODestructibleReplicationInfo in the Actor tree]]<br />
<br />
2) Open the properties of the RODestructibleReplicationInfo actor and lock the properties<br />
<br />
[[Image:RODestructionReplicationInfo_Properties.jpg|thumb|300px|center|RODestructibleReplicationInfo Properties]]<br />
<br />
3) Open the Scene manager<br />
<br />
[[Image:SceneManager.jpg|thumb|300px|center|UE3 Scene Manager]]<br />
<br />
4) Select the persistent level<br />
<br />
5) Use the pulldown to select ROStaticMeshDestructible in the filter<br />
<br />
6) Add the appropriate number of slots to the replication actor (not exceeding 300)<br />
<br />
7) Select the first ROStaticMeshDestructible<br />
<br />
8) Add it to the first entry in the RODestructibleReplicationInfo actor<br />
<br />
9) Repeat steps 7-9 until you've either added all the ROStaticMeshDestructible actors in the map to the RODestructibleReplicationInfo actor or you've added 300 to the actor<br />
<br />
==Objective Based Destructible==<br />
This section covers how to setup objective based destructible solutions. <br />
<br />
===ROObjectiveSatchel===<br />
<br />
The purpose of the ROObjectiveSatchel is to allow for the capability for level designers to have objectives that “capture” upon destruction. It also allows for “proximity” capturing via a ROPlaceableVolume and otherwise functions 100% like a standard ROObjective.<br />
<br />
Setup of ROObjectiveSatchel<br />
<br />
1) Open the content browser and select a static mesh that you'd like to use for a ROObjectiveSatchel. Ideally this mesh will have it's origin centered on the object correctly (center, bottom-center, corner, etc).<br />
<br />
2) Find the ROObjectiveSatchel in the actor tree and place one in your map where you'd like the satchel objective to be<br />
<br />
3) Open the properties of the ROObjectiveSatchel and Expand the StaticMeshComponent section and replace the Static Mesh field with the mesh selected in Step 1<br />
<br />
[[Image:ROObjectiveSatchel_Properties_B.jpg|thumb|300px|center|Satchel Objective StaticMesh Properties]]<br />
<br />
4) Add at least two entries to the Destructible Assets list<br />
<br />
[[Image:ROObjectiveSatchel_Properties_A.jpg|thumb|300px|center|Satchel Objective Destructible Properties]]<br />
<br />
5) In the 0 section put the same base mesh as that of the Static Mesh. This is what will be shown to the players at runtime. NOTE: Use the Material Override to override the material that will be rendered in game. The LODMaterial Override should be used to override the materials on the LODs of the StaticMesh, if it exists, that will be rendered in game.<br />
<br />
6) In the 1 section put the destructed stage of the base static mesh. NOTE: You can add more than two stages but for each stage the lighting system will have to make a shadow map which can cause some bloat in map size. <br />
<br />
[[Image:ROObjectiveSatchel_Properties_D.jpg|thumb|300px|center|Satchel Objective Objective Properties]]<br />
<br />
7) Expand the ROObjective section and fill that out:<br />
<br />
Obj Index – this is a unique value that assigns the alphabetical assignment to the objective<br />
<br />
Obj Rep Index – this is a unique value that is used in replication. Usually this has the same value as the object name. For example, if the objective name is ROObjective_1 the Obj Rep Index will be 1<br />
<br />
Obj Name – this is localize name of the objective<br />
<br />
Obj Secondary Name – this is a internally used field that will be rendered on the overhead map. Any value here will be ignored in game. Best to leave it blank<br />
<br />
Obj Volume – this is the ROPlaceableVolume that is assigned to this objective for “proximity” capturing<br />
<br />
Map Zone Texture – this is a texture that is used as an overlay for the overhead map when the objective becomes active<br />
<br />
Minimum Capture Time – this time, in seconds, is the the amount of time it will take to capture the objective<br />
<br />
Initial Obj State – use the pulldown to select the initial defender state of the objective. NOTE: Neutral objective assignment for a ROObjectiveSatchel is not supported<br />
<br />
Lock Down Time 16/32/64 – these fields are deprecated and values assigned will not do anything<br />
<br />
Countdown Time – this is the amount of time the objective is active in the Countdown game mode, counted in seconds<br />
<br />
Is Key Objective – this bit is used in Countdown and gives an additional reinforcement for the commander<br />
<br />
Enable Lockdown – this bit is used to enable the procedural lockdown system in RO2<br />
<br />
Axis/Allies Priority – this is the order in which the AI will attack or defend the objectives. <br />
<br />
===RODamageOtherVolume===<br />
<br />
There is an additional supporting actor called a RODamageOtherVolume that allows of dropping the Satchel weapon (equipment for the engineering role) inside the volume. This overcomes the limitation that occurs when the origin of the SatchelObjective mesh is in a location to be “touched” by the explosion radius. For example, if the physical objective is inside a brick building but you'd like for the ability for the players to drop the satchel near the building and still destroy the objective.<br />
<br />
[[Image:RODamageOtherVolume_Properties.jpg|thumb|300px|center|DamageOtherVolume Properties]]<br />
<br />
Victim Actor: This points to the ROObjectiveSatchel that you'd like have accept the damage<br />
<br />
Damage Scale: A scale value of the damage applied to the Victim Actor<br />
<br />
Damage Types: The accepted damage types<br />
<br />
Ignore Damage Types: The damage types that should be ignored (usually to filter out subclasses of a damage type that won't damage the objective but the parent class will)<br />
<br />
==ROStaticMeshObstacle==<br />
==ROStaticMeshSatchelObstacle==<br />
==RODestructible==</div>Keithhttps://wiki.tripwireinteractive.com/index.php?title=Red_Orchestra_2:_Heroes_Of_Stalingrad/LevelDesign/RO2DestructionSystem&diff=1494Red Orchestra 2: Heroes Of Stalingrad/LevelDesign/RO2DestructionSystem2012-07-25T14:38:11Z<p>Keith: /* ROStaticMeshDestructible */</p>
<hr />
<div>=Red Orchestra 2 Destructible Setup Guide=<br />
<br />
Red Orchestra 2 has a number of tools to facilitate destructible environments and/or objectives. This document is to serve as a means to understand how to set up the systems and why you would want to use each of the tools available.<br />
<br />
The topics covered in this document will be:<br />
<br />
*ROStaticMeshDestructible<br />
*ROStaticMeshReplicationInfo<br />
*ROObjectiveSatchel<br />
*ROStaticMeshObstacle<br />
*ROStaticMeshSatchelObstacle<br />
*RODestructible<br />
<br />
==ROStaticMeshDestructible==<br />
<br />
[[Image:ROStaticMeshDestructible_In_A_Map_Wireframe.jpg|thumb|300px|center|frame|ROStaticMeshDestructible in a Map]]<br />
<br />
[[Image:ROStaticMeshDestructible_In_The_Tree.jpg|thumb|300px|center|frame|In the Tree]]<br />
<br />
===Setup of ROStaticMeshDestuctible map actors===<br />
<br />
1) Select the base static mesh that will appear to the players in it's “undestroyed” state<br />
<br />
2) Select the map actor in the actor tree<br />
<br />
3) RMB → Add ROStaticMeshDestructible Here<br />
<br />
[[Image:ROStaticMeshDestructible_Add_To_Map.jpg|thumb|300px|center|Add to Map]]<br />
<br />
4) Open the properties of the newly place actor and find the StaticMeshComponent section of ROStaticMeshDestructible (Properties → ROStaticMeshDestructible → Destructible Mesh Component → StaticMeshComponent → Static Mesh) and replace the default static with the one selected in step 1. This is what is shown to the level designer in the editor.<br />
<br />
[[Image:ROStaticMeshDestructible_Add_To_Map_C.jpg|thumb|300px|center|Add to Map]]<br />
<br />
5) Open the RODestructibleStaticMeshComponent section of the properties<br />
<br />
[[Image:ROStaticMeshDestructible_Properties.jpg|thumb|300px|center|Destructible Properties]]<br />
<br />
6) Add at least two entries to the Destructible Assets list<br />
<br />
7) In the 0 section put the same base mesh as that of the Static Mesh. This is what will be shown to the players at runtime. NOTE: Use the Material Override to override the material that will be rendered in game. The LODMaterial Override should be used to override the materials on the LODs of the StaticMesh, if it exists, that will be rendered in game.<br />
<br />
8) In the 1 section put the destructed stage of the base static mesh. NOTE: You can add more than two stages but for each stage the lighting system will have to make a shadow map which can cause some bloat in map size. <br />
<br />
9) Under the Accepted Damage Types add the damage types you'd like to have effect the ROStaticMeshDestructible<br />
<br />
[[Image:ROStaticMeshDestructible_Properties_Component_C.jpg|thumb|300px|center|Accepted DamageType Example]]<br />
<br />
10) Set the appropriate value for Starting Health. If you'd like a tank to be able to run over the actor, give it a starting health of 1<br />
<br />
11) Set an appropriate emitter for the Destruction Emitter Template. This is what will be shown to the players when it changes states. The emitter will be spawned at the origin of the Static Mesh itself.<br />
<br />
12) Use the Destruction Emitter Offset values to adjust the spawn origin of the static mesh the origin of the Static Mesh being used is not in a good place for spawning an emitter<br />
<br />
13) If you would like the destructible to become active and interact with world space on destruction, set the Physics Static Mesh. NOTE: If you are going to have an active physics actors spawn instead of a destruction phase static mesh, leave the section in Step 8 empty.<br />
<br />
14) If there is cover that you would like to activate/deactivate upon stage change, you can add the cover references here. NOTE: ROStaticMeshDestructible and cover node must be in the same level. Usually the persistent. Use the Lock properties to allow selecting the cover node in the map without change the property window<br />
<br />
15) If you'd like to have multiple destructible static meshes to destroy even if they are not directly touched by the damage, add references to the ROStaticMeshDestructible to the Grouped Destructibles section of the properties. <br />
<br />
[[Image:ROStaticMeshDestructible_Properties_Component_D.jpg|thumb|300px|center|Other ROStaticMeshDestructible Properties]]<br />
<br />
==RODestructionReplicationInfo==<br />
<br />
The purpose of this actor is to provide a lighter weight replication solution for destructible actors in a map; instead of sending a lot of information from the server to the client to change the state of a destructible actor in a map this actor sends just the Integer value of the destructible in info structure. This makes it a little bit more intensive for the server when a large number of destructible map actors change state simultaneously but should not bog down the net code. <br />
<br />
===Rules of Thumb===<br />
<br />
1) No more than 300 destructible actors in each RODestructibleReplicationInfo actor<br />
<br />
2) Maps are not suggested to exceed 500 destructible actors<br />
<br />
3) No limitation of the number of RODestructibleReplicationInfo <br />
<br />
4) The RODestructibleReplicationInfo actor must be in the same level as the ROStaticMeshDestructible, usually the Persistent level.<br />
<br />
===Setting Up RODestructibleReplicationInfo Actors===<br />
<br />
1) Find and place a RODestructibleReplicationInfo Actor in your map<br />
<br />
[[Image:RODestructionReplicationInfo_Actor_In_A_Map.jpg|thumb|300px|center|RODestructibleReplicationInfo in a Map]]<br />
<br />
[[Image:RODestructionReplicationInfo_Actor_In_The_Tree.jpg|thumb|300px|center|RODestructibleReplicationInfo in the Actor tree]]<br />
<br />
2) Open the properties of the RODestructibleReplicationInfo actor and lock the properties<br />
<br />
[[Image:RODestructionReplicationInfo_Properties.jpg|thumb|300px|center|RODestructibleReplicationInfo Properties]]<br />
<br />
3) Open the Scene manager<br />
<br />
[[Image:SceneManager.jpg|thumb|300px|center|UE3 Scene Manager]]<br />
<br />
4) Select the persistent level<br />
<br />
5) Use the pulldown to select ROStaticMeshDestructible in the filter<br />
<br />
6) Add the appropriate number of slots to the replication actor (not exceeding 300)<br />
<br />
7) Select the first ROStaticMeshDestructible<br />
<br />
8) Add it to the first entry in the RODestructibleReplicationInfo actor<br />
<br />
9) Repeat steps 7-9 until you've either added all the ROStaticMeshDestructible actors in the map to the RODestructibleReplicationInfo actor or you've added 300 to the actor<br />
<br />
==Objective Based Destructible==<br />
This section covers how to setup objective based destructible solutions. <br />
<br />
===ROObjectiveSatchel===<br />
<br />
The purpose of the ROObjectiveSatchel is to allow for the capability for level designers to have objectives that “capture” upon destruction. It also allows for “proximity” capturing via a ROPlaceableVolume and otherwise functions 100% like a standard ROObjective.<br />
<br />
Setup of ROObjectiveSatchel<br />
<br />
1) Open the content browser and select a static mesh that you'd like to use for a ROObjectiveSatchel. Ideally this mesh will have it's origin centered on the object correctly (center, bottom-center, corner, etc).<br />
<br />
2) Find the ROObjectiveSatchel in the actor tree and place one in your map where you'd like the satchel objective to be<br />
<br />
3) Open the properties of the ROObjectiveSatchel and Expand the StaticMeshComponent section and replace the Static Mesh field with the mesh selected in Step 1<br />
<br />
[[Image:ROObjectiveSatchel_Properties_B.jpg|thumb|300px|center|Satchel Objective StaticMesh Properties]]<br />
<br />
4) Add at least two entries to the Destructible Assets list<br />
<br />
[[Image:ROObjectiveSatchel_Properties_A.jpg|thumb|300px|center|Satchel Objective Destructible Properties]]<br />
<br />
5) In the 0 section put the same base mesh as that of the Static Mesh. This is what will be shown to the players at runtime. NOTE: Use the Material Override to override the material that will be rendered in game. The LODMaterial Override should be used to override the materials on the LODs of the StaticMesh, if it exists, that will be rendered in game.<br />
<br />
6) In the 1 section put the destructed stage of the base static mesh. NOTE: You can add more than two stages but for each stage the lighting system will have to make a shadow map which can cause some bloat in map size. <br />
<br />
[[Image:ROObjectiveSatchel_Properties_D.jpg|thumb|300px|center|Satchel Objective Objective Properties]]<br />
<br />
7) Expand the ROObjective section and fill that out:<br />
<br />
Obj Index – this is a unique value that assigns the alphabetical assignment to the objective<br />
<br />
Obj Rep Index – this is a unique value that is used in replication. Usually this has the same value as the object name. For example, if the objective name is ROObjective_1 the Obj Rep Index will be 1<br />
<br />
Obj Name – this is localize name of the objective<br />
<br />
Obj Secondary Name – this is a internally used field that will be rendered on the overhead map. Any value here will be ignored in game. Best to leave it blank<br />
<br />
Obj Volume – this is the ROPlaceableVolume that is assigned to this objective for “proximity” capturing<br />
<br />
Map Zone Texture – this is a texture that is used as an overlay for the overhead map when the objective becomes active<br />
<br />
Minimum Capture Time – this time, in seconds, is the the amount of time it will take to capture the objective<br />
<br />
Initial Obj State – use the pulldown to select the initial defender state of the objective. NOTE: Neutral objective assignment for a ROObjectiveSatchel is not supported<br />
<br />
Lock Down Time 16/32/64 – these fields are deprecated and values assigned will not do anything<br />
<br />
Countdown Time – this is the amount of time the objective is active in the Countdown game mode, counted in seconds<br />
<br />
Is Key Objective – this bit is used in Countdown and gives an additional reinforcement for the commander<br />
<br />
Enable Lockdown – this bit is used to enable the procedural lockdown system in RO2<br />
<br />
Axis/Allies Priority – this is the order in which the AI will attack or defend the objectives. <br />
<br />
===RODamageOtherVolume===<br />
<br />
There is an additional supporting actor called a RODamageOtherVolume that allows of dropping the Satchel weapon (equipment for the engineering role) inside the volume. This overcomes the limitation that occurs when the origin of the SatchelObjective mesh is in a location to be “touched” by the explosion radius. For example, if the physical objective is inside a brick building but you'd like for the ability for the players to drop the satchel near the building and still destroy the objective.<br />
<br />
[[Image:RODamageOtherVolume_Properties.jpg|thumb|300px|center|DamageOtherVolume Properties]]<br />
<br />
Victim Actor: This points to the ROObjectiveSatchel that you'd like have accept the damage<br />
<br />
Damage Scale: A scale value of the damage applied to the Victim Actor<br />
<br />
Damage Types: The accepted damage types<br />
<br />
Ignore Damage Types: The damage types that should be ignored (usually to filter out subclasses of a damage type that won't damage the objective but the parent class will)</div>Keithhttps://wiki.tripwireinteractive.com/index.php?title=File:ROObjectiveSatchel_Properties_A.jpg&diff=1493File:ROObjectiveSatchel Properties A.jpg2012-07-25T14:33:58Z<p>Keith: </p>
<hr />
<div></div>Keithhttps://wiki.tripwireinteractive.com/index.php?title=File:RODamageOtherVolume_Properties.jpg&diff=1492File:RODamageOtherVolume Properties.jpg2012-07-25T14:33:31Z<p>Keith: </p>
<hr />
<div></div>Keithhttps://wiki.tripwireinteractive.com/index.php?title=File:ROObjectiveSatchel_Properties_D.jpg&diff=1491File:ROObjectiveSatchel Properties D.jpg2012-07-25T14:33:14Z<p>Keith: </p>
<hr />
<div></div>Keithhttps://wiki.tripwireinteractive.com/index.php?title=File:ROObjectiveSatchel_Properties_B.jpg&diff=1490File:ROObjectiveSatchel Properties B.jpg2012-07-25T14:33:05Z<p>Keith: </p>
<hr />
<div></div>Keithhttps://wiki.tripwireinteractive.com/index.php?title=File:SceneManager.jpg&diff=1489File:SceneManager.jpg2012-07-25T14:32:53Z<p>Keith: </p>
<hr />
<div></div>Keithhttps://wiki.tripwireinteractive.com/index.php?title=File:RODestructionReplicationInfo_Properties.jpg&diff=1488File:RODestructionReplicationInfo Properties.jpg2012-07-25T14:32:47Z<p>Keith: </p>
<hr />
<div></div>Keithhttps://wiki.tripwireinteractive.com/index.php?title=File:RODestructionReplicationInfo_Actor_In_The_Tree.jpg&diff=1487File:RODestructionReplicationInfo Actor In The Tree.jpg2012-07-25T14:32:14Z<p>Keith: </p>
<hr />
<div></div>Keithhttps://wiki.tripwireinteractive.com/index.php?title=File:RODestructionReplicationInfo_Actor_In_A_Map.jpg&diff=1486File:RODestructionReplicationInfo Actor In A Map.jpg2012-07-25T14:32:03Z<p>Keith: </p>
<hr />
<div></div>Keithhttps://wiki.tripwireinteractive.com/index.php?title=File:ROStaticMeshDestructible_Properties_Component_D.jpg&diff=1485File:ROStaticMeshDestructible Properties Component D.jpg2012-07-25T14:31:53Z<p>Keith: </p>
<hr />
<div></div>Keithhttps://wiki.tripwireinteractive.com/index.php?title=File:ROStaticMeshDestructible_Properties_Component_C.jpg&diff=1484File:ROStaticMeshDestructible Properties Component C.jpg2012-07-25T14:31:22Z<p>Keith: </p>
<hr />
<div></div>Keithhttps://wiki.tripwireinteractive.com/index.php?title=File:ROStaticMeshDestructible_Properties.jpg&diff=1483File:ROStaticMeshDestructible Properties.jpg2012-07-25T14:31:14Z<p>Keith: </p>
<hr />
<div></div>Keithhttps://wiki.tripwireinteractive.com/index.php?title=File:ROStaticMeshDestructible_Add_To_Map_C.jpg&diff=1482File:ROStaticMeshDestructible Add To Map C.jpg2012-07-25T14:30:54Z<p>Keith: </p>
<hr />
<div></div>Keithhttps://wiki.tripwireinteractive.com/index.php?title=File:ROStaticMeshDestructible_Add_To_Map.jpg&diff=1481File:ROStaticMeshDestructible Add To Map.jpg2012-07-25T14:30:29Z<p>Keith: </p>
<hr />
<div></div>Keithhttps://wiki.tripwireinteractive.com/index.php?title=File:ROStaticMeshDestructible_In_The_Tree.jpg&diff=1480File:ROStaticMeshDestructible In The Tree.jpg2012-07-25T14:29:34Z<p>Keith: </p>
<hr />
<div></div>Keithhttps://wiki.tripwireinteractive.com/index.php?title=File:ROStaticMeshDestructible_In_A_Map_Wireframe.jpg&diff=1479File:ROStaticMeshDestructible In A Map Wireframe.jpg2012-07-25T14:29:16Z<p>Keith: Keith uploaded a new version of &quot;File:ROStaticMeshDestructible In A Map Wireframe.jpg&quot;</p>
<hr />
<div></div>Keithhttps://wiki.tripwireinteractive.com/index.php?title=File:ROStaticMeshDestructible_In_A_Map_Wireframe.jpg&diff=1478File:ROStaticMeshDestructible In A Map Wireframe.jpg2012-07-25T14:28:00Z<p>Keith: </p>
<hr />
<div></div>Keithhttps://wiki.tripwireinteractive.com/index.php?title=Red_Orchestra_2:_Heroes_Of_Stalingrad/LevelDesign/RO2DestructionSystem&diff=1477Red Orchestra 2: Heroes Of Stalingrad/LevelDesign/RO2DestructionSystem2012-07-25T14:27:19Z<p>Keith: </p>
<hr />
<div>=Red Orchestra 2 Destructible Setup Guide=<br />
<br />
Red Orchestra 2 has a number of tools to facilitate destructible environments and/or objectives. This document is to serve as a means to understand how to set up the systems and why you would want to use each of the tools available.<br />
<br />
The topics covered in this document will be:<br />
<br />
*ROStaticMeshDestructible<br />
*ROStaticMeshReplicationInfo<br />
*ROObjectiveSatchel<br />
*ROStaticMeshObstacle<br />
*ROStaticMeshSatchelObstacle<br />
*RODestructible<br />
<br />
==ROStaticMeshDestructible==<br />
<br />
This actor is used by level designers to place destructible assets in their maps.<br />
<br />
<br />
[[Image:ROStaticMeshDestructible_In_A_Map_Wireframe.jpg|thumb|300px|center|ROStaticMeshDestructible in a Map]]<br />
<br />
[[Image:ROStaticMeshDestructible_In_The_Tree.jpg|thumb|300px|center|In the Tree]]<br />
<br />
===Setup of ROStaticMeshDestuctible map actors===<br />
<br />
1) Select the base static mesh that will appear to the players in it's “undestroyed” state<br />
<br />
2) Select the map actor in the actor tree<br />
<br />
3) RMB → Add ROStaticMeshDestructible Here<br />
<br />
[[Image:ROStaticMeshDestructible_Add_To_Map.jpg|thumb|300px|center|Add to Map]]<br />
<br />
4) Open the properties of the newly place actor and find the StaticMeshComponent section of ROStaticMeshDestructible (Properties → ROStaticMeshDestructible → Destructible Mesh Component → StaticMeshComponent → Static Mesh) and replace the default static with the one selected in step 1. This is what is shown to the level designer in the editor.<br />
<br />
[[Image:ROStaticMeshDestructible_Add_To_Map_C.jpg|thumb|300px|center|Add to Map]]<br />
<br />
5) Open the RODestructibleStaticMeshComponent section of the properties<br />
<br />
[[Image:ROStaticMeshDestructible_Properties.jpg|thumb|300px|center|Destructible Properties]]<br />
<br />
6) Add at least two entries to the Destructible Assets list<br />
<br />
7) In the 0 section put the same base mesh as that of the Static Mesh. This is what will be shown to the players at runtime. NOTE: Use the Material Override to override the material that will be rendered in game. The LODMaterial Override should be used to override the materials on the LODs of the StaticMesh, if it exists, that will be rendered in game.<br />
<br />
8) In the 1 section put the destructed stage of the base static mesh. NOTE: You can add more than two stages but for each stage the lighting system will have to make a shadow map which can cause some bloat in map size. <br />
<br />
9) Under the Accepted Damage Types add the damage types you'd like to have effect the ROStaticMeshDestructible<br />
<br />
[[Image:ROStaticMeshDestructible_Properties_Component_C.jpg|thumb|300px|center|Accepted DamageType Example]]<br />
<br />
10) Set the appropriate value for Starting Health. If you'd like a tank to be able to run over the actor, give it a starting health of 1<br />
<br />
11) Set an appropriate emitter for the Destruction Emitter Template. This is what will be shown to the players when it changes states. The emitter will be spawned at the origin of the Static Mesh itself.<br />
<br />
12) Use the Destruction Emitter Offset values to adjust the spawn origin of the static mesh the origin of the Static Mesh being used is not in a good place for spawning an emitter<br />
<br />
13) If you would like the destructible to become active and interact with world space on destruction, set the Physics Static Mesh. NOTE: If you are going to have an active physics actors spawn instead of a destruction phase static mesh, leave the section in Step 8 empty.<br />
<br />
14) If there is cover that you would like to activate/deactivate upon stage change, you can add the cover references here. NOTE: ROStaticMeshDestructible and cover node must be in the same level. Usually the persistent. Use the Lock properties to allow selecting the cover node in the map without change the property window<br />
<br />
15) If you'd like to have multiple destructible static meshes to destroy even if they are not directly touched by the damage, add references to the ROStaticMeshDestructible to the Grouped Destructibles section of the properties. <br />
<br />
[[Image:ROStaticMeshDestructible_Properties_Component_D.jpg|thumb|300px|center|Other ROStaticMeshDestructible Properties]]<br />
<br />
<br />
<br />
==RODestructionReplicationInfo==<br />
<br />
The purpose of this actor is to provide a lighter weight replication solution for destructible actors in a map; instead of sending a lot of information from the server to the client to change the state of a destructible actor in a map this actor sends just the Integer value of the destructible in info structure. This makes it a little bit more intensive for the server when a large number of destructible map actors change state simultaneously but should not bog down the net code. <br />
<br />
===Rules of Thumb===<br />
<br />
1) No more than 300 destructible actors in each RODestructibleReplicationInfo actor<br />
<br />
2) Maps are not suggested to exceed 500 destructible actors<br />
<br />
3) No limitation of the number of RODestructibleReplicationInfo <br />
<br />
4) The RODestructibleReplicationInfo actor must be in the same level as the ROStaticMeshDestructible, usually the Persistent level.<br />
<br />
===Setting Up RODestructibleReplicationInfo Actors===<br />
<br />
1) Find and place a RODestructibleReplicationInfo Actor in your map<br />
<br />
[[Image:RODestructionReplicationInfo_Actor_In_A_Map.jpg|thumb|300px|center|RODestructibleReplicationInfo in a Map]]<br />
<br />
[[Image:RODestructionReplicationInfo_Actor_In_The_Tree.jpg|thumb|300px|center|RODestructibleReplicationInfo in the Actor tree]]<br />
<br />
2) Open the properties of the RODestructibleReplicationInfo actor and lock the properties<br />
<br />
[[Image:RODestructionReplicationInfo_Properties.jpg|thumb|300px|center|RODestructibleReplicationInfo Properties]]<br />
<br />
3) Open the Scene manager<br />
<br />
[[Image:SceneManager.jpg|thumb|300px|center|UE3 Scene Manager]]<br />
<br />
4) Select the persistent level<br />
<br />
5) Use the pulldown to select ROStaticMeshDestructible in the filter<br />
<br />
6) Add the appropriate number of slots to the replication actor (not exceeding 300)<br />
<br />
7) Select the first ROStaticMeshDestructible<br />
<br />
8) Add it to the first entry in the RODestructibleReplicationInfo actor<br />
<br />
9) Repeat steps 7-9 until you've either added all the ROStaticMeshDestructible actors in the map to the RODestructibleReplicationInfo actor or you've added 300 to the actor<br />
<br />
==Objective Based Destructible==<br />
This section covers how to setup objective based destructible solutions. <br />
<br />
===ROObjectiveSatchel===<br />
<br />
The purpose of the ROObjectiveSatchel is to allow for the capability for level designers to have objectives that “capture” upon destruction. It also allows for “proximity” capturing via a ROPlaceableVolume and otherwise functions 100% like a standard ROObjective.<br />
<br />
Setup of ROObjectiveSatchel<br />
<br />
1) Open the content browser and select a static mesh that you'd like to use for a ROObjectiveSatchel. Ideally this mesh will have it's origin centered on the object correctly (center, bottom-center, corner, etc).<br />
<br />
2) Find the ROObjectiveSatchel in the actor tree and place one in your map where you'd like the satchel objective to be<br />
<br />
3) Open the properties of the ROObjectiveSatchel and Expand the StaticMeshComponent section and replace the Static Mesh field with the mesh selected in Step 1<br />
<br />
[[Image:ROObjectiveSatchel_Properties_B.jpg|thumb|300px|center|Satchel Objective StaticMesh Properties]]<br />
<br />
4) Add at least two entries to the Destructible Assets list<br />
<br />
[[Image:ROObjectiveSatchel_Properties_A.jpg|thumb|300px|center|Satchel Objective Destructible Properties]]<br />
<br />
5) In the 0 section put the same base mesh as that of the Static Mesh. This is what will be shown to the players at runtime. NOTE: Use the Material Override to override the material that will be rendered in game. The LODMaterial Override should be used to override the materials on the LODs of the StaticMesh, if it exists, that will be rendered in game.<br />
<br />
6) In the 1 section put the destructed stage of the base static mesh. NOTE: You can add more than two stages but for each stage the lighting system will have to make a shadow map which can cause some bloat in map size. <br />
<br />
[[Image:ROObjectiveSatchel_Properties_D.jpg|thumb|300px|center|Satchel Objective Objective Properties]]<br />
<br />
7) Expand the ROObjective section and fill that out:<br />
<br />
Obj Index – this is a unique value that assigns the alphabetical assignment to the objective<br />
<br />
Obj Rep Index – this is a unique value that is used in replication. Usually this has the same value as the object name. For example, if the objective name is ROObjective_1 the Obj Rep Index will be 1<br />
<br />
Obj Name – this is localize name of the objective<br />
<br />
Obj Secondary Name – this is a internally used field that will be rendered on the overhead map. Any value here will be ignored in game. Best to leave it blank<br />
<br />
Obj Volume – this is the ROPlaceableVolume that is assigned to this objective for “proximity” capturing<br />
<br />
Map Zone Texture – this is a texture that is used as an overlay for the overhead map when the objective becomes active<br />
<br />
Minimum Capture Time – this time, in seconds, is the the amount of time it will take to capture the objective<br />
<br />
Initial Obj State – use the pulldown to select the initial defender state of the objective. NOTE: Neutral objective assignment for a ROObjectiveSatchel is not supported<br />
<br />
Lock Down Time 16/32/64 – these fields are deprecated and values assigned will not do anything<br />
<br />
Countdown Time – this is the amount of time the objective is active in the Countdown game mode, counted in seconds<br />
<br />
Is Key Objective – this bit is used in Countdown and gives an additional reinforcement for the commander<br />
<br />
Enable Lockdown – this bit is used to enable the procedural lockdown system in RO2<br />
<br />
Axis/Allies Priority – this is the order in which the AI will attack or defend the objectives. <br />
<br />
===RODamageOtherVolume===<br />
<br />
There is an additional supporting actor called a RODamageOtherVolume that allows of dropping the Satchel weapon (equipment for the engineering role) inside the volume. This overcomes the limitation that occurs when the origin of the SatchelObjective mesh is in a location to be “touched” by the explosion radius. For example, if the physical objective is inside a brick building but you'd like for the ability for the players to drop the satchel near the building and still destroy the objective.<br />
<br />
[[Image:RODamageOtherVolume_Properties.jpg|thumb|300px|center|DamageOtherVolume Properties]]<br />
<br />
Victim Actor: This points to the ROObjectiveSatchel that you'd like have accept the damage<br />
<br />
Damage Scale: A scale value of the damage applied to the Victim Actor<br />
<br />
Damage Types: The accepted damage types<br />
<br />
Ignore Damage Types: The damage types that should be ignored (usually to filter out subclasses of a damage type that won't damage the objective but the parent class will)</div>Keithhttps://wiki.tripwireinteractive.com/index.php?title=Red_Orchestra_2:_Heroes_Of_Stalingrad/LevelDesign/RO2DestructionSystem&diff=1476Red Orchestra 2: Heroes Of Stalingrad/LevelDesign/RO2DestructionSystem2012-07-24T20:19:53Z<p>Keith: </p>
<hr />
<div>=Red Orchestra 2 Destructible Setup Guide=<br />
<br />
Red Orchestra 2 has a number of tools to facilitate destructible environments and/or objectives. This document is to serve as a means to understand how to set up the systems and why you would want to use each of the tools available.<br />
<br />
The topics covered in this document will be:<br />
<br />
*ROStaticMeshDestructible<br />
*ROStaticMeshReplicationInfo<br />
*ROObjectiveSatchel<br />
*ROStaticMeshObstacle<br />
*ROStaticMeshSatchelObstacle<br />
*RODestructible<br />
<br />
==ROStaticMeshDestructible==<br />
<br />
This actor is used by level designers to place destructible assets in their maps.<br />
<br />
[[Image:|center|frame|Low Res deco layer shadows]]<br />
<br />
===Setup of ROStaticMeshDestuctible map actors===<br />
<br />
1) Select the base static mesh that will appear to the players in it's “undestroyed” state<br />
<br />
2) Select the map actor in the actor tree<br />
<br />
3) RMB → Add ROStaticMeshDestructible Here<br />
<br />
4) Open the properties of the newly place actor and find the StaticMeshComponent section of ROStaticMeshDestructible (Properties → ROStaticMeshDestructible → Destructible Mesh Component → StaticMeshComponent → Static Mesh) and replace the default static with the one selected in step 1. This is what is shown to the level designer in the editor.<br />
<br />
5) Open the RODestructibleStaticMeshComponent section of the properties<br />
<br />
6) Add at least two entries to the Destructible Assets list<br />
<br />
7) In the 0 section put the same base mesh as that of the Static Mesh. This is what will be shown to the players at runtime. NOTE: Use the Material Override to override the material that will be rendered in game. The LODMaterial Override should be used to override the materials on the LODs of the StaticMesh, if it exists, that will be rendered in game.<br />
<br />
8) In the 1 section put the destructed stage of the base static mesh. NOTE: You can add more than two stages but for each stage the lighting system will have to make a shadow map which can cause some bloat in map size. <br />
<br />
9) Under the Accepted Damage Types add the damage types you'd like to have effect the ROStaticMeshDestructible<br />
<br />
10) Set the appropriate value for Starting Health. If you'd like a tank to be able to run over the actor, give it a starting health of 1<br />
<br />
11) Set an appropriate emitter for the Destruction Emitter Template. This is what will be shown to the players when it changes states. The emitter will be spawned at the origin of the Static Mesh itself.<br />
<br />
12) Use the Destruction Emitter Offset values to adjust the spawn origin of the static mesh the origin of the Static Mesh being used is not in a good place for spawning an emitter<br />
<br />
13) If you would like the destructible to become active and interact with world space on destruction, set the Physics Static Mesh. NOTE: If you are going to have an active physics actors spawn instead of a destruction phase static mesh, leave the section in Step 8 empty.<br />
<br />
14) If there is cover that you would like to activate/deactivate upon stage change, you can add the cover references here. NOTE: ROStaticMeshDestructible and cover node must be in the same level. Usually the persistent. Use the Lock properties to allow selecting the cover node in the map without change the property window<br />
<br />
15) If you'd like to have multiple destructible static meshes to destroy even if they are not directly touched by the damage, add references to the ROStaticMeshDestructible to the Grouped Destructibles section of the properties. <br />
<br />
<br />
<br />
<br />
<br />
==RODestructionReplicationInfo==<br />
<br />
The purpose of this actor is to provide a lighter weight replication solution for destructible actors in a map; instead of sending a lot of information from the server to the client to change the state of a destructible actor in a map this actor sends just the Integer value of the destructible in info structure. This makes it a little bit more intensive for the server when a large number of destructible map actors change state simultaneously but should not bog down the net code. <br />
<br />
===Rules of Thumb===<br />
<br />
1) No more than 300 destructible actors in each RODestructibleReplicationInfo actor<br />
<br />
2) Maps are not suggested to exceed 500 destructible actors<br />
<br />
3) No limitation of the number of RODestructibleReplicationInfo <br />
<br />
4) The RODestructibleReplicationInfo actor must be in the same level as the ROStaticMeshDestructible, usually the Persistent level.<br />
<br />
===Setting Up RODestructibleReplicationInfo Actors===<br />
<br />
1) Find and place a RODestructibleReplicationInfo Actor in your map<br />
<br />
2) Open the properties of the RODestructibleReplicationInfo actor and lock the properties<br />
<br />
3) Open the Scene manager<br />
<br />
4) Select the persistent level<br />
<br />
5) Use the pulldown to select ROStaticMeshDestructible in the filter<br />
<br />
6) Add the appropriate number of slots to the replication actor (not exceeding 300)<br />
<br />
7) Select the first ROStaticMeshDestructible<br />
<br />
8) Add it to the first entry in the RODestructibleReplicationInfo actor<br />
<br />
9) Repeat steps 7-9 until you've either added all the ROStaticMeshDestructible actors in the map to the RODestructibleReplicationInfo actor or you've added 300 to the actor<br />
<br />
==Objective Based Destructible==<br />
This section covers how to setup objective based destructible solutions. <br />
<br />
===ROObjectiveSatchel===<br />
<br />
The purpose of the ROObjectiveSatchel is to allow for the capability for level designers to have objectives that “capture” upon destruction. It also allows for “proximity” capturing via a ROPlaceableVolume and otherwise functions 100% like a standard ROObjective.<br />
<br />
Setup of ROObjectiveSatchel<br />
<br />
1) Open the content browser and select a static mesh that you'd like to use for a ROObjectiveSatchel. Ideally this mesh will have it's origin centered on the object correctly (center, bottom-center, corner, etc).<br />
<br />
2) Find the ROObjectiveSatchel in the actor tree and place one in your map where you'd like the satchel objective to be<br />
<br />
3) Open the properties of the ROObjectiveSatchel and Expand the StaticMeshComponent section and replace the Static Mesh field with the mesh selected in Step 1<br />
<br />
4) Add at least two entries to the Destructible Assets list<br />
<br />
5) In the 0 section put the same base mesh as that of the Static Mesh. This is what will be shown to the players at runtime. NOTE: Use the Material Override to override the material that will be rendered in game. The LODMaterial Override should be used to override the materials on the LODs of the StaticMesh, if it exists, that will be rendered in game.<br />
<br />
6) In the 1 section put the destructed stage of the base static mesh. NOTE: You can add more than two stages but for each stage the lighting system will have to make a shadow map which can cause some bloat in map size. <br />
<br />
7) Expand the ROObjective section and fill that out:<br />
<br />
Obj Index – this is a unique value that assigns the alphabetical assignment to the objective<br />
<br />
Obj Rep Index – this is a unique value that is used in replication. Usually this has the same value as the object name. For example, if the objective name is ROObjective_1 the Obj Rep Index will be 1<br />
<br />
Obj Name – this is localize name of the objective<br />
<br />
Obj Secondary Name – this is a internally used field that will be rendered on the overhead map. Any value here will be ignored in game. Best to leave it blank<br />
<br />
Obj Volume – this is the ROPlaceableVolume that is assigned to this objective for “proximity” capturing<br />
<br />
Map Zone Texture – this is a texture that is used as an overlay for the overhead map when the objective becomes active<br />
<br />
Minimum Capture Time – this time, in seconds, is the the amount of time it will take to capture the objective<br />
<br />
Initial Obj State – use the pulldown to select the initial defender state of the objective. NOTE: Neutral objective assignment for a ROObjectiveSatchel is not supported<br />
<br />
Lock Down Time 16/32/64 – these fields are deprecated and values assigned will not do anything<br />
<br />
Countdown Time – this is the amount of time the objective is active in the Countdown game mode, counted in seconds<br />
<br />
Is Key Objective – this bit is used in Countdown and gives an additional reinforcement for the commander<br />
<br />
Enable Lockdown – this bit is used to enable the procedural lockdown system in RO2<br />
<br />
Axis/Allies Priority – this is the order in which the AI will attack or defend the objectives. <br />
<br />
===RODamageOtherVolume===<br />
<br />
There is an additional supporting actor called a RODamageOtherVolume that allows of dropping the Satchel weapon (equipment for the engineering role) inside the volume. This overcomes the limitation that occurs when the origin of the SatchelObjective mesh is in a location to be “touched” by the explosion radius. For example, if the physical objective is inside a brick building but you'd like for the ability for the players to drop the satchel near the building and still destroy the objective.<br />
<br />
Victim Actor: This points to the ROObjectiveSatchel that you'd like have accept the damage<br />
<br />
Damage Scale: A scale value of the damage applied to the Victim Actor<br />
<br />
Damage Types: The accepted damage types<br />
<br />
Ignore Damage Types: The damage types that should be ignored (usually to filter out subclasses of a damage type that won't damage the objective but the parent class will)</div>Keithhttps://wiki.tripwireinteractive.com/index.php?title=Red_Orchestra_2:_Heroes_Of_Stalingrad/LevelDesign/RO2DestructionSystem&diff=1475Red Orchestra 2: Heroes Of Stalingrad/LevelDesign/RO2DestructionSystem2012-07-24T19:54:58Z<p>Keith: Created page with "=Red Orchestra 2 Destructible Setup Guide= Red Orchestra 2 has a number of tools to facilitate destructible environments and/or objectives. This document is to serve as a mea..."</p>
<hr />
<div>=Red Orchestra 2 Destructible Setup Guide=<br />
<br />
Red Orchestra 2 has a number of tools to facilitate destructible environments and/or objectives. This document is to serve as a means to understand how to set up the systems and why you would want to use each of the tools available.<br />
<br />
The topics covered in this document will be:<br />
<br />
*ROStaticMeshDestructible<br />
*ROStaticMeshReplicationInfo<br />
*ROObjectiveSatchel<br />
*ROStaticMeshObstacle<br />
*ROStaticMeshSatchelObstacle<br />
*RODestructible<br />
<br />
==ROStaticMeshDestructible==<br />
<br />
This actor is used by level designers to place destructible assets in their maps.<br />
<br />
===Setup of ROStaticMeshDestuctible map actors===<br />
<br />
1) Select the base static mesh that will appear to the players in it's “undestroyed” state<br />
<br />
2) Select the map actor in the actor tree<br />
<br />
3) RMB → Add ROStaticMeshDestructible Here<br />
<br />
4) Open the properties of the newly place actor and find the StaticMeshComponent section of ROStaticMeshDestructible (Properties → ROStaticMeshDestructible → Destructible Mesh Component → StaticMeshComponent → Static Mesh) and replace the default static with the one selected in step 1. This is what is shown to the level designer in the editor.<br />
<br />
5) Open the RODestructibleStaticMeshComponent section of the properties<br />
<br />
6) Add at least two entries to the Destructible Assets list<br />
<br />
7) In the 0 section put the same base mesh as that of the Static Mesh. This is what will be shown to the players at runtime. NOTE: Use the Material Override to override the material that will be rendered in game. The LODMaterial Override should be used to override the materials on the LODs of the StaticMesh, if it exists, that will be rendered in game.<br />
<br />
8) In the 1 section put the destructed stage of the base static mesh. NOTE: You can add more than two stages but for each stage the lighting system will have to make a shadow map which can cause some bloat in map size. <br />
<br />
9) Under the Accepted Damage Types add the damage types you'd like to have effect the ROStaticMeshDestructible<br />
<br />
10) Set the appropriate value for Starting Health. If you'd like a tank to be able to run over the actor, give it a starting health of 1<br />
<br />
11) Set an appropriate emitter for the Destruction Emitter Template. This is what will be shown to the players when it changes states. The emitter will be spawned at the origin of the Static Mesh itself.<br />
<br />
12) Use the Destruction Emitter Offset values to adjust the spawn origin of the static mesh the origin of the Static Mesh being used is not in a good place for spawning an emitter<br />
<br />
13) If you would like the destructible to become active and interact with world space on destruction, set the Physics Static Mesh. NOTE: If you are going to have an active physics actors spawn instead of a destruction phase static mesh, leave the section in Step 8 empty.<br />
<br />
14) If there is cover that you would like to activate/deactivate upon stage change, you can add the cover references here. NOTE: ROStaticMeshDestructible and cover node must be in the same level. Usually the persistent. Use the Lock properties to allow selecting the cover node in the map without change the property window<br />
<br />
15) If you'd like to have multiple destructible static meshes to destroy even if they are not directly touched by the damage, add references to the ROStaticMeshDestructible to the Grouped Destructibles section of the properties. <br />
<br />
<br />
<br />
<br />
<br />
==RODestructionReplicationInfo==<br />
<br />
The purpose of this actor is to provide a lighter weight replication solution for destructible actors in a map; instead of sending a lot of information from the server to the client to change the state of a destructible actor in a map this actor sends just the Integer value of the destructible in info structure. This makes it a little bit more intensive for the server when a large number of destructible map actors change state simultaneously but should not bog down the net code. <br />
<br />
===Rules of Thumb===<br />
<br />
1) No more than 300 destructible actors in each RODestructibleReplicationInfo actor<br />
<br />
2) Maps are not suggested to exceed 500 destructible actors<br />
<br />
3) No limitation of the number of RODestructibleReplicationInfo <br />
<br />
4) The RODestructibleReplicationInfo actor must be in the same level as the ROStaticMeshDestructible, usually the Persistent level.<br />
<br />
===Setting Up RODestructibleReplicationInfo Actors===<br />
<br />
1) Find and place a RODestructibleReplicationInfo Actor in your map<br />
<br />
2) Open the properties of the RODestructibleReplicationInfo actor and lock the properties<br />
<br />
3) Open the Scene manager<br />
<br />
4) Select the persistent level<br />
<br />
5) Use the pulldown to select ROStaticMeshDestructible in the filter<br />
<br />
6) Add the appropriate number of slots to the replication actor (not exceeding 300)<br />
<br />
7) Select the first ROStaticMeshDestructible<br />
<br />
8) Add it to the first entry in the RODestructibleReplicationInfo actor<br />
<br />
9) Repeat steps 7-9 until you've either added all the ROStaticMeshDestructible actors in the map to the RODestructibleReplicationInfo actor or you've added 300 to the actor<br />
<br />
==Objective Based Destructible==<br />
This section covers how to setup objective based destructible solutions. <br />
<br />
===ROObjectiveSatchel===<br />
<br />
The purpose of the ROObjectiveSatchel is to allow for the capability for level designers to have objectives that “capture” upon destruction. It also allows for “proximity” capturing via a ROPlaceableVolume and otherwise functions 100% like a standard ROObjective.<br />
<br />
Setup of ROObjectiveSatchel<br />
<br />
1) Open the content browser and select a static mesh that you'd like to use for a ROObjectiveSatchel. Ideally this mesh will have it's origin centered on the object correctly (center, bottom-center, corner, etc).<br />
<br />
2) Find the ROObjectiveSatchel in the actor tree and place one in your map where you'd like the satchel objective to be<br />
<br />
3) Open the properties of the ROObjectiveSatchel and Expand the StaticMeshComponent section and replace the Static Mesh field with the mesh selected in Step 1<br />
<br />
4) Add at least two entries to the Destructible Assets list<br />
<br />
5) In the 0 section put the same base mesh as that of the Static Mesh. This is what will be shown to the players at runtime. NOTE: Use the Material Override to override the material that will be rendered in game. The LODMaterial Override should be used to override the materials on the LODs of the StaticMesh, if it exists, that will be rendered in game.<br />
<br />
6) In the 1 section put the destructed stage of the base static mesh. NOTE: You can add more than two stages but for each stage the lighting system will have to make a shadow map which can cause some bloat in map size. <br />
<br />
7) Expand the ROObjective section and fill that out:<br />
<br />
Obj Index – this is a unique value that assigns the alphabetical assignment to the objective<br />
<br />
Obj Rep Index – this is a unique value that is used in replication. Usually this has the same value as the object name. For example, if the objective name is ROObjective_1 the Obj Rep Index will be 1<br />
<br />
Obj Name – this is localize name of the objective<br />
<br />
Obj Secondary Name – this is a internally used field that will be rendered on the overhead map. Any value here will be ignored in game. Best to leave it blank<br />
<br />
Obj Volume – this is the ROPlaceableVolume that is assigned to this objective for “proximity” capturing<br />
<br />
Map Zone Texture – this is a texture that is used as an overlay for the overhead map when the objective becomes active<br />
<br />
Minimum Capture Time – this time, in seconds, is the the amount of time it will take to capture the objective<br />
<br />
Initial Obj State – use the pulldown to select the initial defender state of the objective. NOTE: Neutral objective assignment for a ROObjectiveSatchel is not supported<br />
<br />
Lock Down Time 16/32/64 – these fields are deprecated and values assigned will not do anything<br />
<br />
Countdown Time – this is the amount of time the objective is active in the Countdown game mode, counted in seconds<br />
<br />
Is Key Objective – this bit is used in Countdown and gives an additional reinforcement for the commander<br />
<br />
Enable Lockdown – this bit is used to enable the procedural lockdown system in RO2<br />
<br />
Axis/Allies Priority – this is the order in which the AI will attack or defend the objectives. <br />
<br />
===RODamageOtherVolume===<br />
<br />
There is an additional supporting actor called a RODamageOtherVolume that allows of dropping the Satchel weapon (equipment for the engineering role) inside the volume. This overcomes the limitation that occurs when the origin of the SatchelObjective mesh is in a location to be “touched” by the explosion radius. For example, if the physical objective is inside a brick building but you'd like for the ability for the players to drop the satchel near the building and still destroy the objective.<br />
<br />
Victim Actor: This points to the ROObjectiveSatchel that you'd like have accept the damage<br />
<br />
Damage Scale: A scale value of the damage applied to the Victim Actor<br />
<br />
Damage Types: The accepted damage types<br />
<br />
Ignore Damage Types: The damage types that should be ignored (usually to filter out subclasses of a damage type that won't damage the objective but the parent class will)</div>Keithhttps://wiki.tripwireinteractive.com/index.php?title=File:ActorFactoryEX_SupportingActor_FMGNote.jpg&diff=1393File:ActorFactoryEX SupportingActor FMGNote.jpg2012-07-06T17:45:34Z<p>Keith: </p>
<hr />
<div></div>Keithhttps://wiki.tripwireinteractive.com/index.php?title=File:ActorFactoryEX.jpg&diff=1392File:ActorFactoryEX.jpg2012-07-06T17:45:26Z<p>Keith: </p>
<hr />
<div></div>Keithhttps://wiki.tripwireinteractive.com/index.php?title=Red_Orchestra_2:_Heroes_Of_Stalingrad/LevelDesign/KismetNodes&diff=1391Red Orchestra 2: Heroes Of Stalingrad/LevelDesign/KismetNodes2012-07-06T17:44:47Z<p>Keith: /* ActorFactory EX */</p>
<hr />
<div>=Actions=<br />
<br />
==Recommended Reading==<br />
====[http://udn.epicgames.com/Three/KismetReference.html#Unreal%20Kismet%20Reference Epic's UDN Page for Kismet Reference]====<br />
<br />
==ActorFactory EX==<br />
<br />
[[image: ActorFactoryEX.jpg|thumb|center|Actor Factory EX is used to spawn actors into the Map]]<br />
<br />
===Fixed Machine Gun===<br />
<br />
Factory -> ROActorFactoryFixedMG -> Fixed MGClass ['''ROTurret_Maxim_HMG''' / '''ROTurrent_MG34_LMG''']<br />
<br />
====Supporting Actor(s)====<br />
=====ROFixedMGSpawnPoint=====<br />
<br />
[[image:ActorFactoryEX_SupportingActor_FMGNote.jpg|thumb|center|Fixed MG Spawn location actor]]<br />
<br />
SkeletalMesh'WP_3rd_Master.Mesh.Maxim_3rd_Master'<br />
<br />
SkeletalMesh'WP_3rd_Master.Mesh.MG34_Tripod_3rd_Master'</div>Keithhttps://wiki.tripwireinteractive.com/index.php?title=Red_Orchestra_2:_Heroes_Of_Stalingrad/LevelDesign/KismetNodes&diff=1389Red Orchestra 2: Heroes Of Stalingrad/LevelDesign/KismetNodes2012-07-06T17:18:33Z<p>Keith: /* ActorFactory EX */</p>
<hr />
<div>=Actions=<br />
<br />
==ActorFactory EX==<br />
<br />
[[image: ActorFactoryEX.jpg|thumb|center|Actor Factory EX is used to spawn actors into the Map]]<br />
<br />
===Fixed Machine Gun===<br />
Factory -> ROActorFactoryFixedMG -> Fixed MGClass ['''ROTurret_Maxim_HMG''' / '''ROTurrent_MG34_LMG''']</div>Keithhttps://wiki.tripwireinteractive.com/index.php?title=Red_Orchestra_2:_Heroes_Of_Stalingrad/LevelDesign/KismetNodes&diff=1388Red Orchestra 2: Heroes Of Stalingrad/LevelDesign/KismetNodes2012-07-06T17:16:22Z<p>Keith: Created page with "=Actions= ==ActorFactory EX== Actor Factory EX is used to spawn actors into the Map ===Fixed Machine Gun=== Factory -> ROActorFac..."</p>
<hr />
<div>=Actions=<br />
<br />
==ActorFactory EX==<br />
<br />
[[image: ActorFactoryEX.jpg|thumb|Center|Actor Factory EX is used to spawn actors into the Map]]<br />
<br />
===Fixed Machine Gun===<br />
Factory -> ROActorFactoryFixedMG -> Fixed MGClass ['''ROTurret_Maxim_HMG'''/'''ROTurrent_MG34_LMG''']</div>Keithhttps://wiki.tripwireinteractive.com/index.php?title=Red_Orchestra_2:_Heroes_Of_Stalingrad/LevelDesign/OptimizationGuide&diff=1384Red Orchestra 2: Heroes Of Stalingrad/LevelDesign/OptimizationGuide2012-07-06T16:24:13Z<p>Keith: /* Store Results for Future Profiles */</p>
<hr />
<div><br />
== Recommended Reading ==<br />
<br />
<br />
If you are new to optimizing in general for Unreal 3 games please have a look through the below web pages so you are up to speed with the grunt work.<br />
<br />
===Epic's Unreal Development Network - UDN===<br />
====[http://udn.epicgames.com/Three/PerformanceHome.html Epic's Performance UDN Page]====<br />
<br />
====[http://udn.epicgames.com/Three/ProfilingBasics.html Epic's Profiling UDN Page]====<br />
<br />
====[http://udn.epicgames.com/Three/MemoryProfilingHome.html Epic's Memory Profiling UDN Page]====<br />
<br />
====[http://udn.epicgames.com/Three/RenderThreadProfilingHome.html Epic's Rendering Thread Profiling UDN Page]====<br />
<br />
=Introduction=<br />
<br />
The purpose of this document is to give information on the guidelines used to optimize the maps inside RO2. These guidelines worked for us. If you are a community level designer and/or artist you may find this document useful. This document will cover the various approaches and the reasoning behind decisions so that the reader may be able to avoid pitfalls when making levels for Red Orchestra 2.<br />
<br />
The following is a list of items that LDs and Environment Artists should follow for a map to perform well. Most of these were lessons learnt while optimizing RO2 and should also serve as a guideline for modders to make sure that they don't run into the same pitfalls.<br />
<br />
=Level Performance Guidelines=<br />
==Terrain==<br />
<br />
=== bCastDynamicShadow ===<br />
This flag should be OFF. Setting this flag to ON will cast dynamic preshadows by the terrain for both per-object shadows and whole scene dynamic shadows, which can be very expensive depending on the number of dynamic primitives in the scene. Preshadows (which are dynamic shadows from the static environment onto dynamic objects) only make sense if the terrain has hills and valleys throughout the scene. If the scene just has a few mounds here and there it might be worth modeling the mounds with static meshes and have the terrain blend in at the bottom. The side effect of disabling bCastDynamicShadow is that terrain deco layers (e.g. grass) will not cast whole scene dynamic shadows. But considering that shadows from deco layers usually are low-res and don't look great, it is a good price to pay for a substantial performance boost.<br />
<br />
[[Image:GrassShadows.png|center|frame|Low Res deco layer shadows]]<br />
<br />
=== Terrain Layers ===<br />
The RO2 engine allows for a maximum of 12 textures to be blended for terrain. These 12 textures could be part of 2 terrain layers (6 textures each), 3 terrain layers (4 textures each), or any other combination thereof. This is a hard limit for the engine, and exceeding this limit will result in rainbow colored terrain patches. However, fetching and accessing so many textures is not cheap and since the terrain usually takes up a large portion of the screen, it is recommended that you keep the number of blend textures to a minimum.<br />
<br />
One example for this is that say you have a terrain which comprises or dirt, rubble and snow and one part of the terrain is solid concrete. Instead of making 4 terrain layers of dirt, rubble, snow and concrete and blending between them it is more optimized if the terrain uses 3 layers of dirt, rubble and snow, and the concrete portion is modeled separately as BSP, static mesh or even another terrain actor. Doing this will reduce the overall cost of rendering the entire terrain since the concrete layer texture fetches are eliminated for the rest of the terrain that doesn't need it.<br />
<br />
==Static Meshes==<br />
<br />
=== bCastDynamicShadow ===<br />
When placing a static mesh in the level, you should decide whether you want it to cast dynamic preshadows or not. Preshadows are dynamic shadows from the static environment onto dynamic objects, and can be very expensive depending on the number of dynamic primitives in the scene. Turning off this flag for a lot of static meshes in the environment in the scene such as debris, rubble, etc. will improve the dynamic shadow performance.<br />
<br />
[[Image:Preshadows.png|center|frame|Dynamic preshadows cast by tree foliage onto character]]<br />
<br />
Once the lighting in a map is finalized, you can also go through and set bCastDynamicShadow to false for all static meshes that are already in shadow (such as the truck in the following image, which is is shadow of the building) since any dynamic shadow cast by it will be drowned by the static shadow cast by the environment.<br />
<br />
[[Image:DynamicShadowTruck.jpg|thumb|300px|center|The truck does not need to cast dynamic shadows since it is already in shadow]]<br />
<br />
=== Distance Culling ===<br />
Using distance culling effectively will allow you to have a lot of detail in your environment whilst still allowing the map to perform well. There are 2 ways to do this :<br />
<br />
* You can either put a CullDistanceVolume around the map and the let the map build process choose the appropriate cull distances for the placed static meshes in the level. This method is not ideal though, and might cause certain cover objects, etc. to disappear at a distance (which is not desirable). <br />
<br />
* Or, you can manually set the MaxDrawDistance for each object.<br />
<br />
== Materials ==<br />
=== Using Material LODs ===<br />
In order to make the best looking environment materials as well as keep the overall performance cost low, consider using material LODs. The concept is very simple - assign the best looking/highest instruction count material to the base LOD for a static mesh, and then create another LOD for the static mesh (this can have the exact same triangle count as the base LOD) and assign it a simple material that does not have expensive operations such as depth biased alpha, specularity, cube maps or even normal maps. Such subtle lighting effects cannot be perceived from a distance anyway, and will make improve the fill rate for the rendered scene.<br />
<br />
[[Image:NormalMappedBaseMaterial.png|thumb|300px|center|Base material using normal maps]][[Image:SimpleMaterial.png|thumb|300px|center|Simple material that does not use normal maps]]<br />
<br />
== Dynamic Actors ==<br />
=== bDisablePerObjectShadows ===<br />
If you place an actor onto a level that casts dynamic shadows, the shadowing cost for it is one per object shadow and in certain cases a preshadow as well. If bDisablePerObjectShadows is set it will only cast dynamic shadows for the primitive if it is within the whole scene dominant shadow radius. This reduces the cost associated with shadowing for the primitive. If whole scene dominant shadows are not enabled, the primitive will not cast any dynamic shadows.<br />
<br />
[[Image:DisablePerObjectShadowsDemo.jpg|thumb|600px|center|The flag pole is outside the whole scene dominant shadow radius in the image on the left and hence is not shadowed. When the player moves such that the flag pole is now within the whole scene dominant shadow radius, it will start casting whole scene dominant shadows (right image)]]<br />
<br />
=== bAllowMergedDynamicShadows ===<br />
If this flag is set, any primitive that allows per object dynamic shadows will be considered for being merged with other primitives that allow merged per object dynamic shadows and are close enough. As a consequence, the number of dynamic shadows in the scene are reduced.<br />
<br />
The radius used to merge primitives is dynamically adjusted based on the distance of the primitives from the viewer. It starts at ''MinShadowGroupRadius'' (when the primitive is closest to the viewer) and increases up to ''MaxShadowGroupRadius'' (when the primitive is ''ShadowGroupRampCutoff'' away from the viewer). The rate of increase is determined by ''ShadowGroupRadiusRampUpFactor''. For anything beyond ''ShadowGroupRampCutoff'', the ''MaxShadowGroupRadius'' will be used. All these settings are available in the engine INI.<br />
<br />
[[Image:GroupedDynamicPerObjectShadowsDemo.jpg|thumb|600px|center|The image on the left has bAllowMergedDynamicShadows set to false on the two placed pawns, and they cast a per object shadow each. The image on the right has bAllowMergedDynamicShadows set to true on the pawns, and as such both the pawns are included in the same projected shadow.]]<br />
<br />
== Draw Calls ==<br />
== About Draw Calls==<br />
As the UE3 rendering engine is a Direct X 9.0 renderer, it is limited to one CPU core to tell the GPU about what to draw. It does this via a Draw Call. Each object you place in the world is at least one draw call (if not more due to shadows). The CPU can become the bottleneck of a level if it is trying to tell the GPU to draw a detailed scene and chokes on the amount of draw calls. This is why it is best to limit the amount in any given scene. With the Red Orchestra SDK it is very easy to make many types of levels, from wide open plains (or with rolling hills) to detailed interior settings and building to building fighting. However, depending on what the scale of your map is, you will be limited in the amount of "detail" you can place in the level. <br />
<br />
<br />
== Limiting Draw Calls Per Scene==<br />
Suggested Maximum Draw Call Limit: 2000<br />
<br />
Using the console command ''Stat d3d9rhi"'' a Level Designer/Artist (or anyone) can go through a level and find out the amount of Draw Calls and optimize based on areas where it has increased beyond the suggested maximum.<br />
<br />
The details settings for both users and in the SDK allows Level Designers to put some objects on different levels of the setting so those with faster computers (in this case CPU core speed) can see more details without harming performance for those with slower machines. It is best to do this with "fluff" detail that is not gameplay important but just makes the level look better overall.<br />
<br />
<br />
=Profiling Preliminary Work=<br />
<br />
There is a small amount of setup work that must be completed.<br />
<br />
==RODebugPosedPlayer==<br />
<br />
We have made a tool for level designers and artists that are used to gather statistical data about maps called Posed Players. The purpose of the Posed Player is to have a placeable actor to simulate a player in a scene. It has the capability to be used as a camera during profile stage. All of which I will go over now.<br />
<br />
===Actor In Tree===<br />
<br />
[[Image:RODebugPosedPlayerActorTree.jpg|thumb|300px|center|RODebugPosedPlayer in Actor Tree]]<br />
<br />
The RODebugPosedPlayer actor is found at Actor -> RODebugPosedPlayer<br />
<br />
===Properties===<br />
<br />
[[File:RODebugPosedPlayerProperties.jpg|Properties of RODebugPosedPlayer]]<br />
<br />
*Pose: The pose, or stance, the posed player will be in when spawned<br />
*Weapon: The weapon the posed player will be using when posed<br />
*Pawn Type: German or Russian<br />
*Can Possess: Allows the user to possess this posed player using the '''PossessPosedPlayer''' console command<br />
*Description: Small description on what this posed player is - OPTIONAL<br />
<br />
====Available Poses====<br />
<br />
[[File:RODebugPosedPlayerProperties_Pose.jpg|Available Poses for RODebugPosedPlayer]]<br />
<br />
The pose will not make a difference in regards to performance and optimization. It was added so if you wanted to stage a scene for screen shots or something along those lines, this allows you to put the posed player into various positions.<br />
<br />
====Can Possess====<br />
<br />
[[File:RODebugPosedPlayerProperties_CanPossess.jpg|Can Possess Changes Color of RODebugPosedPlayer to BLUE]]<br />
<br />
==Placing RODebugPosedPlayer Actor in Map==<br />
<br />
====Posed Player Placement Guideline====<br />
<br />
*Expected player count is 64 player which would be the worse case scenario in regards to performance<br />
*Use Can Possess on posed players that have vantage view on a particular high traffic area/areas of performance pits<br />
*Any particular player SHOULD NOT see 100% of the map nor players<br />
*Place the actors where players will be<br />
*Do not unnaturally bunch up the posed players<br />
*Distribute the posed players evenly across scene<br />
*More actors near objective spaces, spawn areas, and known fight spaces<br />
*Position RODebugPosedPlayers ~16 Unreal Units above surface to avoid posed player clipping/failure to spawn<br />
<br />
====Create a NEW sublevel====<br />
<br />
[[FILE:LevelBrowser_CreateNEW.jpg|Create a new sub level]]<br />
<br />
=====Naming the Sub Level=====<br />
<br />
[[FILE:LevelBrowser_LevelName.jpg|Give the new sub level a name]]<br />
<br />
Give the sub level a name. It really doesn't matter what you call it as long as you know what it is.<br />
<br />
=====Setting Streaming Method=====<br />
<br />
[[File:LevelBrowser_StreamingMethod.jpg|Set Streaming Method to Always Loaded]]<br />
<br />
We always use Always Loaded so that every time the persistent is loaded, so is this sublevel. Done this way there is no need to have Kismet handle it.<br />
<br />
Options:<br />
*Kismet- Used when you want to use a Kismet node to stream in the sub level. <br />
*Distance- Used when you want to use a certain distance.<br />
*Always Loaded- Used when you want the sub level always loaded when the persistent is loaded.<br />
<br />
[http://udn.epicgames.com/Three/LevelStreamingHome.html Epic Games' UDN Page]<br />
<br />
=====Making New Sub Level Current=====<br />
<br />
[[FILE:LevelBrowser_MakeCurrent.jpg|Set the new sub level as CURRENT]]<br />
<br />
Make the new sub level current and we are ready to start placing actors.<br />
<br />
<br />
==Results==<br />
<br />
[[FILE: PosedPlayer_Placed_L.jpg|This is what we got in Grain Elevator]]<br />
<br />
=Doing the Profile=<br />
<br />
I will document what was done at TWI. Our profiling parameters and data gathering points were specific to our needs for our designs.<br />
<br />
==Profiling Machine Hardware Specifications==<br />
<br />
These are the specifications of the test machine used at TWI<br />
<br />
*Intel Quad 2.40GHz<br />
*4GB RAM<br />
*ATI Radeon HD 5800<br />
*Test Done on High Settings<br />
<br />
==Console Commands==<br />
<br />
*SpawnPosedPlayers<br />
<br />
*PossessPosedPlayer<br />
<br />
==Polling the Results==<br />
<br />
*Location @<br />
*Frame Time<br />
*Game Time<br />
*FPS<br />
*Draw Time (ms)<br />
*GPU Time (ms)<br />
*DrawPrimitive Calls<br />
*Triangles Drawn<br />
*Static Mesh Tris<br />
*Skel Mesh Draw Calls<br />
*Per Object shadows<br />
*Preshadows<br />
*Adjusted FPS<br />
<br />
==Store Results for Future Profiles==<br />
<br />
If you are able to get the profiling tools in sooner than later, you can run the profile process at various stages of development. We did this at TWI allowing us to postmortem the design process with useful data on hand.<br />
<br />
=RO2 Static Mesh Combining Tool=<br />
<br />
This tool allows for you to combine similar staticmeshes into one staticmesh allowing you to reduce the overall draw calls per scene frame. We had a number of guidelines that we worked with to get the best results that we could.<br />
<br />
NOTE: When you are combining meshes it's a good idea to keep an eye on Properties -> Static Mesh Component -> Override Light Map Res and it's Boolean bit as well. Having a non default value will result in lightmap errors.<br />
<br />
[[File:StaticMeshProperties_LightmapOverride.jpg|thumb|300px|center|Keep an eye on Properties -> Static Mesh Component -> Override Light Map Res]]<br />
<br />
To override the lightmap of combined meshes, do it at the asset itself in the package. StaticMesh Asset Properties -> Light Map Resolution -> [INTEGER]<br />
<br />
[[File:StaticMeshProperties_AssetLightmapOverride.jpg|thumb|300px|center|Override the lightmap resolution here instead]]<br />
<br />
==Combining Tool Guidelines==<br />
<br />
*Do not combine meshes that do not share that same material(s) in the same slots<br />
*Do not combine too many meshes that you fight with the natural occlusion systems as even the smallest of pixel of a mesh being rendered will render the entirety of the mesh<br />
*Do not combine meshes that will give you exceedingly high poly counts. (>5000)<br />
*Do not combine meshes that you cannot use over and over as this fights with the engine's instancing capability<br />
*Culling > Occlusion<br />
<br />
==Combining Process==<br />
<br />
===Combine Mesh Context Menu===<br />
<br />
[[image:CombineMesh_ContextMenu.jpg|thumb|300px|center|RMB -> Combine Mesh from context menu]]<br />
<br />
===Create New Asset Location===<br />
<br />
[[image:CombineMesh_NewAssetLocation.jpg|thumb|300px|center|Select the Package, Group, and Name of the Asset]]<br />
<br />
===Combine Convex Collision===<br />
<br />
[[image:CombineMesh_ConvexCollisionCombine.jpg|thumb|300px|center|Takes all the convex collision hull primitives and adds them together]]<br />
<br />
===Replace Actors in Scene===<br />
<br />
[[image:CombineMesh_ReplaceActor.jpg|thumb|300px|center|Replace the actor in the scene?]]<br />
<br />
==UnCombining Process==<br />
<br />
[[image:UNCombineMesh_ContextMenu.jpg|thumb|300px|center|RMB -> Uncombine Mesh from context menu]]<br />
<br />
RMB -> UnCombine Mesh<br />
<br />
This will simply uncombine the meshes and replace them with the stored reference of the original assets in the combined mesh. Do not uncombine more than one combined mesh at a time.<br />
<br />
=Procedural bCastDynamicShow System=<br />
<br />
Every static mesh object in the map has the capability to cast a dynamic shadow. A dynamic shadow uses the cascade shadowing system to make nice crisp shadows for the world objects when the player gets near them. The down side is that they can be an expensive render, relatively, when the engine must cast a dynamic shadow into an already shadowed space. To save from having to check this on each and every object in the world a new system was introduced that traces a line from the 8 corners of the bounding box of the static mesh actor back to the DominantDirectionalLight in the map. If ANY of the traces hit the DominantDirectionalLight, the bCaseDynamicShadow Boolean variable is set to TRUE. If none of the traces touches the DominantDirectionalLight then the variable is set to FALSE.<br />
<br />
Some times you can get a false readings in situations where all 8 corners of the bounding box are contained in another mesh (such as walls with a pillar on each side of each section of wall). In this case we've given the capability for the Level Designer to override the procedural system.<br />
<br />
StaticMeshActor Properties -> StaticMeshComponent -> Lighting -> Allow Auto Cast Dynamic Shadow Override</div>Keithhttps://wiki.tripwireinteractive.com/index.php?title=Red_Orchestra_2:_Heroes_Of_Stalingrad/LevelDesign/OptimizationGuide&diff=1383Red Orchestra 2: Heroes Of Stalingrad/LevelDesign/OptimizationGuide2012-07-06T16:22:09Z<p>Keith: </p>
<hr />
<div><br />
== Recommended Reading ==<br />
<br />
<br />
If you are new to optimizing in general for Unreal 3 games please have a look through the below web pages so you are up to speed with the grunt work.<br />
<br />
===Epic's Unreal Development Network - UDN===<br />
====[http://udn.epicgames.com/Three/PerformanceHome.html Epic's Performance UDN Page]====<br />
<br />
====[http://udn.epicgames.com/Three/ProfilingBasics.html Epic's Profiling UDN Page]====<br />
<br />
====[http://udn.epicgames.com/Three/MemoryProfilingHome.html Epic's Memory Profiling UDN Page]====<br />
<br />
====[http://udn.epicgames.com/Three/RenderThreadProfilingHome.html Epic's Rendering Thread Profiling UDN Page]====<br />
<br />
=Introduction=<br />
<br />
The purpose of this document is to give information on the guidelines used to optimize the maps inside RO2. These guidelines worked for us. If you are a community level designer and/or artist you may find this document useful. This document will cover the various approaches and the reasoning behind decisions so that the reader may be able to avoid pitfalls when making levels for Red Orchestra 2.<br />
<br />
The following is a list of items that LDs and Environment Artists should follow for a map to perform well. Most of these were lessons learnt while optimizing RO2 and should also serve as a guideline for modders to make sure that they don't run into the same pitfalls.<br />
<br />
=Level Performance Guidelines=<br />
==Terrain==<br />
<br />
=== bCastDynamicShadow ===<br />
This flag should be OFF. Setting this flag to ON will cast dynamic preshadows by the terrain for both per-object shadows and whole scene dynamic shadows, which can be very expensive depending on the number of dynamic primitives in the scene. Preshadows (which are dynamic shadows from the static environment onto dynamic objects) only make sense if the terrain has hills and valleys throughout the scene. If the scene just has a few mounds here and there it might be worth modeling the mounds with static meshes and have the terrain blend in at the bottom. The side effect of disabling bCastDynamicShadow is that terrain deco layers (e.g. grass) will not cast whole scene dynamic shadows. But considering that shadows from deco layers usually are low-res and don't look great, it is a good price to pay for a substantial performance boost.<br />
<br />
[[Image:GrassShadows.png|center|frame|Low Res deco layer shadows]]<br />
<br />
=== Terrain Layers ===<br />
The RO2 engine allows for a maximum of 12 textures to be blended for terrain. These 12 textures could be part of 2 terrain layers (6 textures each), 3 terrain layers (4 textures each), or any other combination thereof. This is a hard limit for the engine, and exceeding this limit will result in rainbow colored terrain patches. However, fetching and accessing so many textures is not cheap and since the terrain usually takes up a large portion of the screen, it is recommended that you keep the number of blend textures to a minimum.<br />
<br />
One example for this is that say you have a terrain which comprises or dirt, rubble and snow and one part of the terrain is solid concrete. Instead of making 4 terrain layers of dirt, rubble, snow and concrete and blending between them it is more optimized if the terrain uses 3 layers of dirt, rubble and snow, and the concrete portion is modeled separately as BSP, static mesh or even another terrain actor. Doing this will reduce the overall cost of rendering the entire terrain since the concrete layer texture fetches are eliminated for the rest of the terrain that doesn't need it.<br />
<br />
==Static Meshes==<br />
<br />
=== bCastDynamicShadow ===<br />
When placing a static mesh in the level, you should decide whether you want it to cast dynamic preshadows or not. Preshadows are dynamic shadows from the static environment onto dynamic objects, and can be very expensive depending on the number of dynamic primitives in the scene. Turning off this flag for a lot of static meshes in the environment in the scene such as debris, rubble, etc. will improve the dynamic shadow performance.<br />
<br />
[[Image:Preshadows.png|center|frame|Dynamic preshadows cast by tree foliage onto character]]<br />
<br />
Once the lighting in a map is finalized, you can also go through and set bCastDynamicShadow to false for all static meshes that are already in shadow (such as the truck in the following image, which is is shadow of the building) since any dynamic shadow cast by it will be drowned by the static shadow cast by the environment.<br />
<br />
[[Image:DynamicShadowTruck.jpg|thumb|300px|center|The truck does not need to cast dynamic shadows since it is already in shadow]]<br />
<br />
=== Distance Culling ===<br />
Using distance culling effectively will allow you to have a lot of detail in your environment whilst still allowing the map to perform well. There are 2 ways to do this :<br />
<br />
* You can either put a CullDistanceVolume around the map and the let the map build process choose the appropriate cull distances for the placed static meshes in the level. This method is not ideal though, and might cause certain cover objects, etc. to disappear at a distance (which is not desirable). <br />
<br />
* Or, you can manually set the MaxDrawDistance for each object.<br />
<br />
== Materials ==<br />
=== Using Material LODs ===<br />
In order to make the best looking environment materials as well as keep the overall performance cost low, consider using material LODs. The concept is very simple - assign the best looking/highest instruction count material to the base LOD for a static mesh, and then create another LOD for the static mesh (this can have the exact same triangle count as the base LOD) and assign it a simple material that does not have expensive operations such as depth biased alpha, specularity, cube maps or even normal maps. Such subtle lighting effects cannot be perceived from a distance anyway, and will make improve the fill rate for the rendered scene.<br />
<br />
[[Image:NormalMappedBaseMaterial.png|thumb|300px|center|Base material using normal maps]][[Image:SimpleMaterial.png|thumb|300px|center|Simple material that does not use normal maps]]<br />
<br />
== Dynamic Actors ==<br />
=== bDisablePerObjectShadows ===<br />
If you place an actor onto a level that casts dynamic shadows, the shadowing cost for it is one per object shadow and in certain cases a preshadow as well. If bDisablePerObjectShadows is set it will only cast dynamic shadows for the primitive if it is within the whole scene dominant shadow radius. This reduces the cost associated with shadowing for the primitive. If whole scene dominant shadows are not enabled, the primitive will not cast any dynamic shadows.<br />
<br />
[[Image:DisablePerObjectShadowsDemo.jpg|thumb|600px|center|The flag pole is outside the whole scene dominant shadow radius in the image on the left and hence is not shadowed. When the player moves such that the flag pole is now within the whole scene dominant shadow radius, it will start casting whole scene dominant shadows (right image)]]<br />
<br />
=== bAllowMergedDynamicShadows ===<br />
If this flag is set, any primitive that allows per object dynamic shadows will be considered for being merged with other primitives that allow merged per object dynamic shadows and are close enough. As a consequence, the number of dynamic shadows in the scene are reduced.<br />
<br />
The radius used to merge primitives is dynamically adjusted based on the distance of the primitives from the viewer. It starts at ''MinShadowGroupRadius'' (when the primitive is closest to the viewer) and increases up to ''MaxShadowGroupRadius'' (when the primitive is ''ShadowGroupRampCutoff'' away from the viewer). The rate of increase is determined by ''ShadowGroupRadiusRampUpFactor''. For anything beyond ''ShadowGroupRampCutoff'', the ''MaxShadowGroupRadius'' will be used. All these settings are available in the engine INI.<br />
<br />
[[Image:GroupedDynamicPerObjectShadowsDemo.jpg|thumb|600px|center|The image on the left has bAllowMergedDynamicShadows set to false on the two placed pawns, and they cast a per object shadow each. The image on the right has bAllowMergedDynamicShadows set to true on the pawns, and as such both the pawns are included in the same projected shadow.]]<br />
<br />
== Draw Calls ==<br />
== About Draw Calls==<br />
As the UE3 rendering engine is a Direct X 9.0 renderer, it is limited to one CPU core to tell the GPU about what to draw. It does this via a Draw Call. Each object you place in the world is at least one draw call (if not more due to shadows). The CPU can become the bottleneck of a level if it is trying to tell the GPU to draw a detailed scene and chokes on the amount of draw calls. This is why it is best to limit the amount in any given scene. With the Red Orchestra SDK it is very easy to make many types of levels, from wide open plains (or with rolling hills) to detailed interior settings and building to building fighting. However, depending on what the scale of your map is, you will be limited in the amount of "detail" you can place in the level. <br />
<br />
<br />
== Limiting Draw Calls Per Scene==<br />
Suggested Maximum Draw Call Limit: 2000<br />
<br />
Using the console command ''Stat d3d9rhi"'' a Level Designer/Artist (or anyone) can go through a level and find out the amount of Draw Calls and optimize based on areas where it has increased beyond the suggested maximum.<br />
<br />
The details settings for both users and in the SDK allows Level Designers to put some objects on different levels of the setting so those with faster computers (in this case CPU core speed) can see more details without harming performance for those with slower machines. It is best to do this with "fluff" detail that is not gameplay important but just makes the level look better overall.<br />
<br />
<br />
=Profiling Preliminary Work=<br />
<br />
There is a small amount of setup work that must be completed.<br />
<br />
==RODebugPosedPlayer==<br />
<br />
We have made a tool for level designers and artists that are used to gather statistical data about maps called Posed Players. The purpose of the Posed Player is to have a placeable actor to simulate a player in a scene. It has the capability to be used as a camera during profile stage. All of which I will go over now.<br />
<br />
===Actor In Tree===<br />
<br />
[[Image:RODebugPosedPlayerActorTree.jpg|thumb|300px|center|RODebugPosedPlayer in Actor Tree]]<br />
<br />
The RODebugPosedPlayer actor is found at Actor -> RODebugPosedPlayer<br />
<br />
===Properties===<br />
<br />
[[File:RODebugPosedPlayerProperties.jpg|Properties of RODebugPosedPlayer]]<br />
<br />
*Pose: The pose, or stance, the posed player will be in when spawned<br />
*Weapon: The weapon the posed player will be using when posed<br />
*Pawn Type: German or Russian<br />
*Can Possess: Allows the user to possess this posed player using the '''PossessPosedPlayer''' console command<br />
*Description: Small description on what this posed player is - OPTIONAL<br />
<br />
====Available Poses====<br />
<br />
[[File:RODebugPosedPlayerProperties_Pose.jpg|Available Poses for RODebugPosedPlayer]]<br />
<br />
The pose will not make a difference in regards to performance and optimization. It was added so if you wanted to stage a scene for screen shots or something along those lines, this allows you to put the posed player into various positions.<br />
<br />
====Can Possess====<br />
<br />
[[File:RODebugPosedPlayerProperties_CanPossess.jpg|Can Possess Changes Color of RODebugPosedPlayer to BLUE]]<br />
<br />
==Placing RODebugPosedPlayer Actor in Map==<br />
<br />
====Posed Player Placement Guideline====<br />
<br />
*Expected player count is 64 player which would be the worse case scenario in regards to performance<br />
*Use Can Possess on posed players that have vantage view on a particular high traffic area/areas of performance pits<br />
*Any particular player SHOULD NOT see 100% of the map nor players<br />
*Place the actors where players will be<br />
*Do not unnaturally bunch up the posed players<br />
*Distribute the posed players evenly across scene<br />
*More actors near objective spaces, spawn areas, and known fight spaces<br />
*Position RODebugPosedPlayers ~16 Unreal Units above surface to avoid posed player clipping/failure to spawn<br />
<br />
====Create a NEW sublevel====<br />
<br />
[[FILE:LevelBrowser_CreateNEW.jpg|Create a new sub level]]<br />
<br />
=====Naming the Sub Level=====<br />
<br />
[[FILE:LevelBrowser_LevelName.jpg|Give the new sub level a name]]<br />
<br />
Give the sub level a name. It really doesn't matter what you call it as long as you know what it is.<br />
<br />
=====Setting Streaming Method=====<br />
<br />
[[File:LevelBrowser_StreamingMethod.jpg|Set Streaming Method to Always Loaded]]<br />
<br />
We always use Always Loaded so that every time the persistent is loaded, so is this sublevel. Done this way there is no need to have Kismet handle it.<br />
<br />
Options:<br />
*Kismet- Used when you want to use a Kismet node to stream in the sub level. <br />
*Distance- Used when you want to use a certain distance.<br />
*Always Loaded- Used when you want the sub level always loaded when the persistent is loaded.<br />
<br />
[http://udn.epicgames.com/Three/LevelStreamingHome.html Epic Games' UDN Page]<br />
<br />
=====Making New Sub Level Current=====<br />
<br />
[[FILE:LevelBrowser_MakeCurrent.jpg|Set the new sub level as CURRENT]]<br />
<br />
Make the new sub level current and we are ready to start placing actors.<br />
<br />
<br />
==Results==<br />
<br />
[[FILE: PosedPlayer_Placed_L.jpg|This is what we got in Grain Elevator]]<br />
<br />
=Doing the Profile=<br />
<br />
I will document what was done at TWI. Our profiling parameters and data gathering points were specific to our needs for our designs.<br />
<br />
==Profiling Machine Hardware Specifications==<br />
<br />
These are the specifications of the test machine used at TWI<br />
<br />
*Intel Quad 2.40GHz<br />
*4GB RAM<br />
*ATI Radeon HD 5800<br />
*Test Done on High Settings<br />
<br />
==Console Commands==<br />
<br />
*SpawnPosedPlayers<br />
<br />
*PossessPosedPlayer<br />
<br />
==Polling the Results==<br />
<br />
*Location @<br />
*Frame Time<br />
*Game Time<br />
*FPS<br />
*Draw Time (ms)<br />
*GPU Time (ms)<br />
*DrawPrimitive Calls<br />
*Triangles Drawn<br />
*Static Mesh Tris<br />
*Skel Mesh Draw Calls<br />
*Per Object shadows<br />
*Preshadows<br />
*Adjusted FPS<br />
<br />
==Store Results for Future Profiles==<br />
<br />
=RO2 Static Mesh Combining Tool=<br />
<br />
This tool allows for you to combine similar staticmeshes into one staticmesh allowing you to reduce the overall draw calls per scene frame. We had a number of guidelines that we worked with to get the best results that we could.<br />
<br />
NOTE: When you are combining meshes it's a good idea to keep an eye on Properties -> Static Mesh Component -> Override Light Map Res and it's Boolean bit as well. Having a non default value will result in lightmap errors.<br />
<br />
[[File:StaticMeshProperties_LightmapOverride.jpg|thumb|300px|center|Keep an eye on Properties -> Static Mesh Component -> Override Light Map Res]]<br />
<br />
To override the lightmap of combined meshes, do it at the asset itself in the package. StaticMesh Asset Properties -> Light Map Resolution -> [INTEGER]<br />
<br />
[[File:StaticMeshProperties_AssetLightmapOverride.jpg|thumb|300px|center|Override the lightmap resolution here instead]]<br />
<br />
==Combining Tool Guidelines==<br />
<br />
*Do not combine meshes that do not share that same material(s) in the same slots<br />
*Do not combine too many meshes that you fight with the natural occlusion systems as even the smallest of pixel of a mesh being rendered will render the entirety of the mesh<br />
*Do not combine meshes that will give you exceedingly high poly counts. (>5000)<br />
*Do not combine meshes that you cannot use over and over as this fights with the engine's instancing capability<br />
*Culling > Occlusion<br />
<br />
==Combining Process==<br />
<br />
===Combine Mesh Context Menu===<br />
<br />
[[image:CombineMesh_ContextMenu.jpg|thumb|300px|center|RMB -> Combine Mesh from context menu]]<br />
<br />
===Create New Asset Location===<br />
<br />
[[image:CombineMesh_NewAssetLocation.jpg|thumb|300px|center|Select the Package, Group, and Name of the Asset]]<br />
<br />
===Combine Convex Collision===<br />
<br />
[[image:CombineMesh_ConvexCollisionCombine.jpg|thumb|300px|center|Takes all the convex collision hull primitives and adds them together]]<br />
<br />
===Replace Actors in Scene===<br />
<br />
[[image:CombineMesh_ReplaceActor.jpg|thumb|300px|center|Replace the actor in the scene?]]<br />
<br />
==UnCombining Process==<br />
<br />
[[image:UNCombineMesh_ContextMenu.jpg|thumb|300px|center|RMB -> Uncombine Mesh from context menu]]<br />
<br />
RMB -> UnCombine Mesh<br />
<br />
This will simply uncombine the meshes and replace them with the stored reference of the original assets in the combined mesh. Do not uncombine more than one combined mesh at a time.<br />
<br />
=Procedural bCastDynamicShow System=<br />
<br />
Every static mesh object in the map has the capability to cast a dynamic shadow. A dynamic shadow uses the cascade shadowing system to make nice crisp shadows for the world objects when the player gets near them. The down side is that they can be an expensive render, relatively, when the engine must cast a dynamic shadow into an already shadowed space. To save from having to check this on each and every object in the world a new system was introduced that traces a line from the 8 corners of the bounding box of the static mesh actor back to the DominantDirectionalLight in the map. If ANY of the traces hit the DominantDirectionalLight, the bCaseDynamicShadow Boolean variable is set to TRUE. If none of the traces touches the DominantDirectionalLight then the variable is set to FALSE.<br />
<br />
Some times you can get a false readings in situations where all 8 corners of the bounding box are contained in another mesh (such as walls with a pillar on each side of each section of wall). In this case we've given the capability for the Level Designer to override the procedural system.<br />
<br />
StaticMeshActor Properties -> StaticMeshComponent -> Lighting -> Allow Auto Cast Dynamic Shadow Override</div>Keithhttps://wiki.tripwireinteractive.com/index.php?title=Red_Orchestra_2:_Heroes_Of_Stalingrad/LevelDesign/OptimizationGuide&diff=1382Red Orchestra 2: Heroes Of Stalingrad/LevelDesign/OptimizationGuide2012-07-06T16:21:20Z<p>Keith: /* Store Results for Future Profiles */</p>
<hr />
<div><br />
== Recommended Reading ==<br />
<br />
<br />
If you are new to optimizing in general for Unreal 3 games please have a look through the below web pages so you are up to speed with the grunt work.<br />
<br />
===Epic's Unreal Development Network - UDN===<br />
====[http://udn.epicgames.com/Three/PerformanceHome.html Epic's Performance UDN Page]====<br />
<br />
====[http://udn.epicgames.com/Three/ProfilingBasics.html Epic's Profiling UDN Page]====<br />
<br />
====[http://udn.epicgames.com/Three/MemoryProfilingHome.html Epic's Memory Profiling UDN Page]====<br />
<br />
====[http://udn.epicgames.com/Three/RenderThreadProfilingHome.html Epic's Rendering Thread Profiling UDN Page]====<br />
<br />
=Introduction=<br />
<br />
The purpose of this document is to give information on the guidelines used to optimize the maps inside RO2. These guidelines worked for us. If you are a community level designer and/or artist you may find this document useful. This document will cover the various approaches and the reasoning behind decisions so that the reader may be able to avoid pitfalls when making levels for Red Orchestra 2.<br />
<br />
The following is a list of items that LDs and Environment Artists should follow for a map to perform well. Most of these were lessons learnt while optimizing RO2 and should also serve as a guideline for modders to make sure that they don't run into the same pitfalls.<br />
<br />
=Level Performance Guidelines=<br />
==Terrain==<br />
<br />
=== bCastDynamicShadow ===<br />
This flag should be OFF. Setting this flag to ON will cast dynamic preshadows by the terrain for both per-object shadows and whole scene dynamic shadows, which can be very expensive depending on the number of dynamic primitives in the scene. Preshadows (which are dynamic shadows from the static environment onto dynamic objects) only make sense if the terrain has hills and valleys throughout the scene. If the scene just has a few mounds here and there it might be worth modeling the mounds with static meshes and have the terrain blend in at the bottom. The side effect of disabling bCastDynamicShadow is that terrain deco layers (e.g. grass) will not cast whole scene dynamic shadows. But considering that shadows from deco layers usually are low-res and don't look great, it is a good price to pay for a substantial performance boost.<br />
<br />
[[Image:GrassShadows.png|center|frame|Low Res deco layer shadows]]<br />
<br />
=== Terrain Layers ===<br />
The RO2 engine allows for a maximum of 12 textures to be blended for terrain. These 12 textures could be part of 2 terrain layers (6 textures each), 3 terrain layers (4 textures each), or any other combination thereof. This is a hard limit for the engine, and exceeding this limit will result in rainbow colored terrain patches. However, fetching and accessing so many textures is not cheap and since the terrain usually takes up a large portion of the screen, it is recommended that you keep the number of blend textures to a minimum.<br />
<br />
One example for this is that say you have a terrain which comprises or dirt, rubble and snow and one part of the terrain is solid concrete. Instead of making 4 terrain layers of dirt, rubble, snow and concrete and blending between them it is more optimized if the terrain uses 3 layers of dirt, rubble and snow, and the concrete portion is modeled separately as BSP, static mesh or even another terrain actor. Doing this will reduce the overall cost of rendering the entire terrain since the concrete layer texture fetches are eliminated for the rest of the terrain that doesn't need it.<br />
<br />
==Static Meshes==<br />
<br />
=== bCastDynamicShadow ===<br />
When placing a static mesh in the level, you should decide whether you want it to cast dynamic preshadows or not. Preshadows are dynamic shadows from the static environment onto dynamic objects, and can be very expensive depending on the number of dynamic primitives in the scene. Turning off this flag for a lot of static meshes in the environment in the scene such as debris, rubble, etc. will improve the dynamic shadow performance.<br />
<br />
[[Image:Preshadows.png|center|frame|Dynamic preshadows cast by tree foliage onto character]]<br />
<br />
Once the lighting in a map is finalized, you can also go through and set bCastDynamicShadow to false for all static meshes that are already in shadow (such as the truck in the following image, which is is shadow of the building) since any dynamic shadow cast by it will be drowned by the static shadow cast by the environment.<br />
<br />
[[Image:DynamicShadowTruck.jpg|thumb|300px|center|The truck does not need to cast dynamic shadows since it is already in shadow]]<br />
<br />
=== Distance Culling ===<br />
Using distance culling effectively will allow you to have a lot of detail in your environment whilst still allowing the map to perform well. There are 2 ways to do this :<br />
<br />
* You can either put a CullDistanceVolume around the map and the let the map build process choose the appropriate cull distances for the placed static meshes in the level. This method is not ideal though, and might cause certain cover objects, etc. to disappear at a distance (which is not desirable). <br />
<br />
* Or, you can manually set the MaxDrawDistance for each object.<br />
<br />
== Materials ==<br />
=== Using Material LODs ===<br />
In order to make the best looking environment materials as well as keep the overall performance cost low, consider using material LODs. The concept is very simple - assign the best looking/highest instruction count material to the base LOD for a static mesh, and then create another LOD for the static mesh (this can have the exact same triangle count as the base LOD) and assign it a simple material that does not have expensive operations such as depth biased alpha, specularity, cube maps or even normal maps. Such subtle lighting effects cannot be perceived from a distance anyway, and will make improve the fill rate for the rendered scene.<br />
<br />
[[Image:NormalMappedBaseMaterial.png|thumb|300px|center|Base material using normal maps]][[Image:SimpleMaterial.png|thumb|300px|center|Simple material that does not use normal maps]]<br />
<br />
== Dynamic Actors ==<br />
=== bDisablePerObjectShadows ===<br />
If you place an actor onto a level that casts dynamic shadows, the shadowing cost for it is one per object shadow and in certain cases a preshadow as well. If bDisablePerObjectShadows is set it will only cast dynamic shadows for the primitive if it is within the whole scene dominant shadow radius. This reduces the cost associated with shadowing for the primitive. If whole scene dominant shadows are not enabled, the primitive will not cast any dynamic shadows.<br />
<br />
[[Image:DisablePerObjectShadowsDemo.jpg|thumb|600px|center|The flag pole is outside the whole scene dominant shadow radius in the image on the left and hence is not shadowed. When the player moves such that the flag pole is now within the whole scene dominant shadow radius, it will start casting whole scene dominant shadows (right image)]]<br />
<br />
=== bAllowMergedDynamicShadows ===<br />
If this flag is set, any primitive that allows per object dynamic shadows will be considered for being merged with other primitives that allow merged per object dynamic shadows and are close enough. As a consequence, the number of dynamic shadows in the scene are reduced.<br />
<br />
The radius used to merge primitives is dynamically adjusted based on the distance of the primitives from the viewer. It starts at ''MinShadowGroupRadius'' (when the primitive is closest to the viewer) and increases up to ''MaxShadowGroupRadius'' (when the primitive is ''ShadowGroupRampCutoff'' away from the viewer). The rate of increase is determined by ''ShadowGroupRadiusRampUpFactor''. For anything beyond ''ShadowGroupRampCutoff'', the ''MaxShadowGroupRadius'' will be used. All these settings are available in the engine INI.<br />
<br />
[[Image:GroupedDynamicPerObjectShadowsDemo.jpg|thumb|600px|center|The image on the left has bAllowMergedDynamicShadows set to false on the two placed pawns, and they cast a per object shadow each. The image on the right has bAllowMergedDynamicShadows set to true on the pawns, and as such both the pawns are included in the same projected shadow.]]<br />
<br />
== Draw Calls ==<br />
== About Draw Calls==<br />
As the UE3 rendering engine is a Direct X 9.0 renderer, it is limited to one CPU core to tell the GPU about what to draw. It does this via a Draw Call. Each object you place in the world is at least one draw call (if not more due to shadows). The CPU can become the bottleneck of a level if it is trying to tell the GPU to draw a detailed scene and chokes on the amount of draw calls. This is why it is best to limit the amount in any given scene. With the Red Orchestra SDK it is very easy to make many types of levels, from wide open plains (or with rolling hills) to detailed interior settings and building to building fighting. However, depending on what the scale of your map is, you will be limited in the amount of "detail" you can place in the level. <br />
<br />
<br />
== Limiting Draw Calls Per Scene==<br />
Suggested Maximum Draw Call Limit: 2000<br />
<br />
Using the console command ''Stat d3d9rhi"'' a Level Designer/Artist (or anyone) can go through a level and find out the amount of Draw Calls and optimize based on areas where it has increased beyond the suggested maximum.<br />
<br />
The details settings for both users and in the SDK allows Level Designers to put some objects on different levels of the setting so those with faster computers (in this case CPU core speed) can see more details without harming performance for those with slower machines. It is best to do this with "fluff" detail that is not gameplay important but just makes the level look better overall.<br />
<br />
<br />
=Profiling Preliminary Work=<br />
<br />
There is a small amount of setup work that must be completed.<br />
<br />
==RODebugPosedPlayer==<br />
<br />
We have made a tool for level designers and artists that are used to gather statistical data about maps called Posed Players. The purpose of the Posed Player is to have a placeable actor to simulate a player in a scene. It has the capability to be used as a camera during profile stage. All of which I will go over now.<br />
<br />
===Actor In Tree===<br />
<br />
[[Image:RODebugPosedPlayerActorTree.jpg|thumb|300px|center|RODebugPosedPlayer in Actor Tree]]<br />
<br />
The RODebugPosedPlayer actor is found at Actor -> RODebugPosedPlayer<br />
<br />
===Properties===<br />
<br />
[[File:RODebugPosedPlayerProperties.jpg|Properties of RODebugPosedPlayer]]<br />
<br />
*Pose: The pose, or stance, the posed player will be in when spawned<br />
*Weapon: The weapon the posed player will be using when posed<br />
*Pawn Type: German or Russian<br />
*Can Possess: Allows the user to possess this posed player using the '''PossessPosedPlayer''' console command<br />
*Description: Small description on what this posed player is - OPTIONAL<br />
<br />
====Available Poses====<br />
<br />
[[File:RODebugPosedPlayerProperties_Pose.jpg|Available Poses for RODebugPosedPlayer]]<br />
<br />
The pose will not make a difference in regards to performance and optimization. It was added so if you wanted to stage a scene for screen shots or something along those lines, this allows you to put the posed player into various positions.<br />
<br />
====Can Possess====<br />
<br />
[[File:RODebugPosedPlayerProperties_CanPossess.jpg|Can Possess Changes Color of RODebugPosedPlayer to BLUE]]<br />
<br />
==Placing RODebugPosedPlayer Actor in Map==<br />
<br />
====Posed Player Placement Guideline====<br />
<br />
*Expected player count is 64 player which would be the worse case scenario in regards to performance<br />
*Use Can Possess on posed players that have vantage view on a particular high traffic area/areas of performance pits<br />
*Any particular player SHOULD NOT see 100% of the map nor players<br />
*Place the actors where players will be<br />
*Do not unnaturally bunch up the posed players<br />
*Distribute the posed players evenly across scene<br />
*More actors near objective spaces, spawn areas, and known fight spaces<br />
*Position RODebugPosedPlayers ~16 Unreal Units above surface to avoid posed player clipping/failure to spawn<br />
<br />
====Create a NEW sublevel====<br />
<br />
[[FILE:LevelBrowser_CreateNEW.jpg|Create a new sub level]]<br />
<br />
=====Naming the Sub Level=====<br />
<br />
[[FILE:LevelBrowser_LevelName.jpg|Give the new sub level a name]]<br />
<br />
Give the sub level a name. It really doesn't matter what you call it as long as you know what it is.<br />
<br />
=====Setting Streaming Method=====<br />
<br />
[[File:LevelBrowser_StreamingMethod.jpg|Set Streaming Method to Always Loaded]]<br />
<br />
We always use Always Loaded so that every time the persistent is loaded, so is this sublevel. Done this way there is no need to have Kismet handle it.<br />
<br />
Options:<br />
*Kismet- Used when you want to use a Kismet node to stream in the sub level. <br />
*Distance- Used when you want to use a certain distance.<br />
*Always Loaded- Used when you want the sub level always loaded when the persistent is loaded.<br />
<br />
[http://udn.epicgames.com/Three/LevelStreamingHome.html Epic Games' UDN Page]<br />
<br />
=====Making New Sub Level Current=====<br />
<br />
[[FILE:LevelBrowser_MakeCurrent.jpg|Set the new sub level as CURRENT]]<br />
<br />
Make the new sub level current and we are ready to start placing actors.<br />
<br />
<br />
==Results==<br />
<br />
[[FILE: PosedPlayer_Placed_L.jpg|This is what we got in Grain Elevator]]<br />
<br />
=Doing the Profile=<br />
<br />
I will document what was done at TWI. Our profiling parameters and data gathering points were specific to our needs for our designs.<br />
<br />
==Profiling Machine Hardware Specifications==<br />
<br />
These are the specifications of the test machine used at TWI<br />
<br />
*Intel Quad 2.40GHz<br />
*4GB RAM<br />
*ATI Radeon HD 5800<br />
*Test Done on High Settings<br />
<br />
==Console Commands==<br />
<br />
*'''SpawnPosedPlayers''' - this command will spawn SkeletalMeshes at the locations of the RODebugPosedPlayer map actors<br />
<br />
*'''StopPosedPlayerUpdates''' - this command will stop the engine from updating the posed players between ticks<br />
<br />
*'''PossessPosedPlayer''' - this command allows the user to possess RODebugPosedPlayer actors for "camera" viewing<br />
<br />
==Polling the Results==<br />
====Commands Used====<br />
*'''STAT FPS''': Adds Frames Per Second counter to the screen<br />
*'''STAT UNIT''': Displays the time spend for the current frame on the CPU, in the game thread, in the render thread, and on the GPU<br />
*'''STAT D3D9RHI''': Displays basic DirectX 9 rendering statistics<br />
*'''STAT ENGINE''': Displays engine-level statistics, such as triangle counts, draw calls, and the time spent performing updates to various systems<br />
*'''STAT SHADOWRENDERING''': Displays statistics for rendering dynamic shadows<br />
<br />
====Result Targets====<br />
*Frame Time '''(STAT UNIT)'''<br />
*Game Time '''(STAT UNIT)'''<br />
*FPS '''(STAT FPS)'''<br />
*Draw Time (ms) '''(STAT ENGINE)'''<br />
*GPU Time (ms) '''(STAT UNIT)'''<br />
*DrawPrimitive Calls '''(STAT D3D9RHI)'''<br />
*Triangles Drawn '''(STAT D3D9RHI)'''<br />
*Static Mesh Tris '''(STAT ENGINE)'''<br />
*Skel Mesh Draw Calls '''(STAT ENGINE)'''<br />
*Per Object shadows '''(STAT SHADOWRENDERING)'''<br />
*Preshadows '''(STAT SHADOWRENDERING)'''<br />
<br />
==Store Results for Future Profiles==<br />
<br />
During the process of building a map, if you get the profiling tools in soon you can do progression based profiles. As you hit a milestone, do a profile to know where the map is. Keeping track of that data will help you NOT overwhelm your design into a performance hole.<br />
<br />
We store our results in a spreadsheet with different tabs for each profile run. The data is consolidated over the length of the development cycle allowing us to postmortem the design process with a lot more useful data on hand.<br />
<br />
=RO2 Static Mesh Combining Tool=<br />
<br />
This tool allows for you to combine similar staticmeshes into one staticmesh allowing you to reduce the overall draw calls per scene frame. We had a number of guidelines that we worked with to get the best results that we could.<br />
<br />
NOTE: When you are combining meshes it's a good idea to keep an eye on Properties -> Static Mesh Component -> Override Light Map Res and it's Boolean bit as well. Having a non default value will result in lightmap errors.<br />
<br />
[[File:StaticMeshProperties_LightmapOverride.jpg|thumb|300px|center|Keep an eye on Properties -> Static Mesh Component -> Override Light Map Res]]<br />
<br />
To override the lightmap of combined meshes, do it at the asset itself in the package. StaticMesh Asset Properties -> Light Map Resolution -> [INTEGER]<br />
<br />
[[File:StaticMeshProperties_AssetLightmapOverride.jpg|thumb|300px|center|Override the lightmap resolution here instead]]<br />
<br />
==Combining Tool Guidelines==<br />
<br />
*Do not combine meshes that do not share that same material(s) in the same slots<br />
*Do not combine too many meshes that you fight with the natural occlusion systems as even the smallest of pixel of a mesh being rendered will render the entirety of the mesh<br />
*Do not combine meshes that will give you exceedingly high poly counts. (>5000)<br />
*Do not combine meshes that you cannot use over and over as this fights with the engine's instancing capability<br />
*Culling > Occlusion<br />
<br />
==Combining Process==<br />
<br />
===Combine Mesh Context Menu===<br />
<br />
[[image:CombineMesh_ContextMenu.jpg|thumb|300px|center|RMB -> Combine Mesh from context menu]]<br />
<br />
===Create New Asset Location===<br />
<br />
[[image:CombineMesh_NewAssetLocation.jpg|thumb|300px|center|Select the Package, Group, and Name of the Asset]]<br />
<br />
===Combine Convex Collision===<br />
<br />
[[image:CombineMesh_ConvexCollisionCombine.jpg|thumb|300px|center|Takes all the convex collision hull primitives and adds them together]]<br />
<br />
===Replace Actors in Scene===<br />
<br />
[[image:CombineMesh_ReplaceActor.jpg|thumb|300px|center|Replace the actor in the scene?]]<br />
<br />
==UnCombining Process==<br />
<br />
[[image:UNCombineMesh_ContextMenu.jpg|thumb|300px|center|RMB -> Uncombine Mesh from context menu]]<br />
<br />
RMB -> UnCombine Mesh<br />
<br />
This will simply uncombine the meshes and replace them with the stored reference of the original assets in the combined mesh. Do not uncombine more than one combined mesh at a time.<br />
<br />
=Procedural bCastDynamicShow System=<br />
<br />
Every static mesh object in the map has the capability to cast a dynamic shadow. A dynamic shadow uses the cascade shadowing system to make nice crisp shadows for the world objects when the player gets near them. The down side is that they can be an expensive render, relatively, when the engine must cast a dynamic shadow into an already shadowed space. To save from having to check this on each and every object in the world a new system was introduced that traces a line from the 8 corners of the bounding box of the static mesh actor back to the DominantDirectionalLight in the map. If ANY of the traces hit the DominantDirectionalLight, the bCaseDynamicShadow Boolean variable is set to TRUE. If none of the traces touches the DominantDirectionalLight then the variable is set to FALSE.<br />
<br />
Some times you can get a false readings in situations where all 8 corners of the bounding box are contained in another mesh (such as walls with a pillar on each side of each section of wall). In this case we've given the capability for the Level Designer to override the procedural system.<br />
<br />
StaticMeshActor Properties -> StaticMeshComponent -> Lighting -> Allow Auto Cast Dynamic Shadow Override</div>Keithhttps://wiki.tripwireinteractive.com/index.php?title=Red_Orchestra_2:_Heroes_Of_Stalingrad/LevelDesign/OptimizationGuide&diff=1381Red Orchestra 2: Heroes Of Stalingrad/LevelDesign/OptimizationGuide2012-07-06T16:15:33Z<p>Keith: /* Result Targets */</p>
<hr />
<div><br />
== Recommended Reading ==<br />
<br />
<br />
If you are new to optimizing in general for Unreal 3 games please have a look through the below web pages so you are up to speed with the grunt work.<br />
<br />
===Epic's Unreal Development Network - UDN===<br />
====[http://udn.epicgames.com/Three/PerformanceHome.html Epic's Performance UDN Page]====<br />
<br />
====[http://udn.epicgames.com/Three/ProfilingBasics.html Epic's Profiling UDN Page]====<br />
<br />
====[http://udn.epicgames.com/Three/MemoryProfilingHome.html Epic's Memory Profiling UDN Page]====<br />
<br />
====[http://udn.epicgames.com/Three/RenderThreadProfilingHome.html Epic's Rendering Thread Profiling UDN Page]====<br />
<br />
=Introduction=<br />
<br />
The purpose of this document is to give information on the guidelines used to optimize the maps inside RO2. These guidelines worked for us. If you are a community level designer and/or artist you may find this document useful. This document will cover the various approaches and the reasoning behind decisions so that the reader may be able to avoid pitfalls when making levels for Red Orchestra 2.<br />
<br />
The following is a list of items that LDs and Environment Artists should follow for a map to perform well. Most of these were lessons learnt while optimizing RO2 and should also serve as a guideline for modders to make sure that they don't run into the same pitfalls.<br />
<br />
=Level Performance Guidelines=<br />
==Terrain==<br />
<br />
=== bCastDynamicShadow ===<br />
This flag should be OFF. Setting this flag to ON will cast dynamic preshadows by the terrain for both per-object shadows and whole scene dynamic shadows, which can be very expensive depending on the number of dynamic primitives in the scene. Preshadows (which are dynamic shadows from the static environment onto dynamic objects) only make sense if the terrain has hills and valleys throughout the scene. If the scene just has a few mounds here and there it might be worth modeling the mounds with static meshes and have the terrain blend in at the bottom. The side effect of disabling bCastDynamicShadow is that terrain deco layers (e.g. grass) will not cast whole scene dynamic shadows. But considering that shadows from deco layers usually are low-res and don't look great, it is a good price to pay for a substantial performance boost.<br />
<br />
[[Image:GrassShadows.png|center|frame|Low Res deco layer shadows]]<br />
<br />
=== Terrain Layers ===<br />
The RO2 engine allows for a maximum of 12 textures to be blended for terrain. These 12 textures could be part of 2 terrain layers (6 textures each), 3 terrain layers (4 textures each), or any other combination thereof. This is a hard limit for the engine, and exceeding this limit will result in rainbow colored terrain patches. However, fetching and accessing so many textures is not cheap and since the terrain usually takes up a large portion of the screen, it is recommended that you keep the number of blend textures to a minimum.<br />
<br />
One example for this is that say you have a terrain which comprises or dirt, rubble and snow and one part of the terrain is solid concrete. Instead of making 4 terrain layers of dirt, rubble, snow and concrete and blending between them it is more optimized if the terrain uses 3 layers of dirt, rubble and snow, and the concrete portion is modeled separately as BSP, static mesh or even another terrain actor. Doing this will reduce the overall cost of rendering the entire terrain since the concrete layer texture fetches are eliminated for the rest of the terrain that doesn't need it.<br />
<br />
==Static Meshes==<br />
<br />
=== bCastDynamicShadow ===<br />
When placing a static mesh in the level, you should decide whether you want it to cast dynamic preshadows or not. Preshadows are dynamic shadows from the static environment onto dynamic objects, and can be very expensive depending on the number of dynamic primitives in the scene. Turning off this flag for a lot of static meshes in the environment in the scene such as debris, rubble, etc. will improve the dynamic shadow performance.<br />
<br />
[[Image:Preshadows.png|center|frame|Dynamic preshadows cast by tree foliage onto character]]<br />
<br />
Once the lighting in a map is finalized, you can also go through and set bCastDynamicShadow to false for all static meshes that are already in shadow (such as the truck in the following image, which is is shadow of the building) since any dynamic shadow cast by it will be drowned by the static shadow cast by the environment.<br />
<br />
[[Image:DynamicShadowTruck.jpg|thumb|300px|center|The truck does not need to cast dynamic shadows since it is already in shadow]]<br />
<br />
=== Distance Culling ===<br />
Using distance culling effectively will allow you to have a lot of detail in your environment whilst still allowing the map to perform well. There are 2 ways to do this :<br />
<br />
* You can either put a CullDistanceVolume around the map and the let the map build process choose the appropriate cull distances for the placed static meshes in the level. This method is not ideal though, and might cause certain cover objects, etc. to disappear at a distance (which is not desirable). <br />
<br />
* Or, you can manually set the MaxDrawDistance for each object.<br />
<br />
== Materials ==<br />
=== Using Material LODs ===<br />
In order to make the best looking environment materials as well as keep the overall performance cost low, consider using material LODs. The concept is very simple - assign the best looking/highest instruction count material to the base LOD for a static mesh, and then create another LOD for the static mesh (this can have the exact same triangle count as the base LOD) and assign it a simple material that does not have expensive operations such as depth biased alpha, specularity, cube maps or even normal maps. Such subtle lighting effects cannot be perceived from a distance anyway, and will make improve the fill rate for the rendered scene.<br />
<br />
[[Image:NormalMappedBaseMaterial.png|thumb|300px|center|Base material using normal maps]][[Image:SimpleMaterial.png|thumb|300px|center|Simple material that does not use normal maps]]<br />
<br />
== Dynamic Actors ==<br />
=== bDisablePerObjectShadows ===<br />
If you place an actor onto a level that casts dynamic shadows, the shadowing cost for it is one per object shadow and in certain cases a preshadow as well. If bDisablePerObjectShadows is set it will only cast dynamic shadows for the primitive if it is within the whole scene dominant shadow radius. This reduces the cost associated with shadowing for the primitive. If whole scene dominant shadows are not enabled, the primitive will not cast any dynamic shadows.<br />
<br />
[[Image:DisablePerObjectShadowsDemo.jpg|thumb|600px|center|The flag pole is outside the whole scene dominant shadow radius in the image on the left and hence is not shadowed. When the player moves such that the flag pole is now within the whole scene dominant shadow radius, it will start casting whole scene dominant shadows (right image)]]<br />
<br />
=== bAllowMergedDynamicShadows ===<br />
If this flag is set, any primitive that allows per object dynamic shadows will be considered for being merged with other primitives that allow merged per object dynamic shadows and are close enough. As a consequence, the number of dynamic shadows in the scene are reduced.<br />
<br />
The radius used to merge primitives is dynamically adjusted based on the distance of the primitives from the viewer. It starts at ''MinShadowGroupRadius'' (when the primitive is closest to the viewer) and increases up to ''MaxShadowGroupRadius'' (when the primitive is ''ShadowGroupRampCutoff'' away from the viewer). The rate of increase is determined by ''ShadowGroupRadiusRampUpFactor''. For anything beyond ''ShadowGroupRampCutoff'', the ''MaxShadowGroupRadius'' will be used. All these settings are available in the engine INI.<br />
<br />
[[Image:GroupedDynamicPerObjectShadowsDemo.jpg|thumb|600px|center|The image on the left has bAllowMergedDynamicShadows set to false on the two placed pawns, and they cast a per object shadow each. The image on the right has bAllowMergedDynamicShadows set to true on the pawns, and as such both the pawns are included in the same projected shadow.]]<br />
<br />
== Draw Calls ==<br />
== About Draw Calls==<br />
As the UE3 rendering engine is a Direct X 9.0 renderer, it is limited to one CPU core to tell the GPU about what to draw. It does this via a Draw Call. Each object you place in the world is at least one draw call (if not more due to shadows). The CPU can become the bottleneck of a level if it is trying to tell the GPU to draw a detailed scene and chokes on the amount of draw calls. This is why it is best to limit the amount in any given scene. With the Red Orchestra SDK it is very easy to make many types of levels, from wide open plains (or with rolling hills) to detailed interior settings and building to building fighting. However, depending on what the scale of your map is, you will be limited in the amount of "detail" you can place in the level. <br />
<br />
<br />
== Limiting Draw Calls Per Scene==<br />
Suggested Maximum Draw Call Limit: 2000<br />
<br />
Using the console command ''Stat d3d9rhi"'' a Level Designer/Artist (or anyone) can go through a level and find out the amount of Draw Calls and optimize based on areas where it has increased beyond the suggested maximum.<br />
<br />
The details settings for both users and in the SDK allows Level Designers to put some objects on different levels of the setting so those with faster computers (in this case CPU core speed) can see more details without harming performance for those with slower machines. It is best to do this with "fluff" detail that is not gameplay important but just makes the level look better overall.<br />
<br />
<br />
=Profiling Preliminary Work=<br />
<br />
There is a small amount of setup work that must be completed.<br />
<br />
==RODebugPosedPlayer==<br />
<br />
We have made a tool for level designers and artists that are used to gather statistical data about maps called Posed Players. The purpose of the Posed Player is to have a placeable actor to simulate a player in a scene. It has the capability to be used as a camera during profile stage. All of which I will go over now.<br />
<br />
===Actor In Tree===<br />
<br />
[[Image:RODebugPosedPlayerActorTree.jpg|thumb|300px|center|RODebugPosedPlayer in Actor Tree]]<br />
<br />
The RODebugPosedPlayer actor is found at Actor -> RODebugPosedPlayer<br />
<br />
===Properties===<br />
<br />
[[File:RODebugPosedPlayerProperties.jpg|Properties of RODebugPosedPlayer]]<br />
<br />
*Pose: The pose, or stance, the posed player will be in when spawned<br />
*Weapon: The weapon the posed player will be using when posed<br />
*Pawn Type: German or Russian<br />
*Can Possess: Allows the user to possess this posed player using the '''PossessPosedPlayer''' console command<br />
*Description: Small description on what this posed player is - OPTIONAL<br />
<br />
====Available Poses====<br />
<br />
[[File:RODebugPosedPlayerProperties_Pose.jpg|Available Poses for RODebugPosedPlayer]]<br />
<br />
The pose will not make a difference in regards to performance and optimization. It was added so if you wanted to stage a scene for screen shots or something along those lines, this allows you to put the posed player into various positions.<br />
<br />
====Can Possess====<br />
<br />
[[File:RODebugPosedPlayerProperties_CanPossess.jpg|Can Possess Changes Color of RODebugPosedPlayer to BLUE]]<br />
<br />
==Placing RODebugPosedPlayer Actor in Map==<br />
<br />
====Posed Player Placement Guideline====<br />
<br />
*Expected player count is 64 player which would be the worse case scenario in regards to performance<br />
*Use Can Possess on posed players that have vantage view on a particular high traffic area/areas of performance pits<br />
*Any particular player SHOULD NOT see 100% of the map nor players<br />
*Place the actors where players will be<br />
*Do not unnaturally bunch up the posed players<br />
*Distribute the posed players evenly across scene<br />
*More actors near objective spaces, spawn areas, and known fight spaces<br />
*Position RODebugPosedPlayers ~16 Unreal Units above surface to avoid posed player clipping/failure to spawn<br />
<br />
====Create a NEW sublevel====<br />
<br />
[[FILE:LevelBrowser_CreateNEW.jpg|Create a new sub level]]<br />
<br />
=====Naming the Sub Level=====<br />
<br />
[[FILE:LevelBrowser_LevelName.jpg|Give the new sub level a name]]<br />
<br />
Give the sub level a name. It really doesn't matter what you call it as long as you know what it is.<br />
<br />
=====Setting Streaming Method=====<br />
<br />
[[File:LevelBrowser_StreamingMethod.jpg|Set Streaming Method to Always Loaded]]<br />
<br />
We always use Always Loaded so that every time the persistent is loaded, so is this sublevel. Done this way there is no need to have Kismet handle it.<br />
<br />
Options:<br />
*Kismet- Used when you want to use a Kismet node to stream in the sub level. <br />
*Distance- Used when you want to use a certain distance.<br />
*Always Loaded- Used when you want the sub level always loaded when the persistent is loaded.<br />
<br />
[http://udn.epicgames.com/Three/LevelStreamingHome.html Epic Games' UDN Page]<br />
<br />
=====Making New Sub Level Current=====<br />
<br />
[[FILE:LevelBrowser_MakeCurrent.jpg|Set the new sub level as CURRENT]]<br />
<br />
Make the new sub level current and we are ready to start placing actors.<br />
<br />
<br />
==Results==<br />
<br />
[[FILE: PosedPlayer_Placed_L.jpg|This is what we got in Grain Elevator]]<br />
<br />
=Doing the Profile=<br />
<br />
I will document what was done at TWI. Our profiling parameters and data gathering points were specific to our needs for our designs.<br />
<br />
==Profiling Machine Hardware Specifications==<br />
<br />
These are the specifications of the test machine used at TWI<br />
<br />
*Intel Quad 2.40GHz<br />
*4GB RAM<br />
*ATI Radeon HD 5800<br />
*Test Done on High Settings<br />
<br />
==Console Commands==<br />
<br />
*'''SpawnPosedPlayers''' - this command will spawn SkeletalMeshes at the locations of the RODebugPosedPlayer map actors<br />
<br />
*'''StopPosedPlayerUpdates''' - this command will stop the engine from updating the posed players between ticks<br />
<br />
*'''PossessPosedPlayer''' - this command allows the user to possess RODebugPosedPlayer actors for "camera" viewing<br />
<br />
==Polling the Results==<br />
====Commands Used====<br />
*'''STAT FPS''': Adds Frames Per Second counter to the screen<br />
*'''STAT UNIT''': Displays the time spend for the current frame on the CPU, in the game thread, in the render thread, and on the GPU<br />
*'''STAT D3D9RHI''': Displays basic DirectX 9 rendering statistics<br />
*'''STAT ENGINE''': Displays engine-level statistics, such as triangle counts, draw calls, and the time spent performing updates to various systems<br />
*'''STAT SHADOWRENDERING''': Displays statistics for rendering dynamic shadows<br />
<br />
====Result Targets====<br />
*Frame Time '''(STAT UNIT)'''<br />
*Game Time '''(STAT UNIT)'''<br />
*FPS '''(STAT FPS)'''<br />
*Draw Time (ms) '''(STAT ENGINE)'''<br />
*GPU Time (ms) '''(STAT UNIT)'''<br />
*DrawPrimitive Calls '''(STAT D3D9RHI)'''<br />
*Triangles Drawn '''(STAT D3D9RHI)'''<br />
*Static Mesh Tris '''(STAT ENGINE)'''<br />
*Skel Mesh Draw Calls '''(STAT ENGINE)'''<br />
*Per Object shadows '''(STAT SHADOWRENDERING)'''<br />
*Preshadows '''(STAT SHADOWRENDERING)'''<br />
<br />
==Store Results for Future Profiles==<br />
<br />
=RO2 Static Mesh Combining Tool=<br />
<br />
This tool allows for you to combine similar staticmeshes into one staticmesh allowing you to reduce the overall draw calls per scene frame. We had a number of guidelines that we worked with to get the best results that we could.<br />
<br />
NOTE: When you are combining meshes it's a good idea to keep an eye on Properties -> Static Mesh Component -> Override Light Map Res and it's Boolean bit as well. Having a non default value will result in lightmap errors.<br />
<br />
[[File:StaticMeshProperties_LightmapOverride.jpg|thumb|300px|center|Keep an eye on Properties -> Static Mesh Component -> Override Light Map Res]]<br />
<br />
To override the lightmap of combined meshes, do it at the asset itself in the package. StaticMesh Asset Properties -> Light Map Resolution -> [INTEGER]<br />
<br />
[[File:StaticMeshProperties_AssetLightmapOverride.jpg|thumb|300px|center|Override the lightmap resolution here instead]]<br />
<br />
==Combining Tool Guidelines==<br />
<br />
*Do not combine meshes that do not share that same material(s) in the same slots<br />
*Do not combine too many meshes that you fight with the natural occlusion systems as even the smallest of pixel of a mesh being rendered will render the entirety of the mesh<br />
*Do not combine meshes that will give you exceedingly high poly counts. (>5000)<br />
*Do not combine meshes that you cannot use over and over as this fights with the engine's instancing capability<br />
*Culling > Occlusion<br />
<br />
==Combining Process==<br />
<br />
===Combine Mesh Context Menu===<br />
<br />
[[image:CombineMesh_ContextMenu.jpg|thumb|300px|center|RMB -> Combine Mesh from context menu]]<br />
<br />
===Create New Asset Location===<br />
<br />
[[image:CombineMesh_NewAssetLocation.jpg|thumb|300px|center|Select the Package, Group, and Name of the Asset]]<br />
<br />
===Combine Convex Collision===<br />
<br />
[[image:CombineMesh_ConvexCollisionCombine.jpg|thumb|300px|center|Takes all the convex collision hull primitives and adds them together]]<br />
<br />
===Replace Actors in Scene===<br />
<br />
[[image:CombineMesh_ReplaceActor.jpg|thumb|300px|center|Replace the actor in the scene?]]<br />
<br />
==UnCombining Process==<br />
<br />
[[image:UNCombineMesh_ContextMenu.jpg|thumb|300px|center|RMB -> Uncombine Mesh from context menu]]<br />
<br />
RMB -> UnCombine Mesh<br />
<br />
This will simply uncombine the meshes and replace them with the stored reference of the original assets in the combined mesh. Do not uncombine more than one combined mesh at a time.<br />
<br />
=Procedural bCastDynamicShow System=<br />
<br />
Every static mesh object in the map has the capability to cast a dynamic shadow. A dynamic shadow uses the cascade shadowing system to make nice crisp shadows for the world objects when the player gets near them. The down side is that they can be an expensive render, relatively, when the engine must cast a dynamic shadow into an already shadowed space. To save from having to check this on each and every object in the world a new system was introduced that traces a line from the 8 corners of the bounding box of the static mesh actor back to the DominantDirectionalLight in the map. If ANY of the traces hit the DominantDirectionalLight, the bCaseDynamicShadow Boolean variable is set to TRUE. If none of the traces touches the DominantDirectionalLight then the variable is set to FALSE.<br />
<br />
Some times you can get a false readings in situations where all 8 corners of the bounding box are contained in another mesh (such as walls with a pillar on each side of each section of wall). In this case we've given the capability for the Level Designer to override the procedural system.<br />
<br />
StaticMeshActor Properties -> StaticMeshComponent -> Lighting -> Allow Auto Cast Dynamic Shadow Override</div>Keithhttps://wiki.tripwireinteractive.com/index.php?title=Red_Orchestra_2:_Heroes_Of_Stalingrad/LevelDesign/OptimizationGuide&diff=1380Red Orchestra 2: Heroes Of Stalingrad/LevelDesign/OptimizationGuide2012-07-06T16:12:16Z<p>Keith: /* Polling the Results */</p>
<hr />
<div><br />
== Recommended Reading ==<br />
<br />
<br />
If you are new to optimizing in general for Unreal 3 games please have a look through the below web pages so you are up to speed with the grunt work.<br />
<br />
===Epic's Unreal Development Network - UDN===<br />
====[http://udn.epicgames.com/Three/PerformanceHome.html Epic's Performance UDN Page]====<br />
<br />
====[http://udn.epicgames.com/Three/ProfilingBasics.html Epic's Profiling UDN Page]====<br />
<br />
====[http://udn.epicgames.com/Three/MemoryProfilingHome.html Epic's Memory Profiling UDN Page]====<br />
<br />
====[http://udn.epicgames.com/Three/RenderThreadProfilingHome.html Epic's Rendering Thread Profiling UDN Page]====<br />
<br />
=Introduction=<br />
<br />
The purpose of this document is to give information on the guidelines used to optimize the maps inside RO2. These guidelines worked for us. If you are a community level designer and/or artist you may find this document useful. This document will cover the various approaches and the reasoning behind decisions so that the reader may be able to avoid pitfalls when making levels for Red Orchestra 2.<br />
<br />
The following is a list of items that LDs and Environment Artists should follow for a map to perform well. Most of these were lessons learnt while optimizing RO2 and should also serve as a guideline for modders to make sure that they don't run into the same pitfalls.<br />
<br />
=Level Performance Guidelines=<br />
==Terrain==<br />
<br />
=== bCastDynamicShadow ===<br />
This flag should be OFF. Setting this flag to ON will cast dynamic preshadows by the terrain for both per-object shadows and whole scene dynamic shadows, which can be very expensive depending on the number of dynamic primitives in the scene. Preshadows (which are dynamic shadows from the static environment onto dynamic objects) only make sense if the terrain has hills and valleys throughout the scene. If the scene just has a few mounds here and there it might be worth modeling the mounds with static meshes and have the terrain blend in at the bottom. The side effect of disabling bCastDynamicShadow is that terrain deco layers (e.g. grass) will not cast whole scene dynamic shadows. But considering that shadows from deco layers usually are low-res and don't look great, it is a good price to pay for a substantial performance boost.<br />
<br />
[[Image:GrassShadows.png|center|frame|Low Res deco layer shadows]]<br />
<br />
=== Terrain Layers ===<br />
The RO2 engine allows for a maximum of 12 textures to be blended for terrain. These 12 textures could be part of 2 terrain layers (6 textures each), 3 terrain layers (4 textures each), or any other combination thereof. This is a hard limit for the engine, and exceeding this limit will result in rainbow colored terrain patches. However, fetching and accessing so many textures is not cheap and since the terrain usually takes up a large portion of the screen, it is recommended that you keep the number of blend textures to a minimum.<br />
<br />
One example for this is that say you have a terrain which comprises or dirt, rubble and snow and one part of the terrain is solid concrete. Instead of making 4 terrain layers of dirt, rubble, snow and concrete and blending between them it is more optimized if the terrain uses 3 layers of dirt, rubble and snow, and the concrete portion is modeled separately as BSP, static mesh or even another terrain actor. Doing this will reduce the overall cost of rendering the entire terrain since the concrete layer texture fetches are eliminated for the rest of the terrain that doesn't need it.<br />
<br />
==Static Meshes==<br />
<br />
=== bCastDynamicShadow ===<br />
When placing a static mesh in the level, you should decide whether you want it to cast dynamic preshadows or not. Preshadows are dynamic shadows from the static environment onto dynamic objects, and can be very expensive depending on the number of dynamic primitives in the scene. Turning off this flag for a lot of static meshes in the environment in the scene such as debris, rubble, etc. will improve the dynamic shadow performance.<br />
<br />
[[Image:Preshadows.png|center|frame|Dynamic preshadows cast by tree foliage onto character]]<br />
<br />
Once the lighting in a map is finalized, you can also go through and set bCastDynamicShadow to false for all static meshes that are already in shadow (such as the truck in the following image, which is is shadow of the building) since any dynamic shadow cast by it will be drowned by the static shadow cast by the environment.<br />
<br />
[[Image:DynamicShadowTruck.jpg|thumb|300px|center|The truck does not need to cast dynamic shadows since it is already in shadow]]<br />
<br />
=== Distance Culling ===<br />
Using distance culling effectively will allow you to have a lot of detail in your environment whilst still allowing the map to perform well. There are 2 ways to do this :<br />
<br />
* You can either put a CullDistanceVolume around the map and the let the map build process choose the appropriate cull distances for the placed static meshes in the level. This method is not ideal though, and might cause certain cover objects, etc. to disappear at a distance (which is not desirable). <br />
<br />
* Or, you can manually set the MaxDrawDistance for each object.<br />
<br />
== Materials ==<br />
=== Using Material LODs ===<br />
In order to make the best looking environment materials as well as keep the overall performance cost low, consider using material LODs. The concept is very simple - assign the best looking/highest instruction count material to the base LOD for a static mesh, and then create another LOD for the static mesh (this can have the exact same triangle count as the base LOD) and assign it a simple material that does not have expensive operations such as depth biased alpha, specularity, cube maps or even normal maps. Such subtle lighting effects cannot be perceived from a distance anyway, and will make improve the fill rate for the rendered scene.<br />
<br />
[[Image:NormalMappedBaseMaterial.png|thumb|300px|center|Base material using normal maps]][[Image:SimpleMaterial.png|thumb|300px|center|Simple material that does not use normal maps]]<br />
<br />
== Dynamic Actors ==<br />
=== bDisablePerObjectShadows ===<br />
If you place an actor onto a level that casts dynamic shadows, the shadowing cost for it is one per object shadow and in certain cases a preshadow as well. If bDisablePerObjectShadows is set it will only cast dynamic shadows for the primitive if it is within the whole scene dominant shadow radius. This reduces the cost associated with shadowing for the primitive. If whole scene dominant shadows are not enabled, the primitive will not cast any dynamic shadows.<br />
<br />
[[Image:DisablePerObjectShadowsDemo.jpg|thumb|600px|center|The flag pole is outside the whole scene dominant shadow radius in the image on the left and hence is not shadowed. When the player moves such that the flag pole is now within the whole scene dominant shadow radius, it will start casting whole scene dominant shadows (right image)]]<br />
<br />
=== bAllowMergedDynamicShadows ===<br />
If this flag is set, any primitive that allows per object dynamic shadows will be considered for being merged with other primitives that allow merged per object dynamic shadows and are close enough. As a consequence, the number of dynamic shadows in the scene are reduced.<br />
<br />
The radius used to merge primitives is dynamically adjusted based on the distance of the primitives from the viewer. It starts at ''MinShadowGroupRadius'' (when the primitive is closest to the viewer) and increases up to ''MaxShadowGroupRadius'' (when the primitive is ''ShadowGroupRampCutoff'' away from the viewer). The rate of increase is determined by ''ShadowGroupRadiusRampUpFactor''. For anything beyond ''ShadowGroupRampCutoff'', the ''MaxShadowGroupRadius'' will be used. All these settings are available in the engine INI.<br />
<br />
[[Image:GroupedDynamicPerObjectShadowsDemo.jpg|thumb|600px|center|The image on the left has bAllowMergedDynamicShadows set to false on the two placed pawns, and they cast a per object shadow each. The image on the right has bAllowMergedDynamicShadows set to true on the pawns, and as such both the pawns are included in the same projected shadow.]]<br />
<br />
== Draw Calls ==<br />
== About Draw Calls==<br />
As the UE3 rendering engine is a Direct X 9.0 renderer, it is limited to one CPU core to tell the GPU about what to draw. It does this via a Draw Call. Each object you place in the world is at least one draw call (if not more due to shadows). The CPU can become the bottleneck of a level if it is trying to tell the GPU to draw a detailed scene and chokes on the amount of draw calls. This is why it is best to limit the amount in any given scene. With the Red Orchestra SDK it is very easy to make many types of levels, from wide open plains (or with rolling hills) to detailed interior settings and building to building fighting. However, depending on what the scale of your map is, you will be limited in the amount of "detail" you can place in the level. <br />
<br />
<br />
== Limiting Draw Calls Per Scene==<br />
Suggested Maximum Draw Call Limit: 2000<br />
<br />
Using the console command ''Stat d3d9rhi"'' a Level Designer/Artist (or anyone) can go through a level and find out the amount of Draw Calls and optimize based on areas where it has increased beyond the suggested maximum.<br />
<br />
The details settings for both users and in the SDK allows Level Designers to put some objects on different levels of the setting so those with faster computers (in this case CPU core speed) can see more details without harming performance for those with slower machines. It is best to do this with "fluff" detail that is not gameplay important but just makes the level look better overall.<br />
<br />
<br />
=Profiling Preliminary Work=<br />
<br />
There is a small amount of setup work that must be completed.<br />
<br />
==RODebugPosedPlayer==<br />
<br />
We have made a tool for level designers and artists that are used to gather statistical data about maps called Posed Players. The purpose of the Posed Player is to have a placeable actor to simulate a player in a scene. It has the capability to be used as a camera during profile stage. All of which I will go over now.<br />
<br />
===Actor In Tree===<br />
<br />
[[Image:RODebugPosedPlayerActorTree.jpg|thumb|300px|center|RODebugPosedPlayer in Actor Tree]]<br />
<br />
The RODebugPosedPlayer actor is found at Actor -> RODebugPosedPlayer<br />
<br />
===Properties===<br />
<br />
[[File:RODebugPosedPlayerProperties.jpg|Properties of RODebugPosedPlayer]]<br />
<br />
*Pose: The pose, or stance, the posed player will be in when spawned<br />
*Weapon: The weapon the posed player will be using when posed<br />
*Pawn Type: German or Russian<br />
*Can Possess: Allows the user to possess this posed player using the '''PossessPosedPlayer''' console command<br />
*Description: Small description on what this posed player is - OPTIONAL<br />
<br />
====Available Poses====<br />
<br />
[[File:RODebugPosedPlayerProperties_Pose.jpg|Available Poses for RODebugPosedPlayer]]<br />
<br />
The pose will not make a difference in regards to performance and optimization. It was added so if you wanted to stage a scene for screen shots or something along those lines, this allows you to put the posed player into various positions.<br />
<br />
====Can Possess====<br />
<br />
[[File:RODebugPosedPlayerProperties_CanPossess.jpg|Can Possess Changes Color of RODebugPosedPlayer to BLUE]]<br />
<br />
==Placing RODebugPosedPlayer Actor in Map==<br />
<br />
====Posed Player Placement Guideline====<br />
<br />
*Expected player count is 64 player which would be the worse case scenario in regards to performance<br />
*Use Can Possess on posed players that have vantage view on a particular high traffic area/areas of performance pits<br />
*Any particular player SHOULD NOT see 100% of the map nor players<br />
*Place the actors where players will be<br />
*Do not unnaturally bunch up the posed players<br />
*Distribute the posed players evenly across scene<br />
*More actors near objective spaces, spawn areas, and known fight spaces<br />
*Position RODebugPosedPlayers ~16 Unreal Units above surface to avoid posed player clipping/failure to spawn<br />
<br />
====Create a NEW sublevel====<br />
<br />
[[FILE:LevelBrowser_CreateNEW.jpg|Create a new sub level]]<br />
<br />
=====Naming the Sub Level=====<br />
<br />
[[FILE:LevelBrowser_LevelName.jpg|Give the new sub level a name]]<br />
<br />
Give the sub level a name. It really doesn't matter what you call it as long as you know what it is.<br />
<br />
=====Setting Streaming Method=====<br />
<br />
[[File:LevelBrowser_StreamingMethod.jpg|Set Streaming Method to Always Loaded]]<br />
<br />
We always use Always Loaded so that every time the persistent is loaded, so is this sublevel. Done this way there is no need to have Kismet handle it.<br />
<br />
Options:<br />
*Kismet- Used when you want to use a Kismet node to stream in the sub level. <br />
*Distance- Used when you want to use a certain distance.<br />
*Always Loaded- Used when you want the sub level always loaded when the persistent is loaded.<br />
<br />
[http://udn.epicgames.com/Three/LevelStreamingHome.html Epic Games' UDN Page]<br />
<br />
=====Making New Sub Level Current=====<br />
<br />
[[FILE:LevelBrowser_MakeCurrent.jpg|Set the new sub level as CURRENT]]<br />
<br />
Make the new sub level current and we are ready to start placing actors.<br />
<br />
<br />
==Results==<br />
<br />
[[FILE: PosedPlayer_Placed_L.jpg|This is what we got in Grain Elevator]]<br />
<br />
=Doing the Profile=<br />
<br />
I will document what was done at TWI. Our profiling parameters and data gathering points were specific to our needs for our designs.<br />
<br />
==Profiling Machine Hardware Specifications==<br />
<br />
These are the specifications of the test machine used at TWI<br />
<br />
*Intel Quad 2.40GHz<br />
*4GB RAM<br />
*ATI Radeon HD 5800<br />
*Test Done on High Settings<br />
<br />
==Console Commands==<br />
<br />
*'''SpawnPosedPlayers''' - this command will spawn SkeletalMeshes at the locations of the RODebugPosedPlayer map actors<br />
<br />
*'''StopPosedPlayerUpdates''' - this command will stop the engine from updating the posed players between ticks<br />
<br />
*'''PossessPosedPlayer''' - this command allows the user to possess RODebugPosedPlayer actors for "camera" viewing<br />
<br />
==Polling the Results==<br />
====Commands Used====<br />
*'''STAT FPS''': Adds Frames Per Second counter to the screen<br />
*'''STAT UNIT''': Displays the time spend for the current frame on the CPU, in the game thread, in the render thread, and on the GPU<br />
*'''STAT D3D9RHI''': Displays basic DirectX 9 rendering statistics<br />
*'''STAT ENGINE''': Displays engine-level statistics, such as triangle counts, draw calls, and the time spent performing updates to various systems<br />
*'''STAT SHADOWRENDERING''': Displays statistics for rendering dynamic shadows<br />
<br />
====Result Targets====<br />
*Frame Time (STAT UNIT)<br />
*Game Time (STAT UNIT)<br />
*FPS (STAT FPS)<br />
*Draw Time (ms) (STAT ENGINE)<br />
*GPU Time (ms) (STAT UNIT)<br />
*DrawPrimitive Calls (STAT D3D9RHI)<br />
*Triangles Drawn (STAT D3D9RHI)<br />
*Static Mesh Tris (STAT ENGINE)<br />
*Skel Mesh Draw Calls (STAT ENGINE)<br />
*Per Object shadows (STAT SHADOWRENDERING)<br />
*Preshadows (STAT SHADOWRENDERING)<br />
<br />
==Store Results for Future Profiles==<br />
<br />
=RO2 Static Mesh Combining Tool=<br />
<br />
This tool allows for you to combine similar staticmeshes into one staticmesh allowing you to reduce the overall draw calls per scene frame. We had a number of guidelines that we worked with to get the best results that we could.<br />
<br />
NOTE: When you are combining meshes it's a good idea to keep an eye on Properties -> Static Mesh Component -> Override Light Map Res and it's Boolean bit as well. Having a non default value will result in lightmap errors.<br />
<br />
[[File:StaticMeshProperties_LightmapOverride.jpg|thumb|300px|center|Keep an eye on Properties -> Static Mesh Component -> Override Light Map Res]]<br />
<br />
To override the lightmap of combined meshes, do it at the asset itself in the package. StaticMesh Asset Properties -> Light Map Resolution -> [INTEGER]<br />
<br />
[[File:StaticMeshProperties_AssetLightmapOverride.jpg|thumb|300px|center|Override the lightmap resolution here instead]]<br />
<br />
==Combining Tool Guidelines==<br />
<br />
*Do not combine meshes that do not share that same material(s) in the same slots<br />
*Do not combine too many meshes that you fight with the natural occlusion systems as even the smallest of pixel of a mesh being rendered will render the entirety of the mesh<br />
*Do not combine meshes that will give you exceedingly high poly counts. (>5000)<br />
*Do not combine meshes that you cannot use over and over as this fights with the engine's instancing capability<br />
*Culling > Occlusion<br />
<br />
==Combining Process==<br />
<br />
===Combine Mesh Context Menu===<br />
<br />
[[image:CombineMesh_ContextMenu.jpg|thumb|300px|center|RMB -> Combine Mesh from context menu]]<br />
<br />
===Create New Asset Location===<br />
<br />
[[image:CombineMesh_NewAssetLocation.jpg|thumb|300px|center|Select the Package, Group, and Name of the Asset]]<br />
<br />
===Combine Convex Collision===<br />
<br />
[[image:CombineMesh_ConvexCollisionCombine.jpg|thumb|300px|center|Takes all the convex collision hull primitives and adds them together]]<br />
<br />
===Replace Actors in Scene===<br />
<br />
[[image:CombineMesh_ReplaceActor.jpg|thumb|300px|center|Replace the actor in the scene?]]<br />
<br />
==UnCombining Process==<br />
<br />
[[image:UNCombineMesh_ContextMenu.jpg|thumb|300px|center|RMB -> Uncombine Mesh from context menu]]<br />
<br />
RMB -> UnCombine Mesh<br />
<br />
This will simply uncombine the meshes and replace them with the stored reference of the original assets in the combined mesh. Do not uncombine more than one combined mesh at a time.<br />
<br />
=Procedural bCastDynamicShow System=<br />
<br />
Every static mesh object in the map has the capability to cast a dynamic shadow. A dynamic shadow uses the cascade shadowing system to make nice crisp shadows for the world objects when the player gets near them. The down side is that they can be an expensive render, relatively, when the engine must cast a dynamic shadow into an already shadowed space. To save from having to check this on each and every object in the world a new system was introduced that traces a line from the 8 corners of the bounding box of the static mesh actor back to the DominantDirectionalLight in the map. If ANY of the traces hit the DominantDirectionalLight, the bCaseDynamicShadow Boolean variable is set to TRUE. If none of the traces touches the DominantDirectionalLight then the variable is set to FALSE.<br />
<br />
Some times you can get a false readings in situations where all 8 corners of the bounding box are contained in another mesh (such as walls with a pillar on each side of each section of wall). In this case we've given the capability for the Level Designer to override the procedural system.<br />
<br />
StaticMeshActor Properties -> StaticMeshComponent -> Lighting -> Allow Auto Cast Dynamic Shadow Override</div>Keithhttps://wiki.tripwireinteractive.com/index.php?title=Red_Orchestra_2:_Heroes_Of_Stalingrad/LevelDesign/OptimizationGuide&diff=1379Red Orchestra 2: Heroes Of Stalingrad/LevelDesign/OptimizationGuide2012-07-06T16:11:32Z<p>Keith: /* Polling the Results */</p>
<hr />
<div><br />
== Recommended Reading ==<br />
<br />
<br />
If you are new to optimizing in general for Unreal 3 games please have a look through the below web pages so you are up to speed with the grunt work.<br />
<br />
===Epic's Unreal Development Network - UDN===<br />
====[http://udn.epicgames.com/Three/PerformanceHome.html Epic's Performance UDN Page]====<br />
<br />
====[http://udn.epicgames.com/Three/ProfilingBasics.html Epic's Profiling UDN Page]====<br />
<br />
====[http://udn.epicgames.com/Three/MemoryProfilingHome.html Epic's Memory Profiling UDN Page]====<br />
<br />
====[http://udn.epicgames.com/Three/RenderThreadProfilingHome.html Epic's Rendering Thread Profiling UDN Page]====<br />
<br />
=Introduction=<br />
<br />
The purpose of this document is to give information on the guidelines used to optimize the maps inside RO2. These guidelines worked for us. If you are a community level designer and/or artist you may find this document useful. This document will cover the various approaches and the reasoning behind decisions so that the reader may be able to avoid pitfalls when making levels for Red Orchestra 2.<br />
<br />
The following is a list of items that LDs and Environment Artists should follow for a map to perform well. Most of these were lessons learnt while optimizing RO2 and should also serve as a guideline for modders to make sure that they don't run into the same pitfalls.<br />
<br />
=Level Performance Guidelines=<br />
==Terrain==<br />
<br />
=== bCastDynamicShadow ===<br />
This flag should be OFF. Setting this flag to ON will cast dynamic preshadows by the terrain for both per-object shadows and whole scene dynamic shadows, which can be very expensive depending on the number of dynamic primitives in the scene. Preshadows (which are dynamic shadows from the static environment onto dynamic objects) only make sense if the terrain has hills and valleys throughout the scene. If the scene just has a few mounds here and there it might be worth modeling the mounds with static meshes and have the terrain blend in at the bottom. The side effect of disabling bCastDynamicShadow is that terrain deco layers (e.g. grass) will not cast whole scene dynamic shadows. But considering that shadows from deco layers usually are low-res and don't look great, it is a good price to pay for a substantial performance boost.<br />
<br />
[[Image:GrassShadows.png|center|frame|Low Res deco layer shadows]]<br />
<br />
=== Terrain Layers ===<br />
The RO2 engine allows for a maximum of 12 textures to be blended for terrain. These 12 textures could be part of 2 terrain layers (6 textures each), 3 terrain layers (4 textures each), or any other combination thereof. This is a hard limit for the engine, and exceeding this limit will result in rainbow colored terrain patches. However, fetching and accessing so many textures is not cheap and since the terrain usually takes up a large portion of the screen, it is recommended that you keep the number of blend textures to a minimum.<br />
<br />
One example for this is that say you have a terrain which comprises or dirt, rubble and snow and one part of the terrain is solid concrete. Instead of making 4 terrain layers of dirt, rubble, snow and concrete and blending between them it is more optimized if the terrain uses 3 layers of dirt, rubble and snow, and the concrete portion is modeled separately as BSP, static mesh or even another terrain actor. Doing this will reduce the overall cost of rendering the entire terrain since the concrete layer texture fetches are eliminated for the rest of the terrain that doesn't need it.<br />
<br />
==Static Meshes==<br />
<br />
=== bCastDynamicShadow ===<br />
When placing a static mesh in the level, you should decide whether you want it to cast dynamic preshadows or not. Preshadows are dynamic shadows from the static environment onto dynamic objects, and can be very expensive depending on the number of dynamic primitives in the scene. Turning off this flag for a lot of static meshes in the environment in the scene such as debris, rubble, etc. will improve the dynamic shadow performance.<br />
<br />
[[Image:Preshadows.png|center|frame|Dynamic preshadows cast by tree foliage onto character]]<br />
<br />
Once the lighting in a map is finalized, you can also go through and set bCastDynamicShadow to false for all static meshes that are already in shadow (such as the truck in the following image, which is is shadow of the building) since any dynamic shadow cast by it will be drowned by the static shadow cast by the environment.<br />
<br />
[[Image:DynamicShadowTruck.jpg|thumb|300px|center|The truck does not need to cast dynamic shadows since it is already in shadow]]<br />
<br />
=== Distance Culling ===<br />
Using distance culling effectively will allow you to have a lot of detail in your environment whilst still allowing the map to perform well. There are 2 ways to do this :<br />
<br />
* You can either put a CullDistanceVolume around the map and the let the map build process choose the appropriate cull distances for the placed static meshes in the level. This method is not ideal though, and might cause certain cover objects, etc. to disappear at a distance (which is not desirable). <br />
<br />
* Or, you can manually set the MaxDrawDistance for each object.<br />
<br />
== Materials ==<br />
=== Using Material LODs ===<br />
In order to make the best looking environment materials as well as keep the overall performance cost low, consider using material LODs. The concept is very simple - assign the best looking/highest instruction count material to the base LOD for a static mesh, and then create another LOD for the static mesh (this can have the exact same triangle count as the base LOD) and assign it a simple material that does not have expensive operations such as depth biased alpha, specularity, cube maps or even normal maps. Such subtle lighting effects cannot be perceived from a distance anyway, and will make improve the fill rate for the rendered scene.<br />
<br />
[[Image:NormalMappedBaseMaterial.png|thumb|300px|center|Base material using normal maps]][[Image:SimpleMaterial.png|thumb|300px|center|Simple material that does not use normal maps]]<br />
<br />
== Dynamic Actors ==<br />
=== bDisablePerObjectShadows ===<br />
If you place an actor onto a level that casts dynamic shadows, the shadowing cost for it is one per object shadow and in certain cases a preshadow as well. If bDisablePerObjectShadows is set it will only cast dynamic shadows for the primitive if it is within the whole scene dominant shadow radius. This reduces the cost associated with shadowing for the primitive. If whole scene dominant shadows are not enabled, the primitive will not cast any dynamic shadows.<br />
<br />
[[Image:DisablePerObjectShadowsDemo.jpg|thumb|600px|center|The flag pole is outside the whole scene dominant shadow radius in the image on the left and hence is not shadowed. When the player moves such that the flag pole is now within the whole scene dominant shadow radius, it will start casting whole scene dominant shadows (right image)]]<br />
<br />
=== bAllowMergedDynamicShadows ===<br />
If this flag is set, any primitive that allows per object dynamic shadows will be considered for being merged with other primitives that allow merged per object dynamic shadows and are close enough. As a consequence, the number of dynamic shadows in the scene are reduced.<br />
<br />
The radius used to merge primitives is dynamically adjusted based on the distance of the primitives from the viewer. It starts at ''MinShadowGroupRadius'' (when the primitive is closest to the viewer) and increases up to ''MaxShadowGroupRadius'' (when the primitive is ''ShadowGroupRampCutoff'' away from the viewer). The rate of increase is determined by ''ShadowGroupRadiusRampUpFactor''. For anything beyond ''ShadowGroupRampCutoff'', the ''MaxShadowGroupRadius'' will be used. All these settings are available in the engine INI.<br />
<br />
[[Image:GroupedDynamicPerObjectShadowsDemo.jpg|thumb|600px|center|The image on the left has bAllowMergedDynamicShadows set to false on the two placed pawns, and they cast a per object shadow each. The image on the right has bAllowMergedDynamicShadows set to true on the pawns, and as such both the pawns are included in the same projected shadow.]]<br />
<br />
== Draw Calls ==<br />
== About Draw Calls==<br />
As the UE3 rendering engine is a Direct X 9.0 renderer, it is limited to one CPU core to tell the GPU about what to draw. It does this via a Draw Call. Each object you place in the world is at least one draw call (if not more due to shadows). The CPU can become the bottleneck of a level if it is trying to tell the GPU to draw a detailed scene and chokes on the amount of draw calls. This is why it is best to limit the amount in any given scene. With the Red Orchestra SDK it is very easy to make many types of levels, from wide open plains (or with rolling hills) to detailed interior settings and building to building fighting. However, depending on what the scale of your map is, you will be limited in the amount of "detail" you can place in the level. <br />
<br />
<br />
== Limiting Draw Calls Per Scene==<br />
Suggested Maximum Draw Call Limit: 2000<br />
<br />
Using the console command ''Stat d3d9rhi"'' a Level Designer/Artist (or anyone) can go through a level and find out the amount of Draw Calls and optimize based on areas where it has increased beyond the suggested maximum.<br />
<br />
The details settings for both users and in the SDK allows Level Designers to put some objects on different levels of the setting so those with faster computers (in this case CPU core speed) can see more details without harming performance for those with slower machines. It is best to do this with "fluff" detail that is not gameplay important but just makes the level look better overall.<br />
<br />
<br />
=Profiling Preliminary Work=<br />
<br />
There is a small amount of setup work that must be completed.<br />
<br />
==RODebugPosedPlayer==<br />
<br />
We have made a tool for level designers and artists that are used to gather statistical data about maps called Posed Players. The purpose of the Posed Player is to have a placeable actor to simulate a player in a scene. It has the capability to be used as a camera during profile stage. All of which I will go over now.<br />
<br />
===Actor In Tree===<br />
<br />
[[Image:RODebugPosedPlayerActorTree.jpg|thumb|300px|center|RODebugPosedPlayer in Actor Tree]]<br />
<br />
The RODebugPosedPlayer actor is found at Actor -> RODebugPosedPlayer<br />
<br />
===Properties===<br />
<br />
[[File:RODebugPosedPlayerProperties.jpg|Properties of RODebugPosedPlayer]]<br />
<br />
*Pose: The pose, or stance, the posed player will be in when spawned<br />
*Weapon: The weapon the posed player will be using when posed<br />
*Pawn Type: German or Russian<br />
*Can Possess: Allows the user to possess this posed player using the '''PossessPosedPlayer''' console command<br />
*Description: Small description on what this posed player is - OPTIONAL<br />
<br />
====Available Poses====<br />
<br />
[[File:RODebugPosedPlayerProperties_Pose.jpg|Available Poses for RODebugPosedPlayer]]<br />
<br />
The pose will not make a difference in regards to performance and optimization. It was added so if you wanted to stage a scene for screen shots or something along those lines, this allows you to put the posed player into various positions.<br />
<br />
====Can Possess====<br />
<br />
[[File:RODebugPosedPlayerProperties_CanPossess.jpg|Can Possess Changes Color of RODebugPosedPlayer to BLUE]]<br />
<br />
==Placing RODebugPosedPlayer Actor in Map==<br />
<br />
====Posed Player Placement Guideline====<br />
<br />
*Expected player count is 64 player which would be the worse case scenario in regards to performance<br />
*Use Can Possess on posed players that have vantage view on a particular high traffic area/areas of performance pits<br />
*Any particular player SHOULD NOT see 100% of the map nor players<br />
*Place the actors where players will be<br />
*Do not unnaturally bunch up the posed players<br />
*Distribute the posed players evenly across scene<br />
*More actors near objective spaces, spawn areas, and known fight spaces<br />
*Position RODebugPosedPlayers ~16 Unreal Units above surface to avoid posed player clipping/failure to spawn<br />
<br />
====Create a NEW sublevel====<br />
<br />
[[FILE:LevelBrowser_CreateNEW.jpg|Create a new sub level]]<br />
<br />
=====Naming the Sub Level=====<br />
<br />
[[FILE:LevelBrowser_LevelName.jpg|Give the new sub level a name]]<br />
<br />
Give the sub level a name. It really doesn't matter what you call it as long as you know what it is.<br />
<br />
=====Setting Streaming Method=====<br />
<br />
[[File:LevelBrowser_StreamingMethod.jpg|Set Streaming Method to Always Loaded]]<br />
<br />
We always use Always Loaded so that every time the persistent is loaded, so is this sublevel. Done this way there is no need to have Kismet handle it.<br />
<br />
Options:<br />
*Kismet- Used when you want to use a Kismet node to stream in the sub level. <br />
*Distance- Used when you want to use a certain distance.<br />
*Always Loaded- Used when you want the sub level always loaded when the persistent is loaded.<br />
<br />
[http://udn.epicgames.com/Three/LevelStreamingHome.html Epic Games' UDN Page]<br />
<br />
=====Making New Sub Level Current=====<br />
<br />
[[FILE:LevelBrowser_MakeCurrent.jpg|Set the new sub level as CURRENT]]<br />
<br />
Make the new sub level current and we are ready to start placing actors.<br />
<br />
<br />
==Results==<br />
<br />
[[FILE: PosedPlayer_Placed_L.jpg|This is what we got in Grain Elevator]]<br />
<br />
=Doing the Profile=<br />
<br />
I will document what was done at TWI. Our profiling parameters and data gathering points were specific to our needs for our designs.<br />
<br />
==Profiling Machine Hardware Specifications==<br />
<br />
These are the specifications of the test machine used at TWI<br />
<br />
*Intel Quad 2.40GHz<br />
*4GB RAM<br />
*ATI Radeon HD 5800<br />
*Test Done on High Settings<br />
<br />
==Console Commands==<br />
<br />
*'''SpawnPosedPlayers''' - this command will spawn SkeletalMeshes at the locations of the RODebugPosedPlayer map actors<br />
<br />
*'''StopPosedPlayerUpdates''' - this command will stop the engine from updating the posed players between ticks<br />
<br />
*'''PossessPosedPlayer''' - this command allows the user to possess RODebugPosedPlayer actors for "camera" viewing<br />
<br />
==Polling the Results==<br />
<br />
*'''STAT FPS''': Adds Frames Per Second counter to the screen<br />
*'''STAT UNIT''': Displays the time spend for the current frame on the CPU, in the game thread, in the render thread, and on the GPU<br />
*'''STAT D3D9RHI''': Displays basic DirectX 9 rendering statistics<br />
*'''STAT ENGINE''': Displays engine-level statistics, such as triangle counts, draw calls, and the time spent performing updates to various systems<br />
*'''STAT SHADOWRENDERING''': Displays statistics for rendering dynamic shadows<br />
<br />
*Frame Time (STAT UNIT)<br />
*Game Time (STAT UNIT)<br />
*FPS (STAT FPS)<br />
*Draw Time (ms) (STAT ENGINE)<br />
*GPU Time (ms) (STAT UNIT)<br />
*DrawPrimitive Calls (STAT D3D9RHI)<br />
*Triangles Drawn (STAT D3D9RHI)<br />
*Static Mesh Tris (STAT ENGINE)<br />
*Skel Mesh Draw Calls (STAT ENGINE)<br />
*Per Object shadows (STAT SHADOWRENDERING)<br />
*Preshadows (STAT SHADOWRENDERING)<br />
<br />
==Store Results for Future Profiles==<br />
<br />
=RO2 Static Mesh Combining Tool=<br />
<br />
This tool allows for you to combine similar staticmeshes into one staticmesh allowing you to reduce the overall draw calls per scene frame. We had a number of guidelines that we worked with to get the best results that we could.<br />
<br />
NOTE: When you are combining meshes it's a good idea to keep an eye on Properties -> Static Mesh Component -> Override Light Map Res and it's Boolean bit as well. Having a non default value will result in lightmap errors.<br />
<br />
[[File:StaticMeshProperties_LightmapOverride.jpg|thumb|300px|center|Keep an eye on Properties -> Static Mesh Component -> Override Light Map Res]]<br />
<br />
To override the lightmap of combined meshes, do it at the asset itself in the package. StaticMesh Asset Properties -> Light Map Resolution -> [INTEGER]<br />
<br />
[[File:StaticMeshProperties_AssetLightmapOverride.jpg|thumb|300px|center|Override the lightmap resolution here instead]]<br />
<br />
==Combining Tool Guidelines==<br />
<br />
*Do not combine meshes that do not share that same material(s) in the same slots<br />
*Do not combine too many meshes that you fight with the natural occlusion systems as even the smallest of pixel of a mesh being rendered will render the entirety of the mesh<br />
*Do not combine meshes that will give you exceedingly high poly counts. (>5000)<br />
*Do not combine meshes that you cannot use over and over as this fights with the engine's instancing capability<br />
*Culling > Occlusion<br />
<br />
==Combining Process==<br />
<br />
===Combine Mesh Context Menu===<br />
<br />
[[image:CombineMesh_ContextMenu.jpg|thumb|300px|center|RMB -> Combine Mesh from context menu]]<br />
<br />
===Create New Asset Location===<br />
<br />
[[image:CombineMesh_NewAssetLocation.jpg|thumb|300px|center|Select the Package, Group, and Name of the Asset]]<br />
<br />
===Combine Convex Collision===<br />
<br />
[[image:CombineMesh_ConvexCollisionCombine.jpg|thumb|300px|center|Takes all the convex collision hull primitives and adds them together]]<br />
<br />
===Replace Actors in Scene===<br />
<br />
[[image:CombineMesh_ReplaceActor.jpg|thumb|300px|center|Replace the actor in the scene?]]<br />
<br />
==UnCombining Process==<br />
<br />
[[image:UNCombineMesh_ContextMenu.jpg|thumb|300px|center|RMB -> Uncombine Mesh from context menu]]<br />
<br />
RMB -> UnCombine Mesh<br />
<br />
This will simply uncombine the meshes and replace them with the stored reference of the original assets in the combined mesh. Do not uncombine more than one combined mesh at a time.<br />
<br />
=Procedural bCastDynamicShow System=<br />
<br />
Every static mesh object in the map has the capability to cast a dynamic shadow. A dynamic shadow uses the cascade shadowing system to make nice crisp shadows for the world objects when the player gets near them. The down side is that they can be an expensive render, relatively, when the engine must cast a dynamic shadow into an already shadowed space. To save from having to check this on each and every object in the world a new system was introduced that traces a line from the 8 corners of the bounding box of the static mesh actor back to the DominantDirectionalLight in the map. If ANY of the traces hit the DominantDirectionalLight, the bCaseDynamicShadow Boolean variable is set to TRUE. If none of the traces touches the DominantDirectionalLight then the variable is set to FALSE.<br />
<br />
Some times you can get a false readings in situations where all 8 corners of the bounding box are contained in another mesh (such as walls with a pillar on each side of each section of wall). In this case we've given the capability for the Level Designer to override the procedural system.<br />
<br />
StaticMeshActor Properties -> StaticMeshComponent -> Lighting -> Allow Auto Cast Dynamic Shadow Override</div>Keithhttps://wiki.tripwireinteractive.com/index.php?title=Red_Orchestra_2:_Heroes_Of_Stalingrad/LevelDesign/OptimizationGuide&diff=1378Red Orchestra 2: Heroes Of Stalingrad/LevelDesign/OptimizationGuide2012-07-06T16:03:16Z<p>Keith: /* Console Commands */</p>
<hr />
<div><br />
== Recommended Reading ==<br />
<br />
<br />
If you are new to optimizing in general for Unreal 3 games please have a look through the below web pages so you are up to speed with the grunt work.<br />
<br />
===Epic's Unreal Development Network - UDN===<br />
====[http://udn.epicgames.com/Three/PerformanceHome.html Epic's Performance UDN Page]====<br />
<br />
====[http://udn.epicgames.com/Three/ProfilingBasics.html Epic's Profiling UDN Page]====<br />
<br />
====[http://udn.epicgames.com/Three/MemoryProfilingHome.html Epic's Memory Profiling UDN Page]====<br />
<br />
====[http://udn.epicgames.com/Three/RenderThreadProfilingHome.html Epic's Rendering Thread Profiling UDN Page]====<br />
<br />
=Introduction=<br />
<br />
The purpose of this document is to give information on the guidelines used to optimize the maps inside RO2. These guidelines worked for us. If you are a community level designer and/or artist you may find this document useful. This document will cover the various approaches and the reasoning behind decisions so that the reader may be able to avoid pitfalls when making levels for Red Orchestra 2.<br />
<br />
The following is a list of items that LDs and Environment Artists should follow for a map to perform well. Most of these were lessons learnt while optimizing RO2 and should also serve as a guideline for modders to make sure that they don't run into the same pitfalls.<br />
<br />
=Level Performance Guidelines=<br />
==Terrain==<br />
<br />
=== bCastDynamicShadow ===<br />
This flag should be OFF. Setting this flag to ON will cast dynamic preshadows by the terrain for both per-object shadows and whole scene dynamic shadows, which can be very expensive depending on the number of dynamic primitives in the scene. Preshadows (which are dynamic shadows from the static environment onto dynamic objects) only make sense if the terrain has hills and valleys throughout the scene. If the scene just has a few mounds here and there it might be worth modeling the mounds with static meshes and have the terrain blend in at the bottom. The side effect of disabling bCastDynamicShadow is that terrain deco layers (e.g. grass) will not cast whole scene dynamic shadows. But considering that shadows from deco layers usually are low-res and don't look great, it is a good price to pay for a substantial performance boost.<br />
<br />
[[Image:GrassShadows.png|center|frame|Low Res deco layer shadows]]<br />
<br />
=== Terrain Layers ===<br />
The RO2 engine allows for a maximum of 12 textures to be blended for terrain. These 12 textures could be part of 2 terrain layers (6 textures each), 3 terrain layers (4 textures each), or any other combination thereof. This is a hard limit for the engine, and exceeding this limit will result in rainbow colored terrain patches. However, fetching and accessing so many textures is not cheap and since the terrain usually takes up a large portion of the screen, it is recommended that you keep the number of blend textures to a minimum.<br />
<br />
One example for this is that say you have a terrain which comprises or dirt, rubble and snow and one part of the terrain is solid concrete. Instead of making 4 terrain layers of dirt, rubble, snow and concrete and blending between them it is more optimized if the terrain uses 3 layers of dirt, rubble and snow, and the concrete portion is modeled separately as BSP, static mesh or even another terrain actor. Doing this will reduce the overall cost of rendering the entire terrain since the concrete layer texture fetches are eliminated for the rest of the terrain that doesn't need it.<br />
<br />
==Static Meshes==<br />
<br />
=== bCastDynamicShadow ===<br />
When placing a static mesh in the level, you should decide whether you want it to cast dynamic preshadows or not. Preshadows are dynamic shadows from the static environment onto dynamic objects, and can be very expensive depending on the number of dynamic primitives in the scene. Turning off this flag for a lot of static meshes in the environment in the scene such as debris, rubble, etc. will improve the dynamic shadow performance.<br />
<br />
[[Image:Preshadows.png|center|frame|Dynamic preshadows cast by tree foliage onto character]]<br />
<br />
Once the lighting in a map is finalized, you can also go through and set bCastDynamicShadow to false for all static meshes that are already in shadow (such as the truck in the following image, which is is shadow of the building) since any dynamic shadow cast by it will be drowned by the static shadow cast by the environment.<br />
<br />
[[Image:DynamicShadowTruck.jpg|thumb|300px|center|The truck does not need to cast dynamic shadows since it is already in shadow]]<br />
<br />
=== Distance Culling ===<br />
Using distance culling effectively will allow you to have a lot of detail in your environment whilst still allowing the map to perform well. There are 2 ways to do this :<br />
<br />
* You can either put a CullDistanceVolume around the map and the let the map build process choose the appropriate cull distances for the placed static meshes in the level. This method is not ideal though, and might cause certain cover objects, etc. to disappear at a distance (which is not desirable). <br />
<br />
* Or, you can manually set the MaxDrawDistance for each object.<br />
<br />
== Materials ==<br />
=== Using Material LODs ===<br />
In order to make the best looking environment materials as well as keep the overall performance cost low, consider using material LODs. The concept is very simple - assign the best looking/highest instruction count material to the base LOD for a static mesh, and then create another LOD for the static mesh (this can have the exact same triangle count as the base LOD) and assign it a simple material that does not have expensive operations such as depth biased alpha, specularity, cube maps or even normal maps. Such subtle lighting effects cannot be perceived from a distance anyway, and will make improve the fill rate for the rendered scene.<br />
<br />
[[Image:NormalMappedBaseMaterial.png|thumb|300px|center|Base material using normal maps]][[Image:SimpleMaterial.png|thumb|300px|center|Simple material that does not use normal maps]]<br />
<br />
== Dynamic Actors ==<br />
=== bDisablePerObjectShadows ===<br />
If you place an actor onto a level that casts dynamic shadows, the shadowing cost for it is one per object shadow and in certain cases a preshadow as well. If bDisablePerObjectShadows is set it will only cast dynamic shadows for the primitive if it is within the whole scene dominant shadow radius. This reduces the cost associated with shadowing for the primitive. If whole scene dominant shadows are not enabled, the primitive will not cast any dynamic shadows.<br />
<br />
[[Image:DisablePerObjectShadowsDemo.jpg|thumb|600px|center|The flag pole is outside the whole scene dominant shadow radius in the image on the left and hence is not shadowed. When the player moves such that the flag pole is now within the whole scene dominant shadow radius, it will start casting whole scene dominant shadows (right image)]]<br />
<br />
=== bAllowMergedDynamicShadows ===<br />
If this flag is set, any primitive that allows per object dynamic shadows will be considered for being merged with other primitives that allow merged per object dynamic shadows and are close enough. As a consequence, the number of dynamic shadows in the scene are reduced.<br />
<br />
The radius used to merge primitives is dynamically adjusted based on the distance of the primitives from the viewer. It starts at ''MinShadowGroupRadius'' (when the primitive is closest to the viewer) and increases up to ''MaxShadowGroupRadius'' (when the primitive is ''ShadowGroupRampCutoff'' away from the viewer). The rate of increase is determined by ''ShadowGroupRadiusRampUpFactor''. For anything beyond ''ShadowGroupRampCutoff'', the ''MaxShadowGroupRadius'' will be used. All these settings are available in the engine INI.<br />
<br />
[[Image:GroupedDynamicPerObjectShadowsDemo.jpg|thumb|600px|center|The image on the left has bAllowMergedDynamicShadows set to false on the two placed pawns, and they cast a per object shadow each. The image on the right has bAllowMergedDynamicShadows set to true on the pawns, and as such both the pawns are included in the same projected shadow.]]<br />
<br />
== Draw Calls ==<br />
== About Draw Calls==<br />
As the UE3 rendering engine is a Direct X 9.0 renderer, it is limited to one CPU core to tell the GPU about what to draw. It does this via a Draw Call. Each object you place in the world is at least one draw call (if not more due to shadows). The CPU can become the bottleneck of a level if it is trying to tell the GPU to draw a detailed scene and chokes on the amount of draw calls. This is why it is best to limit the amount in any given scene. With the Red Orchestra SDK it is very easy to make many types of levels, from wide open plains (or with rolling hills) to detailed interior settings and building to building fighting. However, depending on what the scale of your map is, you will be limited in the amount of "detail" you can place in the level. <br />
<br />
<br />
== Limiting Draw Calls Per Scene==<br />
Suggested Maximum Draw Call Limit: 2000<br />
<br />
Using the console command ''Stat d3d9rhi"'' a Level Designer/Artist (or anyone) can go through a level and find out the amount of Draw Calls and optimize based on areas where it has increased beyond the suggested maximum.<br />
<br />
The details settings for both users and in the SDK allows Level Designers to put some objects on different levels of the setting so those with faster computers (in this case CPU core speed) can see more details without harming performance for those with slower machines. It is best to do this with "fluff" detail that is not gameplay important but just makes the level look better overall.<br />
<br />
<br />
=Profiling Preliminary Work=<br />
<br />
There is a small amount of setup work that must be completed.<br />
<br />
==RODebugPosedPlayer==<br />
<br />
We have made a tool for level designers and artists that are used to gather statistical data about maps called Posed Players. The purpose of the Posed Player is to have a placeable actor to simulate a player in a scene. It has the capability to be used as a camera during profile stage. All of which I will go over now.<br />
<br />
===Actor In Tree===<br />
<br />
[[Image:RODebugPosedPlayerActorTree.jpg|thumb|300px|center|RODebugPosedPlayer in Actor Tree]]<br />
<br />
The RODebugPosedPlayer actor is found at Actor -> RODebugPosedPlayer<br />
<br />
===Properties===<br />
<br />
[[File:RODebugPosedPlayerProperties.jpg|Properties of RODebugPosedPlayer]]<br />
<br />
*Pose: The pose, or stance, the posed player will be in when spawned<br />
*Weapon: The weapon the posed player will be using when posed<br />
*Pawn Type: German or Russian<br />
*Can Possess: Allows the user to possess this posed player using the '''PossessPosedPlayer''' console command<br />
*Description: Small description on what this posed player is - OPTIONAL<br />
<br />
====Available Poses====<br />
<br />
[[File:RODebugPosedPlayerProperties_Pose.jpg|Available Poses for RODebugPosedPlayer]]<br />
<br />
The pose will not make a difference in regards to performance and optimization. It was added so if you wanted to stage a scene for screen shots or something along those lines, this allows you to put the posed player into various positions.<br />
<br />
====Can Possess====<br />
<br />
[[File:RODebugPosedPlayerProperties_CanPossess.jpg|Can Possess Changes Color of RODebugPosedPlayer to BLUE]]<br />
<br />
==Placing RODebugPosedPlayer Actor in Map==<br />
<br />
====Posed Player Placement Guideline====<br />
<br />
*Expected player count is 64 player which would be the worse case scenario in regards to performance<br />
*Use Can Possess on posed players that have vantage view on a particular high traffic area/areas of performance pits<br />
*Any particular player SHOULD NOT see 100% of the map nor players<br />
*Place the actors where players will be<br />
*Do not unnaturally bunch up the posed players<br />
*Distribute the posed players evenly across scene<br />
*More actors near objective spaces, spawn areas, and known fight spaces<br />
*Position RODebugPosedPlayers ~16 Unreal Units above surface to avoid posed player clipping/failure to spawn<br />
<br />
====Create a NEW sublevel====<br />
<br />
[[FILE:LevelBrowser_CreateNEW.jpg|Create a new sub level]]<br />
<br />
=====Naming the Sub Level=====<br />
<br />
[[FILE:LevelBrowser_LevelName.jpg|Give the new sub level a name]]<br />
<br />
Give the sub level a name. It really doesn't matter what you call it as long as you know what it is.<br />
<br />
=====Setting Streaming Method=====<br />
<br />
[[File:LevelBrowser_StreamingMethod.jpg|Set Streaming Method to Always Loaded]]<br />
<br />
We always use Always Loaded so that every time the persistent is loaded, so is this sublevel. Done this way there is no need to have Kismet handle it.<br />
<br />
Options:<br />
*Kismet- Used when you want to use a Kismet node to stream in the sub level. <br />
*Distance- Used when you want to use a certain distance.<br />
*Always Loaded- Used when you want the sub level always loaded when the persistent is loaded.<br />
<br />
[http://udn.epicgames.com/Three/LevelStreamingHome.html Epic Games' UDN Page]<br />
<br />
=====Making New Sub Level Current=====<br />
<br />
[[FILE:LevelBrowser_MakeCurrent.jpg|Set the new sub level as CURRENT]]<br />
<br />
Make the new sub level current and we are ready to start placing actors.<br />
<br />
<br />
==Results==<br />
<br />
[[FILE: PosedPlayer_Placed_L.jpg|This is what we got in Grain Elevator]]<br />
<br />
=Doing the Profile=<br />
<br />
I will document what was done at TWI. Our profiling parameters and data gathering points were specific to our needs for our designs.<br />
<br />
==Profiling Machine Hardware Specifications==<br />
<br />
These are the specifications of the test machine used at TWI<br />
<br />
*Intel Quad 2.40GHz<br />
*4GB RAM<br />
*ATI Radeon HD 5800<br />
*Test Done on High Settings<br />
<br />
==Console Commands==<br />
<br />
*'''SpawnPosedPlayers''' - this command will spawn SkeletalMeshes at the locations of the RODebugPosedPlayer map actors<br />
<br />
*'''StopPosedPlayerUpdates''' - this command will stop the engine from updating the posed players between ticks<br />
<br />
*'''PossessPosedPlayer''' - this command allows the user to possess RODebugPosedPlayer actors for "camera" viewing<br />
<br />
==Polling the Results==<br />
<br />
*Location @<br />
*Frame Time<br />
*Game Time<br />
*FPS<br />
*Draw Time (ms)<br />
*GPU Time (ms)<br />
*DrawPrimitive Calls<br />
*Triangles Drawn<br />
*Static Mesh Tris<br />
*Skel Mesh Draw Calls<br />
*Per Object shadows<br />
*Preshadows<br />
*Adjusted FPS<br />
<br />
==Store Results for Future Profiles==<br />
<br />
=RO2 Static Mesh Combining Tool=<br />
<br />
This tool allows for you to combine similar staticmeshes into one staticmesh allowing you to reduce the overall draw calls per scene frame. We had a number of guidelines that we worked with to get the best results that we could.<br />
<br />
NOTE: When you are combining meshes it's a good idea to keep an eye on Properties -> Static Mesh Component -> Override Light Map Res and it's Boolean bit as well. Having a non default value will result in lightmap errors.<br />
<br />
[[File:StaticMeshProperties_LightmapOverride.jpg|thumb|300px|center|Keep an eye on Properties -> Static Mesh Component -> Override Light Map Res]]<br />
<br />
To override the lightmap of combined meshes, do it at the asset itself in the package. StaticMesh Asset Properties -> Light Map Resolution -> [INTEGER]<br />
<br />
[[File:StaticMeshProperties_AssetLightmapOverride.jpg|thumb|300px|center|Override the lightmap resolution here instead]]<br />
<br />
==Combining Tool Guidelines==<br />
<br />
*Do not combine meshes that do not share that same material(s) in the same slots<br />
*Do not combine too many meshes that you fight with the natural occlusion systems as even the smallest of pixel of a mesh being rendered will render the entirety of the mesh<br />
*Do not combine meshes that will give you exceedingly high poly counts. (>5000)<br />
*Do not combine meshes that you cannot use over and over as this fights with the engine's instancing capability<br />
*Culling > Occlusion<br />
<br />
==Combining Process==<br />
<br />
===Combine Mesh Context Menu===<br />
<br />
[[image:CombineMesh_ContextMenu.jpg|thumb|300px|center|RMB -> Combine Mesh from context menu]]<br />
<br />
===Create New Asset Location===<br />
<br />
[[image:CombineMesh_NewAssetLocation.jpg|thumb|300px|center|Select the Package, Group, and Name of the Asset]]<br />
<br />
===Combine Convex Collision===<br />
<br />
[[image:CombineMesh_ConvexCollisionCombine.jpg|thumb|300px|center|Takes all the convex collision hull primitives and adds them together]]<br />
<br />
===Replace Actors in Scene===<br />
<br />
[[image:CombineMesh_ReplaceActor.jpg|thumb|300px|center|Replace the actor in the scene?]]<br />
<br />
==UnCombining Process==<br />
<br />
[[image:UNCombineMesh_ContextMenu.jpg|thumb|300px|center|RMB -> Uncombine Mesh from context menu]]<br />
<br />
RMB -> UnCombine Mesh<br />
<br />
This will simply uncombine the meshes and replace them with the stored reference of the original assets in the combined mesh. Do not uncombine more than one combined mesh at a time.<br />
<br />
=Procedural bCastDynamicShow System=<br />
<br />
Every static mesh object in the map has the capability to cast a dynamic shadow. A dynamic shadow uses the cascade shadowing system to make nice crisp shadows for the world objects when the player gets near them. The down side is that they can be an expensive render, relatively, when the engine must cast a dynamic shadow into an already shadowed space. To save from having to check this on each and every object in the world a new system was introduced that traces a line from the 8 corners of the bounding box of the static mesh actor back to the DominantDirectionalLight in the map. If ANY of the traces hit the DominantDirectionalLight, the bCaseDynamicShadow Boolean variable is set to TRUE. If none of the traces touches the DominantDirectionalLight then the variable is set to FALSE.<br />
<br />
Some times you can get a false readings in situations where all 8 corners of the bounding box are contained in another mesh (such as walls with a pillar on each side of each section of wall). In this case we've given the capability for the Level Designer to override the procedural system.<br />
<br />
StaticMeshActor Properties -> StaticMeshComponent -> Lighting -> Allow Auto Cast Dynamic Shadow Override</div>Keithhttps://wiki.tripwireinteractive.com/index.php?title=Red_Orchestra_2:_Heroes_Of_Stalingrad/LevelDesign/OptimizationGuide&diff=1377Red Orchestra 2: Heroes Of Stalingrad/LevelDesign/OptimizationGuide2012-07-06T16:02:58Z<p>Keith: /* Console Commands */</p>
<hr />
<div><br />
== Recommended Reading ==<br />
<br />
<br />
If you are new to optimizing in general for Unreal 3 games please have a look through the below web pages so you are up to speed with the grunt work.<br />
<br />
===Epic's Unreal Development Network - UDN===<br />
====[http://udn.epicgames.com/Three/PerformanceHome.html Epic's Performance UDN Page]====<br />
<br />
====[http://udn.epicgames.com/Three/ProfilingBasics.html Epic's Profiling UDN Page]====<br />
<br />
====[http://udn.epicgames.com/Three/MemoryProfilingHome.html Epic's Memory Profiling UDN Page]====<br />
<br />
====[http://udn.epicgames.com/Three/RenderThreadProfilingHome.html Epic's Rendering Thread Profiling UDN Page]====<br />
<br />
=Introduction=<br />
<br />
The purpose of this document is to give information on the guidelines used to optimize the maps inside RO2. These guidelines worked for us. If you are a community level designer and/or artist you may find this document useful. This document will cover the various approaches and the reasoning behind decisions so that the reader may be able to avoid pitfalls when making levels for Red Orchestra 2.<br />
<br />
The following is a list of items that LDs and Environment Artists should follow for a map to perform well. Most of these were lessons learnt while optimizing RO2 and should also serve as a guideline for modders to make sure that they don't run into the same pitfalls.<br />
<br />
=Level Performance Guidelines=<br />
==Terrain==<br />
<br />
=== bCastDynamicShadow ===<br />
This flag should be OFF. Setting this flag to ON will cast dynamic preshadows by the terrain for both per-object shadows and whole scene dynamic shadows, which can be very expensive depending on the number of dynamic primitives in the scene. Preshadows (which are dynamic shadows from the static environment onto dynamic objects) only make sense if the terrain has hills and valleys throughout the scene. If the scene just has a few mounds here and there it might be worth modeling the mounds with static meshes and have the terrain blend in at the bottom. The side effect of disabling bCastDynamicShadow is that terrain deco layers (e.g. grass) will not cast whole scene dynamic shadows. But considering that shadows from deco layers usually are low-res and don't look great, it is a good price to pay for a substantial performance boost.<br />
<br />
[[Image:GrassShadows.png|center|frame|Low Res deco layer shadows]]<br />
<br />
=== Terrain Layers ===<br />
The RO2 engine allows for a maximum of 12 textures to be blended for terrain. These 12 textures could be part of 2 terrain layers (6 textures each), 3 terrain layers (4 textures each), or any other combination thereof. This is a hard limit for the engine, and exceeding this limit will result in rainbow colored terrain patches. However, fetching and accessing so many textures is not cheap and since the terrain usually takes up a large portion of the screen, it is recommended that you keep the number of blend textures to a minimum.<br />
<br />
One example for this is that say you have a terrain which comprises or dirt, rubble and snow and one part of the terrain is solid concrete. Instead of making 4 terrain layers of dirt, rubble, snow and concrete and blending between them it is more optimized if the terrain uses 3 layers of dirt, rubble and snow, and the concrete portion is modeled separately as BSP, static mesh or even another terrain actor. Doing this will reduce the overall cost of rendering the entire terrain since the concrete layer texture fetches are eliminated for the rest of the terrain that doesn't need it.<br />
<br />
==Static Meshes==<br />
<br />
=== bCastDynamicShadow ===<br />
When placing a static mesh in the level, you should decide whether you want it to cast dynamic preshadows or not. Preshadows are dynamic shadows from the static environment onto dynamic objects, and can be very expensive depending on the number of dynamic primitives in the scene. Turning off this flag for a lot of static meshes in the environment in the scene such as debris, rubble, etc. will improve the dynamic shadow performance.<br />
<br />
[[Image:Preshadows.png|center|frame|Dynamic preshadows cast by tree foliage onto character]]<br />
<br />
Once the lighting in a map is finalized, you can also go through and set bCastDynamicShadow to false for all static meshes that are already in shadow (such as the truck in the following image, which is is shadow of the building) since any dynamic shadow cast by it will be drowned by the static shadow cast by the environment.<br />
<br />
[[Image:DynamicShadowTruck.jpg|thumb|300px|center|The truck does not need to cast dynamic shadows since it is already in shadow]]<br />
<br />
=== Distance Culling ===<br />
Using distance culling effectively will allow you to have a lot of detail in your environment whilst still allowing the map to perform well. There are 2 ways to do this :<br />
<br />
* You can either put a CullDistanceVolume around the map and the let the map build process choose the appropriate cull distances for the placed static meshes in the level. This method is not ideal though, and might cause certain cover objects, etc. to disappear at a distance (which is not desirable). <br />
<br />
* Or, you can manually set the MaxDrawDistance for each object.<br />
<br />
== Materials ==<br />
=== Using Material LODs ===<br />
In order to make the best looking environment materials as well as keep the overall performance cost low, consider using material LODs. The concept is very simple - assign the best looking/highest instruction count material to the base LOD for a static mesh, and then create another LOD for the static mesh (this can have the exact same triangle count as the base LOD) and assign it a simple material that does not have expensive operations such as depth biased alpha, specularity, cube maps or even normal maps. Such subtle lighting effects cannot be perceived from a distance anyway, and will make improve the fill rate for the rendered scene.<br />
<br />
[[Image:NormalMappedBaseMaterial.png|thumb|300px|center|Base material using normal maps]][[Image:SimpleMaterial.png|thumb|300px|center|Simple material that does not use normal maps]]<br />
<br />
== Dynamic Actors ==<br />
=== bDisablePerObjectShadows ===<br />
If you place an actor onto a level that casts dynamic shadows, the shadowing cost for it is one per object shadow and in certain cases a preshadow as well. If bDisablePerObjectShadows is set it will only cast dynamic shadows for the primitive if it is within the whole scene dominant shadow radius. This reduces the cost associated with shadowing for the primitive. If whole scene dominant shadows are not enabled, the primitive will not cast any dynamic shadows.<br />
<br />
[[Image:DisablePerObjectShadowsDemo.jpg|thumb|600px|center|The flag pole is outside the whole scene dominant shadow radius in the image on the left and hence is not shadowed. When the player moves such that the flag pole is now within the whole scene dominant shadow radius, it will start casting whole scene dominant shadows (right image)]]<br />
<br />
=== bAllowMergedDynamicShadows ===<br />
If this flag is set, any primitive that allows per object dynamic shadows will be considered for being merged with other primitives that allow merged per object dynamic shadows and are close enough. As a consequence, the number of dynamic shadows in the scene are reduced.<br />
<br />
The radius used to merge primitives is dynamically adjusted based on the distance of the primitives from the viewer. It starts at ''MinShadowGroupRadius'' (when the primitive is closest to the viewer) and increases up to ''MaxShadowGroupRadius'' (when the primitive is ''ShadowGroupRampCutoff'' away from the viewer). The rate of increase is determined by ''ShadowGroupRadiusRampUpFactor''. For anything beyond ''ShadowGroupRampCutoff'', the ''MaxShadowGroupRadius'' will be used. All these settings are available in the engine INI.<br />
<br />
[[Image:GroupedDynamicPerObjectShadowsDemo.jpg|thumb|600px|center|The image on the left has bAllowMergedDynamicShadows set to false on the two placed pawns, and they cast a per object shadow each. The image on the right has bAllowMergedDynamicShadows set to true on the pawns, and as such both the pawns are included in the same projected shadow.]]<br />
<br />
== Draw Calls ==<br />
== About Draw Calls==<br />
As the UE3 rendering engine is a Direct X 9.0 renderer, it is limited to one CPU core to tell the GPU about what to draw. It does this via a Draw Call. Each object you place in the world is at least one draw call (if not more due to shadows). The CPU can become the bottleneck of a level if it is trying to tell the GPU to draw a detailed scene and chokes on the amount of draw calls. This is why it is best to limit the amount in any given scene. With the Red Orchestra SDK it is very easy to make many types of levels, from wide open plains (or with rolling hills) to detailed interior settings and building to building fighting. However, depending on what the scale of your map is, you will be limited in the amount of "detail" you can place in the level. <br />
<br />
<br />
== Limiting Draw Calls Per Scene==<br />
Suggested Maximum Draw Call Limit: 2000<br />
<br />
Using the console command ''Stat d3d9rhi"'' a Level Designer/Artist (or anyone) can go through a level and find out the amount of Draw Calls and optimize based on areas where it has increased beyond the suggested maximum.<br />
<br />
The details settings for both users and in the SDK allows Level Designers to put some objects on different levels of the setting so those with faster computers (in this case CPU core speed) can see more details without harming performance for those with slower machines. It is best to do this with "fluff" detail that is not gameplay important but just makes the level look better overall.<br />
<br />
<br />
=Profiling Preliminary Work=<br />
<br />
There is a small amount of setup work that must be completed.<br />
<br />
==RODebugPosedPlayer==<br />
<br />
We have made a tool for level designers and artists that are used to gather statistical data about maps called Posed Players. The purpose of the Posed Player is to have a placeable actor to simulate a player in a scene. It has the capability to be used as a camera during profile stage. All of which I will go over now.<br />
<br />
===Actor In Tree===<br />
<br />
[[Image:RODebugPosedPlayerActorTree.jpg|thumb|300px|center|RODebugPosedPlayer in Actor Tree]]<br />
<br />
The RODebugPosedPlayer actor is found at Actor -> RODebugPosedPlayer<br />
<br />
===Properties===<br />
<br />
[[File:RODebugPosedPlayerProperties.jpg|Properties of RODebugPosedPlayer]]<br />
<br />
*Pose: The pose, or stance, the posed player will be in when spawned<br />
*Weapon: The weapon the posed player will be using when posed<br />
*Pawn Type: German or Russian<br />
*Can Possess: Allows the user to possess this posed player using the '''PossessPosedPlayer''' console command<br />
*Description: Small description on what this posed player is - OPTIONAL<br />
<br />
====Available Poses====<br />
<br />
[[File:RODebugPosedPlayerProperties_Pose.jpg|Available Poses for RODebugPosedPlayer]]<br />
<br />
The pose will not make a difference in regards to performance and optimization. It was added so if you wanted to stage a scene for screen shots or something along those lines, this allows you to put the posed player into various positions.<br />
<br />
====Can Possess====<br />
<br />
[[File:RODebugPosedPlayerProperties_CanPossess.jpg|Can Possess Changes Color of RODebugPosedPlayer to BLUE]]<br />
<br />
==Placing RODebugPosedPlayer Actor in Map==<br />
<br />
====Posed Player Placement Guideline====<br />
<br />
*Expected player count is 64 player which would be the worse case scenario in regards to performance<br />
*Use Can Possess on posed players that have vantage view on a particular high traffic area/areas of performance pits<br />
*Any particular player SHOULD NOT see 100% of the map nor players<br />
*Place the actors where players will be<br />
*Do not unnaturally bunch up the posed players<br />
*Distribute the posed players evenly across scene<br />
*More actors near objective spaces, spawn areas, and known fight spaces<br />
*Position RODebugPosedPlayers ~16 Unreal Units above surface to avoid posed player clipping/failure to spawn<br />
<br />
====Create a NEW sublevel====<br />
<br />
[[FILE:LevelBrowser_CreateNEW.jpg|Create a new sub level]]<br />
<br />
=====Naming the Sub Level=====<br />
<br />
[[FILE:LevelBrowser_LevelName.jpg|Give the new sub level a name]]<br />
<br />
Give the sub level a name. It really doesn't matter what you call it as long as you know what it is.<br />
<br />
=====Setting Streaming Method=====<br />
<br />
[[File:LevelBrowser_StreamingMethod.jpg|Set Streaming Method to Always Loaded]]<br />
<br />
We always use Always Loaded so that every time the persistent is loaded, so is this sublevel. Done this way there is no need to have Kismet handle it.<br />
<br />
Options:<br />
*Kismet- Used when you want to use a Kismet node to stream in the sub level. <br />
*Distance- Used when you want to use a certain distance.<br />
*Always Loaded- Used when you want the sub level always loaded when the persistent is loaded.<br />
<br />
[http://udn.epicgames.com/Three/LevelStreamingHome.html Epic Games' UDN Page]<br />
<br />
=====Making New Sub Level Current=====<br />
<br />
[[FILE:LevelBrowser_MakeCurrent.jpg|Set the new sub level as CURRENT]]<br />
<br />
Make the new sub level current and we are ready to start placing actors.<br />
<br />
<br />
==Results==<br />
<br />
[[FILE: PosedPlayer_Placed_L.jpg|This is what we got in Grain Elevator]]<br />
<br />
=Doing the Profile=<br />
<br />
I will document what was done at TWI. Our profiling parameters and data gathering points were specific to our needs for our designs.<br />
<br />
==Profiling Machine Hardware Specifications==<br />
<br />
These are the specifications of the test machine used at TWI<br />
<br />
*Intel Quad 2.40GHz<br />
*4GB RAM<br />
*ATI Radeon HD 5800<br />
*Test Done on High Settings<br />
<br />
==Console Commands==<br />
<br />
*SpawnPosedPlayers - this command will spawn SkeletalMeshes at the locations of the RODebugPosedPlayer map actors<br />
<br />
*StopPosedPlayerUpdates - this command will stop the engine from updating the posed players between ticks<br />
<br />
*PossessPosedPlayer - this command allows the user to possess RODebugPosedPlayer actors for "camera" viewing<br />
<br />
==Polling the Results==<br />
<br />
*Location @<br />
*Frame Time<br />
*Game Time<br />
*FPS<br />
*Draw Time (ms)<br />
*GPU Time (ms)<br />
*DrawPrimitive Calls<br />
*Triangles Drawn<br />
*Static Mesh Tris<br />
*Skel Mesh Draw Calls<br />
*Per Object shadows<br />
*Preshadows<br />
*Adjusted FPS<br />
<br />
==Store Results for Future Profiles==<br />
<br />
=RO2 Static Mesh Combining Tool=<br />
<br />
This tool allows for you to combine similar staticmeshes into one staticmesh allowing you to reduce the overall draw calls per scene frame. We had a number of guidelines that we worked with to get the best results that we could.<br />
<br />
NOTE: When you are combining meshes it's a good idea to keep an eye on Properties -> Static Mesh Component -> Override Light Map Res and it's Boolean bit as well. Having a non default value will result in lightmap errors.<br />
<br />
[[File:StaticMeshProperties_LightmapOverride.jpg|thumb|300px|center|Keep an eye on Properties -> Static Mesh Component -> Override Light Map Res]]<br />
<br />
To override the lightmap of combined meshes, do it at the asset itself in the package. StaticMesh Asset Properties -> Light Map Resolution -> [INTEGER]<br />
<br />
[[File:StaticMeshProperties_AssetLightmapOverride.jpg|thumb|300px|center|Override the lightmap resolution here instead]]<br />
<br />
==Combining Tool Guidelines==<br />
<br />
*Do not combine meshes that do not share that same material(s) in the same slots<br />
*Do not combine too many meshes that you fight with the natural occlusion systems as even the smallest of pixel of a mesh being rendered will render the entirety of the mesh<br />
*Do not combine meshes that will give you exceedingly high poly counts. (>5000)<br />
*Do not combine meshes that you cannot use over and over as this fights with the engine's instancing capability<br />
*Culling > Occlusion<br />
<br />
==Combining Process==<br />
<br />
===Combine Mesh Context Menu===<br />
<br />
[[image:CombineMesh_ContextMenu.jpg|thumb|300px|center|RMB -> Combine Mesh from context menu]]<br />
<br />
===Create New Asset Location===<br />
<br />
[[image:CombineMesh_NewAssetLocation.jpg|thumb|300px|center|Select the Package, Group, and Name of the Asset]]<br />
<br />
===Combine Convex Collision===<br />
<br />
[[image:CombineMesh_ConvexCollisionCombine.jpg|thumb|300px|center|Takes all the convex collision hull primitives and adds them together]]<br />
<br />
===Replace Actors in Scene===<br />
<br />
[[image:CombineMesh_ReplaceActor.jpg|thumb|300px|center|Replace the actor in the scene?]]<br />
<br />
==UnCombining Process==<br />
<br />
[[image:UNCombineMesh_ContextMenu.jpg|thumb|300px|center|RMB -> Uncombine Mesh from context menu]]<br />
<br />
RMB -> UnCombine Mesh<br />
<br />
This will simply uncombine the meshes and replace them with the stored reference of the original assets in the combined mesh. Do not uncombine more than one combined mesh at a time.<br />
<br />
=Procedural bCastDynamicShow System=<br />
<br />
Every static mesh object in the map has the capability to cast a dynamic shadow. A dynamic shadow uses the cascade shadowing system to make nice crisp shadows for the world objects when the player gets near them. The down side is that they can be an expensive render, relatively, when the engine must cast a dynamic shadow into an already shadowed space. To save from having to check this on each and every object in the world a new system was introduced that traces a line from the 8 corners of the bounding box of the static mesh actor back to the DominantDirectionalLight in the map. If ANY of the traces hit the DominantDirectionalLight, the bCaseDynamicShadow Boolean variable is set to TRUE. If none of the traces touches the DominantDirectionalLight then the variable is set to FALSE.<br />
<br />
Some times you can get a false readings in situations where all 8 corners of the bounding box are contained in another mesh (such as walls with a pillar on each side of each section of wall). In this case we've given the capability for the Level Designer to override the procedural system.<br />
<br />
StaticMeshActor Properties -> StaticMeshComponent -> Lighting -> Allow Auto Cast Dynamic Shadow Override</div>Keithhttps://wiki.tripwireinteractive.com/index.php?title=Red_Orchestra_2:_Heroes_Of_Stalingrad/LevelDesign&diff=1376Red Orchestra 2: Heroes Of Stalingrad/LevelDesign2012-07-06T15:55:19Z<p>Keith: </p>
<hr />
<div>[[File:RO2banner.gif|x304px|link=Red_Orchestra_2:_Heroes_Of_Stalingrad]]<br />
<br />
=Suggested Reading=<br />
==== [http://udn.epicgames.com/Three/LevelEditingHome.html Epic's UDN Page for Level Editing] ====<br />
==== [http://udn.epicgames.com/Three/EditorAndToolsHome.html Epic's UDN Page for the Editor] ====<br />
==== [http://udn.epicgames.com/Three/CreatingLevels.html Epic's UDN Page for Creating Levels] ====<br />
==== [http://udn.epicgames.com/Three/DesignWorkflow.html Epic's UDN Page for Proposed Design Work Flow] ====<br />
<br />
=Basic Information=<br />
<br />
==== [[Red Orchestra 2 Units and Scale]] ====<br />
<br />
=Map Actor/Game Play Setup=<br />
<br />
====[[Red_Orchestra_2:_Heroes_Of_Stalingrad/LevelDesign/WorldInfo| Red Orchestra 2 World Info Setup]]====<br />
<br />
==== [[Red Orchestra 2 Spawning Setup]] ====<br />
<br />
==== [[Red Orchestra 2 Role Setup]] ====<br />
<br />
==== [[Red Orchestra 2 Objective Setup]] ====<br />
<br />
==== [[Red Orchestra 2 Setting Up Cover]] ====<br />
<br />
==== [[Red_Orchestra_2:_Heroes_Of_Stalingrad/LevelDesign/OverheadMapGeneration|Red Orchestra 2 Overhead Map]]====<br />
<br />
==== [[Red_Orchestra_2:_Heroes_Of_Stalingrad/LevelDesign/OptimizationGuide| Red Orchestra 2 Optimization Guide]] ====</div>Keithhttps://wiki.tripwireinteractive.com/index.php?title=Red_Orchestra_2:_Heroes_Of_Stalingrad/LevelDesign&diff=1375Red Orchestra 2: Heroes Of Stalingrad/LevelDesign2012-07-06T15:51:08Z<p>Keith: </p>
<hr />
<div>[[File:RO2banner.gif|x304px|link=Red_Orchestra_2:_Heroes_Of_Stalingrad]]<br />
<br />
=Suggested Reading=<br />
==http://udn.epicgames.com/Three/LevelEditingHome.html Epic's UDN Page for Level Editing==<br />
==http://udn.epicgames.com/Three/EditorAndToolsHome.html Epic's UDN Page for the Editor==<br />
==http://udn.epicgames.com/Three/CreatingLevels.html Epic's UDN Page for Creating Levels==<br />
==http://udn.epicgames.com/Three/DesignWorkflow.html Epic's UDN Page for Proposed Design Work Flow==<br />
<br />
=Basic Information=<br />
<br />
[[Red Orchestra 2 Units and Scale]]<br />
<br />
=Map Actor/Game Play Setup=<br />
<br />
[[Red_Orchestra_2:_Heroes_Of_Stalingrad/LevelDesign/WorldInfo| Red Orchestra 2 World Info Setup]]<br />
<br />
[[Red Orchestra 2 Spawning Setup]]<br />
<br />
[[Red Orchestra 2 Role Setup]]<br />
<br />
[[Red Orchestra 2 Objective Setup]]<br />
<br />
[[Red Orchestra 2 Setting Up Cover]]<br />
<br />
[[Red_Orchestra_2:_Heroes_Of_Stalingrad/LevelDesign/OverheadMapGeneration|Red Orchestra 2 Overhead Map]]<br />
<br />
[[Red_Orchestra_2:_Heroes_Of_Stalingrad/LevelDesign/OptimizationGuide| Red Orchestra 2 Optimization Guide]]</div>Keithhttps://wiki.tripwireinteractive.com/index.php?title=Red_Orchestra_2:_Heroes_Of_Stalingrad/LevelDesign&diff=1374Red Orchestra 2: Heroes Of Stalingrad/LevelDesign2012-07-06T15:46:53Z<p>Keith: /* Basic Information */</p>
<hr />
<div>[[File:RO2banner.gif|x304px|link=Red_Orchestra_2:_Heroes_Of_Stalingrad]]<br />
<br />
=Basic Information=<br />
<br />
[[Red Orchestra 2 Units and Scale]]<br />
<br />
=Map Actor/Game Play Setup=<br />
<br />
[[Red_Orchestra_2:_Heroes_Of_Stalingrad/LevelDesign/WorldInfo| Red Orchestra 2 World Info Setup]]<br />
<br />
[[Red Orchestra 2 Spawning Setup]]<br />
<br />
[[Red Orchestra 2 Role Setup]]<br />
<br />
[[Red Orchestra 2 Objective Setup]]<br />
<br />
[[Red Orchestra 2 Setting Up Cover]]<br />
<br />
[[Red_Orchestra_2:_Heroes_Of_Stalingrad/LevelDesign/OverheadMapGeneration|Red Orchestra 2 Overhead Map]]<br />
<br />
[[Red_Orchestra_2:_Heroes_Of_Stalingrad/LevelDesign/OptimizationGuide| Red Orchestra 2 Optimization Guide]]</div>Keithhttps://wiki.tripwireinteractive.com/index.php?title=Red_Orchestra_2:_Heroes_Of_Stalingrad/LevelDesign&diff=1373Red Orchestra 2: Heroes Of Stalingrad/LevelDesign2012-07-06T15:45:06Z<p>Keith: </p>
<hr />
<div>[[File:RO2banner.gif|x304px|link=Red_Orchestra_2:_Heroes_Of_Stalingrad]]<br />
<br />
=Basic Information=<br />
<br />
[[Red Orchestra 2 Units and Scale]]<br />
<br />
[[Red Orchestra 2 Tutorials Index]]<br />
<br />
[[Red Orchestra 2 Level Performance Guidelines]]<br />
<br />
=Map Actor/Game Play Setup=<br />
<br />
[[Red_Orchestra_2:_Heroes_Of_Stalingrad/LevelDesign/WorldInfo| Red Orchestra 2 World Info Setup]]<br />
<br />
[[Red Orchestra 2 Spawning Setup]]<br />
<br />
[[Red Orchestra 2 Role Setup]]<br />
<br />
[[Red Orchestra 2 Objective Setup]]<br />
<br />
[[Red Orchestra 2 Setting Up Cover]]<br />
<br />
[[Red_Orchestra_2:_Heroes_Of_Stalingrad/LevelDesign/OverheadMapGeneration|Red Orchestra 2 Overhead Map]]<br />
<br />
[[Red_Orchestra_2:_Heroes_Of_Stalingrad/LevelDesign/OptimizationGuide| Red Orchestra 2 Optimization Guide]]</div>Keithhttps://wiki.tripwireinteractive.com/index.php?title=Red_Orchestra_2:_Heroes_Of_Stalingrad/LevelDesign&diff=1371Red Orchestra 2: Heroes Of Stalingrad/LevelDesign2012-07-06T15:33:01Z<p>Keith: </p>
<hr />
<div>[[File:RO2banner.gif|x304px|link=Red_Orchestra_2:_Heroes_Of_Stalingrad]]<br />
<br />
This is a stub page for all things relating to level design. Thus far we have:<br />
<br />
[[Red_Orchestra_2:_Heroes_Of_Stalingrad/LevelDesign/WorldInfo| Red Orchestra 2 World Info Setup]]<br />
<br />
[[Red Orchestra 2 Spawning Setup]]<br />
<br />
[[Red Orchestra 2 Role Setup]]<br />
<br />
[[Red Orchestra 2 Objective Setup]]<br />
<br />
[[Red Orchestra 2 Setting Up Cover]]<br />
<br />
[[Red_Orchestra_2:_Heroes_Of_Stalingrad/LevelDesign/OverheadMapGeneration|Red Orchestra 2 Overhead Map]]<br />
<br />
[[Red_Orchestra_2:_Heroes_Of_Stalingrad/LevelDesign/OptimizationGuide| Red Orchestra 2 Optimization Guide]]<br />
<br />
[[Red Orchestra 2 Level Performance Guidelines]]<br />
<br />
[[Red Orchestra 2 Units and Scale]]<br />
<br />
[[Red Orchestra 2 Tutorials Index]]</div>Keithhttps://wiki.tripwireinteractive.com/index.php?title=Red_Orchestra_2:_Heroes_Of_Stalingrad/LevelDesign&diff=1370Red Orchestra 2: Heroes Of Stalingrad/LevelDesign2012-07-06T15:32:42Z<p>Keith: </p>
<hr />
<div>[[File:RO2banner.gif|x304px|link=Red_Orchestra_2:_Heroes_Of_Stalingrad]]<br />
<br />
This is a stub page for all things relating to level design. Thus far we have:<br />
<br />
[[Red_Orchestra_2:_Heroes_Of_Stalingrad/LevelDesign/WorldInfo| Red Orchestra 2 World Info Setup]]<br />
<br />
[[Red Orchestra 2 Spawning Setup]]<br />
<br />
[[Red Orchestra 2 Role Setup]]<br />
<br />
[[Red Orchestra 2 Objective Setup]]<br />
<br />
[[Red Orchestra 2 Setting Up Cover]]<br />
<br />
[[Red_Orchestra_2:_Heroes_Of_Stalingrad/LevelDesign/OverheadMapGeneration|Red Orchestra 2 Overhead Map]]<br />
<br />
[[http://wiki.tripwireinteractive.com/index.php/Red_Orchestra_2:_Heroes_Of_Stalingrad/LevelDesign/OptimizationGuide| Red Orchestra 2 Optimization Guide]]<br />
<br />
[[Red Orchestra 2 Level Performance Guidelines]]<br />
<br />
[[Red Orchestra 2 Units and Scale]]<br />
<br />
[[Red Orchestra 2 Tutorials Index]]</div>Keithhttps://wiki.tripwireinteractive.com/index.php?title=Red_Orchestra_2:_Heroes_Of_Stalingrad/LevelDesign&diff=1369Red Orchestra 2: Heroes Of Stalingrad/LevelDesign2012-07-06T15:32:28Z<p>Keith: </p>
<hr />
<div>[[File:RO2banner.gif|x304px|link=Red_Orchestra_2:_Heroes_Of_Stalingrad]]<br />
<br />
This is a stub page for all things relating to level design. Thus far we have:<br />
<br />
[[Red_Orchestra_2:_Heroes_Of_Stalingrad/LevelDesign/WorldInfo| Red Orchestra 2 World Info Setup]]<br />
<br />
[[Red Orchestra 2 Spawning Setup]]<br />
<br />
[[Red Orchestra 2 Role Setup]]<br />
<br />
[[Red Orchestra 2 Objective Setup]]<br />
<br />
[[Red Orchestra 2 Setting Up Cover]]<br />
<br />
[[Red_Orchestra_2:_Heroes_Of_Stalingrad/LevelDesign/OverheadMapGeneration|Red Orchestra 2 Overhead Map]]<br />
<br />
[[http://wiki.tripwireinteractive.com/index.php/Red_Orchestra_2:_Heroes_Of_Stalingrad/LevelDesign/OptimizationGuide|Red Orchestra 2 Optimization Guide]]<br />
<br />
[[Red Orchestra 2 Level Performance Guidelines]]<br />
<br />
[[Red Orchestra 2 Units and Scale]]<br />
<br />
[[Red Orchestra 2 Tutorials Index]]</div>Keithhttps://wiki.tripwireinteractive.com/index.php?title=Red_Orchestra_2:_Heroes_Of_Stalingrad/LevelDesign/OptimizationGuide&diff=1367Red Orchestra 2: Heroes Of Stalingrad/LevelDesign/OptimizationGuide2012-07-06T14:58:28Z<p>Keith: </p>
<hr />
<div><br />
== Recommended Reading ==<br />
<br />
<br />
If you are new to optimizing in general for Unreal 3 games please have a look through the below web pages so you are up to speed with the grunt work.<br />
<br />
===Epic's Unreal Development Network - UDN===<br />
====[http://udn.epicgames.com/Three/PerformanceHome.html Epic's Performance UDN Page]====<br />
<br />
====[http://udn.epicgames.com/Three/ProfilingBasics.html Epic's Profiling UDN Page]====<br />
<br />
====[http://udn.epicgames.com/Three/MemoryProfilingHome.html Epic's Memory Profiling UDN Page]====<br />
<br />
====[http://udn.epicgames.com/Three/RenderThreadProfilingHome.html Epic's Rendering Thread Profiling UDN Page]====<br />
<br />
=Introduction=<br />
<br />
The purpose of this document is to give information on the guidelines used to optimize the maps inside RO2. These guidelines worked for us. If you are a community level designer and/or artist you may find this document useful. This document will cover the various approaches and the reasoning behind decisions so that the reader may be able to avoid pitfalls when making levels for Red Orchestra 2.<br />
<br />
The following is a list of items that LDs and Environment Artists should follow for a map to perform well. Most of these were lessons learnt while optimizing RO2 and should also serve as a guideline for modders to make sure that they don't run into the same pitfalls.<br />
<br />
=Level Performance Guidelines=<br />
==Terrain==<br />
<br />
=== bCastDynamicShadow ===<br />
This flag should be OFF. Setting this flag to ON will cast dynamic preshadows by the terrain for both per-object shadows and whole scene dynamic shadows, which can be very expensive depending on the number of dynamic primitives in the scene. Preshadows (which are dynamic shadows from the static environment onto dynamic objects) only make sense if the terrain has hills and valleys throughout the scene. If the scene just has a few mounds here and there it might be worth modeling the mounds with static meshes and have the terrain blend in at the bottom. The side effect of disabling bCastDynamicShadow is that terrain deco layers (e.g. grass) will not cast whole scene dynamic shadows. But considering that shadows from deco layers usually are low-res and don't look great, it is a good price to pay for a substantial performance boost.<br />
<br />
[[Image:GrassShadows.png|center|frame|Low Res deco layer shadows]]<br />
<br />
=== Terrain Layers ===<br />
The RO2 engine allows for a maximum of 12 textures to be blended for terrain. These 12 textures could be part of 2 terrain layers (6 textures each), 3 terrain layers (4 textures each), or any other combination thereof. This is a hard limit for the engine, and exceeding this limit will result in rainbow colored terrain patches. However, fetching and accessing so many textures is not cheap and since the terrain usually takes up a large portion of the screen, it is recommended that you keep the number of blend textures to a minimum.<br />
<br />
One example for this is that say you have a terrain which comprises or dirt, rubble and snow and one part of the terrain is solid concrete. Instead of making 4 terrain layers of dirt, rubble, snow and concrete and blending between them it is more optimized if the terrain uses 3 layers of dirt, rubble and snow, and the concrete portion is modeled separately as BSP, static mesh or even another terrain actor. Doing this will reduce the overall cost of rendering the entire terrain since the concrete layer texture fetches are eliminated for the rest of the terrain that doesn't need it.<br />
<br />
==Static Meshes==<br />
<br />
=== bCastDynamicShadow ===<br />
When placing a static mesh in the level, you should decide whether you want it to cast dynamic preshadows or not. Preshadows are dynamic shadows from the static environment onto dynamic objects, and can be very expensive depending on the number of dynamic primitives in the scene. Turning off this flag for a lot of static meshes in the environment in the scene such as debris, rubble, etc. will improve the dynamic shadow performance.<br />
<br />
[[Image:Preshadows.png|center|frame|Dynamic preshadows cast by tree foliage onto character]]<br />
<br />
Once the lighting in a map is finalized, you can also go through and set bCastDynamicShadow to false for all static meshes that are already in shadow (such as the truck in the following image, which is is shadow of the building) since any dynamic shadow cast by it will be drowned by the static shadow cast by the environment.<br />
<br />
[[Image:DynamicShadowTruck.jpg|thumb|300px|center|The truck does not need to cast dynamic shadows since it is already in shadow]]<br />
<br />
=== Distance Culling ===<br />
Using distance culling effectively will allow you to have a lot of detail in your environment whilst still allowing the map to perform well. There are 2 ways to do this :<br />
<br />
* You can either put a CullDistanceVolume around the map and the let the map build process choose the appropriate cull distances for the placed static meshes in the level. This method is not ideal though, and might cause certain cover objects, etc. to disappear at a distance (which is not desirable). <br />
<br />
* Or, you can manually set the MaxDrawDistance for each object.<br />
<br />
== Materials ==<br />
=== Using Material LODs ===<br />
In order to make the best looking environment materials as well as keep the overall performance cost low, consider using material LODs. The concept is very simple - assign the best looking/highest instruction count material to the base LOD for a static mesh, and then create another LOD for the static mesh (this can have the exact same triangle count as the base LOD) and assign it a simple material that does not have expensive operations such as depth biased alpha, specularity, cube maps or even normal maps. Such subtle lighting effects cannot be perceived from a distance anyway, and will make improve the fill rate for the rendered scene.<br />
<br />
[[Image:NormalMappedBaseMaterial.png|thumb|300px|center|Base material using normal maps]][[Image:SimpleMaterial.png|thumb|300px|center|Simple material that does not use normal maps]]<br />
<br />
== Dynamic Actors ==<br />
=== bDisablePerObjectShadows ===<br />
If you place an actor onto a level that casts dynamic shadows, the shadowing cost for it is one per object shadow and in certain cases a preshadow as well. If bDisablePerObjectShadows is set it will only cast dynamic shadows for the primitive if it is within the whole scene dominant shadow radius. This reduces the cost associated with shadowing for the primitive. If whole scene dominant shadows are not enabled, the primitive will not cast any dynamic shadows.<br />
<br />
[[Image:DisablePerObjectShadowsDemo.jpg|thumb|600px|center|The flag pole is outside the whole scene dominant shadow radius in the image on the left and hence is not shadowed. When the player moves such that the flag pole is now within the whole scene dominant shadow radius, it will start casting whole scene dominant shadows (right image)]]<br />
<br />
=== bAllowMergedDynamicShadows ===<br />
If this flag is set, any primitive that allows per object dynamic shadows will be considered for being merged with other primitives that allow merged per object dynamic shadows and are close enough. As a consequence, the number of dynamic shadows in the scene are reduced.<br />
<br />
The radius used to merge primitives is dynamically adjusted based on the distance of the primitives from the viewer. It starts at ''MinShadowGroupRadius'' (when the primitive is closest to the viewer) and increases up to ''MaxShadowGroupRadius'' (when the primitive is ''ShadowGroupRampCutoff'' away from the viewer). The rate of increase is determined by ''ShadowGroupRadiusRampUpFactor''. For anything beyond ''ShadowGroupRampCutoff'', the ''MaxShadowGroupRadius'' will be used. All these settings are available in the engine INI.<br />
<br />
[[Image:GroupedDynamicPerObjectShadowsDemo.jpg|thumb|600px|center|The image on the left has bAllowMergedDynamicShadows set to false on the two placed pawns, and they cast a per object shadow each. The image on the right has bAllowMergedDynamicShadows set to true on the pawns, and as such both the pawns are included in the same projected shadow.]]<br />
<br />
== Draw Calls ==<br />
== About Draw Calls==<br />
As the UE3 rendering engine is a Direct X 9.0 renderer, it is limited to one CPU core to tell the GPU about what to draw. It does this via a Draw Call. Each object you place in the world is at least one draw call (if not more due to shadows). The CPU can become the bottleneck of a level if it is trying to tell the GPU to draw a detailed scene and chokes on the amount of draw calls. This is why it is best to limit the amount in any given scene. With the Red Orchestra SDK it is very easy to make many types of levels, from wide open plains (or with rolling hills) to detailed interior settings and building to building fighting. However, depending on what the scale of your map is, you will be limited in the amount of "detail" you can place in the level. <br />
<br />
<br />
== Limiting Draw Calls Per Scene==<br />
Suggested Maximum Draw Call Limit: 2000<br />
<br />
Using the console command ''Stat d3d9rhi"'' a Level Designer/Artist (or anyone) can go through a level and find out the amount of Draw Calls and optimize based on areas where it has increased beyond the suggested maximum.<br />
<br />
The details settings for both users and in the SDK allows Level Designers to put some objects on different levels of the setting so those with faster computers (in this case CPU core speed) can see more details without harming performance for those with slower machines. It is best to do this with "fluff" detail that is not gameplay important but just makes the level look better overall.<br />
<br />
<br />
=Profiling Preliminary Work=<br />
<br />
There is a small amount of setup work that must be completed.<br />
<br />
==RODebugPosedPlayer==<br />
<br />
We have made a tool for level designers and artists that are used to gather statistical data about maps called Posed Players. The purpose of the Posed Player is to have a placeable actor to simulate a player in a scene. It has the capability to be used as a camera during profile stage. All of which I will go over now.<br />
<br />
===Actor In Tree===<br />
<br />
[[Image:RODebugPosedPlayerActorTree.jpg|thumb|300px|center|RODebugPosedPlayer in Actor Tree]]<br />
<br />
The RODebugPosedPlayer actor is found at Actor -> RODebugPosedPlayer<br />
<br />
===Properties===<br />
<br />
[[File:RODebugPosedPlayerProperties.jpg|Properties of RODebugPosedPlayer]]<br />
<br />
*Pose: The pose, or stance, the posed player will be in when spawned<br />
*Weapon: The weapon the posed player will be using when posed<br />
*Pawn Type: German or Russian<br />
*Can Possess: Allows the user to possess this posed player using the '''PossessPosedPlayer''' console command<br />
*Description: Small description on what this posed player is - OPTIONAL<br />
<br />
====Available Poses====<br />
<br />
[[File:RODebugPosedPlayerProperties_Pose.jpg|Available Poses for RODebugPosedPlayer]]<br />
<br />
The pose will not make a difference in regards to performance and optimization. It was added so if you wanted to stage a scene for screen shots or something along those lines, this allows you to put the posed player into various positions.<br />
<br />
====Can Possess====<br />
<br />
[[File:RODebugPosedPlayerProperties_CanPossess.jpg|Can Possess Changes Color of RODebugPosedPlayer to BLUE]]<br />
<br />
==Placing RODebugPosedPlayer Actor in Map==<br />
<br />
====Posed Player Placement Guideline====<br />
<br />
*Expected player count is 64 player which would be the worse case scenario in regards to performance<br />
*Use Can Possess on posed players that have vantage view on a particular high traffic area/areas of performance pits<br />
*Any particular player SHOULD NOT see 100% of the map nor players<br />
*Place the actors where players will be<br />
*Do not unnaturally bunch up the posed players<br />
*Distribute the posed players evenly across scene<br />
*More actors near objective spaces, spawn areas, and known fight spaces<br />
*Position RODebugPosedPlayers ~16 Unreal Units above surface to avoid posed player clipping/failure to spawn<br />
<br />
====Create a NEW sublevel====<br />
<br />
[[FILE:LevelBrowser_CreateNEW.jpg|Create a new sub level]]<br />
<br />
=====Naming the Sub Level=====<br />
<br />
[[FILE:LevelBrowser_LevelName.jpg|Give the new sub level a name]]<br />
<br />
Give the sub level a name. It really doesn't matter what you call it as long as you know what it is.<br />
<br />
=====Setting Streaming Method=====<br />
<br />
[[File:LevelBrowser_StreamingMethod.jpg|Set Streaming Method to Always Loaded]]<br />
<br />
We always use Always Loaded so that every time the persistent is loaded, so is this sublevel. Done this way there is no need to have Kismet handle it.<br />
<br />
Options:<br />
*Kismet- Used when you want to use a Kismet node to stream in the sub level. <br />
*Distance- Used when you want to use a certain distance.<br />
*Always Loaded- Used when you want the sub level always loaded when the persistent is loaded.<br />
<br />
[http://udn.epicgames.com/Three/LevelStreamingHome.html Epic Games' UDN Page]<br />
<br />
=====Making New Sub Level Current=====<br />
<br />
[[FILE:LevelBrowser_MakeCurrent.jpg|Set the new sub level as CURRENT]]<br />
<br />
Make the new sub level current and we are ready to start placing actors.<br />
<br />
<br />
==Results==<br />
<br />
[[FILE: PosedPlayer_Placed_L.jpg|This is what we got in Grain Elevator]]<br />
<br />
=Doing the Profile=<br />
<br />
I will document what was done at TWI. Our profiling parameters and data gathering points were specific to our needs for our designs.<br />
<br />
==Profiling Machine Hardware Specifications==<br />
<br />
These are the specifications of the test machine used at TWI<br />
<br />
*Intel Quad 2.40GHz<br />
*4GB RAM<br />
*ATI Radeon HD 5800<br />
*Test Done on High Settings<br />
<br />
==Console Commands==<br />
<br />
*SpawnPosedPlayers<br />
<br />
*PossessPosedPlayer<br />
<br />
==Polling the Results==<br />
<br />
*Location @<br />
*Frame Time<br />
*Game Time<br />
*FPS<br />
*Draw Time (ms)<br />
*GPU Time (ms)<br />
*DrawPrimitive Calls<br />
*Triangles Drawn<br />
*Static Mesh Tris<br />
*Skel Mesh Draw Calls<br />
*Per Object shadows<br />
*Preshadows<br />
*Adjusted FPS<br />
<br />
==Store Results for Future Profiles==<br />
<br />
=RO2 Static Mesh Combining Tool=<br />
<br />
This tool allows for you to combine similar staticmeshes into one staticmesh allowing you to reduce the overall draw calls per scene frame. We had a number of guidelines that we worked with to get the best results that we could.<br />
<br />
NOTE: When you are combining meshes it's a good idea to keep an eye on Properties -> Static Mesh Component -> Override Light Map Res and it's Boolean bit as well. Having a non default value will result in lightmap errors.<br />
<br />
[[File:StaticMeshProperties_LightmapOverride.jpg|thumb|300px|center|Keep an eye on Properties -> Static Mesh Component -> Override Light Map Res]]<br />
<br />
To override the lightmap of combined meshes, do it at the asset itself in the package. StaticMesh Asset Properties -> Light Map Resolution -> [INTEGER]<br />
<br />
[[File:StaticMeshProperties_AssetLightmapOverride.jpg|thumb|300px|center|Override the lightmap resolution here instead]]<br />
<br />
==Combining Tool Guidelines==<br />
<br />
*Do not combine meshes that do not share that same material(s) in the same slots<br />
*Do not combine too many meshes that you fight with the natural occlusion systems as even the smallest of pixel of a mesh being rendered will render the entirety of the mesh<br />
*Do not combine meshes that will give you exceedingly high poly counts. (>5000)<br />
*Do not combine meshes that you cannot use over and over as this fights with the engine's instancing capability<br />
*Culling > Occlusion<br />
<br />
==Combining Process==<br />
<br />
===Combine Mesh Context Menu===<br />
<br />
[[image:CombineMesh_ContextMenu.jpg|thumb|300px|center|RMB -> Combine Mesh from context menu]]<br />
<br />
===Create New Asset Location===<br />
<br />
[[image:CombineMesh_NewAssetLocation.jpg|thumb|300px|center|Select the Package, Group, and Name of the Asset]]<br />
<br />
===Combine Convex Collision===<br />
<br />
[[image:CombineMesh_ConvexCollisionCombine.jpg|thumb|300px|center|Takes all the convex collision hull primitives and adds them together]]<br />
<br />
===Replace Actors in Scene===<br />
<br />
[[image:CombineMesh_ReplaceActor.jpg|thumb|300px|center|Replace the actor in the scene?]]<br />
<br />
==UnCombining Process==<br />
<br />
[[image:UNCombineMesh_ContextMenu.jpg|thumb|300px|center|RMB -> Uncombine Mesh from context menu]]<br />
<br />
RMB -> UnCombine Mesh<br />
<br />
This will simply uncombine the meshes and replace them with the stored reference of the original assets in the combined mesh. Do not uncombine more than one combined mesh at a time.<br />
<br />
=Procedural bCastDynamicShow System=<br />
<br />
Every static mesh object in the map has the capability to cast a dynamic shadow. A dynamic shadow uses the cascade shadowing system to make nice crisp shadows for the world objects when the player gets near them. The down side is that they can be an expensive render, relatively, when the engine must cast a dynamic shadow into an already shadowed space. To save from having to check this on each and every object in the world a new system was introduced that traces a line from the 8 corners of the bounding box of the static mesh actor back to the DominantDirectionalLight in the map. If ANY of the traces hit the DominantDirectionalLight, the bCaseDynamicShadow Boolean variable is set to TRUE. If none of the traces touches the DominantDirectionalLight then the variable is set to FALSE.<br />
<br />
Some times you can get a false readings in situations where all 8 corners of the bounding box are contained in another mesh (such as walls with a pillar on each side of each section of wall). In this case we've given the capability for the Level Designer to override the procedural system.<br />
<br />
StaticMeshActor Properties -> StaticMeshComponent -> Lighting -> Allow Auto Cast Dynamic Shadow Override</div>Keithhttps://wiki.tripwireinteractive.com/index.php?title=File:UNCombineMesh_ContextMenu.jpg&diff=1366File:UNCombineMesh ContextMenu.jpg2012-07-06T14:57:59Z<p>Keith: </p>
<hr />
<div></div>Keithhttps://wiki.tripwireinteractive.com/index.php?title=Red_Orchestra_2:_Heroes_Of_Stalingrad/LevelDesign/OptimizationGuide&diff=1365Red Orchestra 2: Heroes Of Stalingrad/LevelDesign/OptimizationGuide2012-07-06T14:54:02Z<p>Keith: /* Combining Process */</p>
<hr />
<div><br />
== Recommended Reading ==<br />
<br />
<br />
If you are new to optimizing in general for Unreal 3 games please have a look through the below web pages so you are up to speed with the grunt work.<br />
<br />
===Epic's Unreal Development Network - UDN===<br />
====[http://udn.epicgames.com/Three/PerformanceHome.html Epic's Performance UDN Page]====<br />
<br />
====[http://udn.epicgames.com/Three/ProfilingBasics.html Epic's Profiling UDN Page]====<br />
<br />
====[http://udn.epicgames.com/Three/MemoryProfilingHome.html Epic's Memory Profiling UDN Page]====<br />
<br />
====[http://udn.epicgames.com/Three/RenderThreadProfilingHome.html Epic's Rendering Thread Profiling UDN Page]====<br />
<br />
=Introduction=<br />
<br />
The purpose of this document is to give information on the guidelines used to optimize the maps inside RO2. These guidelines worked for us. If you are a community level designer and/or artist you may find this document useful. This document will cover the various approaches and the reasoning behind decisions so that the reader may be able to avoid pitfalls when making levels for Red Orchestra 2.<br />
<br />
The following is a list of items that LDs and Environment Artists should follow for a map to perform well. Most of these were lessons learnt while optimizing RO2 and should also serve as a guideline for modders to make sure that they don't run into the same pitfalls.<br />
<br />
=Level Performance Guidelines=<br />
==Terrain==<br />
<br />
=== bCastDynamicShadow ===<br />
This flag should be OFF. Setting this flag to ON will cast dynamic preshadows by the terrain for both per-object shadows and whole scene dynamic shadows, which can be very expensive depending on the number of dynamic primitives in the scene. Preshadows (which are dynamic shadows from the static environment onto dynamic objects) only make sense if the terrain has hills and valleys throughout the scene. If the scene just has a few mounds here and there it might be worth modeling the mounds with static meshes and have the terrain blend in at the bottom. The side effect of disabling bCastDynamicShadow is that terrain deco layers (e.g. grass) will not cast whole scene dynamic shadows. But considering that shadows from deco layers usually are low-res and don't look great, it is a good price to pay for a substantial performance boost.<br />
<br />
[[Image:GrassShadows.png|center|frame|Low Res deco layer shadows]]<br />
<br />
=== Terrain Layers ===<br />
The RO2 engine allows for a maximum of 12 textures to be blended for terrain. These 12 textures could be part of 2 terrain layers (6 textures each), 3 terrain layers (4 textures each), or any other combination thereof. This is a hard limit for the engine, and exceeding this limit will result in rainbow colored terrain patches. However, fetching and accessing so many textures is not cheap and since the terrain usually takes up a large portion of the screen, it is recommended that you keep the number of blend textures to a minimum.<br />
<br />
One example for this is that say you have a terrain which comprises or dirt, rubble and snow and one part of the terrain is solid concrete. Instead of making 4 terrain layers of dirt, rubble, snow and concrete and blending between them it is more optimized if the terrain uses 3 layers of dirt, rubble and snow, and the concrete portion is modeled separately as BSP, static mesh or even another terrain actor. Doing this will reduce the overall cost of rendering the entire terrain since the concrete layer texture fetches are eliminated for the rest of the terrain that doesn't need it.<br />
<br />
==Static Meshes==<br />
<br />
=== bCastDynamicShadow ===<br />
When placing a static mesh in the level, you should decide whether you want it to cast dynamic preshadows or not. Preshadows are dynamic shadows from the static environment onto dynamic objects, and can be very expensive depending on the number of dynamic primitives in the scene. Turning off this flag for a lot of static meshes in the environment in the scene such as debris, rubble, etc. will improve the dynamic shadow performance.<br />
<br />
[[Image:Preshadows.png|center|frame|Dynamic preshadows cast by tree foliage onto character]]<br />
<br />
Once the lighting in a map is finalized, you can also go through and set bCastDynamicShadow to false for all static meshes that are already in shadow (such as the truck in the following image, which is is shadow of the building) since any dynamic shadow cast by it will be drowned by the static shadow cast by the environment.<br />
<br />
[[Image:DynamicShadowTruck.jpg|thumb|300px|center|The truck does not need to cast dynamic shadows since it is already in shadow]]<br />
<br />
=== Distance Culling ===<br />
Using distance culling effectively will allow you to have a lot of detail in your environment whilst still allowing the map to perform well. There are 2 ways to do this :<br />
<br />
* You can either put a CullDistanceVolume around the map and the let the map build process choose the appropriate cull distances for the placed static meshes in the level. This method is not ideal though, and might cause certain cover objects, etc. to disappear at a distance (which is not desirable). <br />
<br />
* Or, you can manually set the MaxDrawDistance for each object.<br />
<br />
== Materials ==<br />
=== Using Material LODs ===<br />
In order to make the best looking environment materials as well as keep the overall performance cost low, consider using material LODs. The concept is very simple - assign the best looking/highest instruction count material to the base LOD for a static mesh, and then create another LOD for the static mesh (this can have the exact same triangle count as the base LOD) and assign it a simple material that does not have expensive operations such as depth biased alpha, specularity, cube maps or even normal maps. Such subtle lighting effects cannot be perceived from a distance anyway, and will make improve the fill rate for the rendered scene.<br />
<br />
[[Image:NormalMappedBaseMaterial.png|thumb|300px|center|Base material using normal maps]][[Image:SimpleMaterial.png|thumb|300px|center|Simple material that does not use normal maps]]<br />
<br />
== Dynamic Actors ==<br />
=== bDisablePerObjectShadows ===<br />
If you place an actor onto a level that casts dynamic shadows, the shadowing cost for it is one per object shadow and in certain cases a preshadow as well. If bDisablePerObjectShadows is set it will only cast dynamic shadows for the primitive if it is within the whole scene dominant shadow radius. This reduces the cost associated with shadowing for the primitive. If whole scene dominant shadows are not enabled, the primitive will not cast any dynamic shadows.<br />
<br />
[[Image:DisablePerObjectShadowsDemo.jpg|thumb|600px|center|The flag pole is outside the whole scene dominant shadow radius in the image on the left and hence is not shadowed. When the player moves such that the flag pole is now within the whole scene dominant shadow radius, it will start casting whole scene dominant shadows (right image)]]<br />
<br />
=== bAllowMergedDynamicShadows ===<br />
If this flag is set, any primitive that allows per object dynamic shadows will be considered for being merged with other primitives that allow merged per object dynamic shadows and are close enough. As a consequence, the number of dynamic shadows in the scene are reduced.<br />
<br />
The radius used to merge primitives is dynamically adjusted based on the distance of the primitives from the viewer. It starts at ''MinShadowGroupRadius'' (when the primitive is closest to the viewer) and increases up to ''MaxShadowGroupRadius'' (when the primitive is ''ShadowGroupRampCutoff'' away from the viewer). The rate of increase is determined by ''ShadowGroupRadiusRampUpFactor''. For anything beyond ''ShadowGroupRampCutoff'', the ''MaxShadowGroupRadius'' will be used. All these settings are available in the engine INI.<br />
<br />
[[Image:GroupedDynamicPerObjectShadowsDemo.jpg|thumb|600px|center|The image on the left has bAllowMergedDynamicShadows set to false on the two placed pawns, and they cast a per object shadow each. The image on the right has bAllowMergedDynamicShadows set to true on the pawns, and as such both the pawns are included in the same projected shadow.]]<br />
<br />
== Draw Calls ==<br />
== About Draw Calls==<br />
As the UE3 rendering engine is a Direct X 9.0 renderer, it is limited to one CPU core to tell the GPU about what to draw. It does this via a Draw Call. Each object you place in the world is at least one draw call (if not more due to shadows). The CPU can become the bottleneck of a level if it is trying to tell the GPU to draw a detailed scene and chokes on the amount of draw calls. This is why it is best to limit the amount in any given scene. With the Red Orchestra SDK it is very easy to make many types of levels, from wide open plains (or with rolling hills) to detailed interior settings and building to building fighting. However, depending on what the scale of your map is, you will be limited in the amount of "detail" you can place in the level. <br />
<br />
<br />
== Limiting Draw Calls Per Scene==<br />
Suggested Maximum Draw Call Limit: 2000<br />
<br />
Using the console command ''Stat d3d9rhi"'' a Level Designer/Artist (or anyone) can go through a level and find out the amount of Draw Calls and optimize based on areas where it has increased beyond the suggested maximum.<br />
<br />
The details settings for both users and in the SDK allows Level Designers to put some objects on different levels of the setting so those with faster computers (in this case CPU core speed) can see more details without harming performance for those with slower machines. It is best to do this with "fluff" detail that is not gameplay important but just makes the level look better overall.<br />
<br />
<br />
=Profiling Preliminary Work=<br />
<br />
There is a small amount of setup work that must be completed.<br />
<br />
==RODebugPosedPlayer==<br />
<br />
We have made a tool for level designers and artists that are used to gather statistical data about maps called Posed Players. The purpose of the Posed Player is to have a placeable actor to simulate a player in a scene. It has the capability to be used as a camera during profile stage. All of which I will go over now.<br />
<br />
===Actor In Tree===<br />
<br />
[[Image:RODebugPosedPlayerActorTree.jpg|thumb|300px|center|RODebugPosedPlayer in Actor Tree]]<br />
<br />
The RODebugPosedPlayer actor is found at Actor -> RODebugPosedPlayer<br />
<br />
===Properties===<br />
<br />
[[File:RODebugPosedPlayerProperties.jpg|Properties of RODebugPosedPlayer]]<br />
<br />
*Pose: The pose, or stance, the posed player will be in when spawned<br />
*Weapon: The weapon the posed player will be using when posed<br />
*Pawn Type: German or Russian<br />
*Can Possess: Allows the user to possess this posed player using the '''PossessPosedPlayer''' console command<br />
*Description: Small description on what this posed player is - OPTIONAL<br />
<br />
====Available Poses====<br />
<br />
[[File:RODebugPosedPlayerProperties_Pose.jpg|Available Poses for RODebugPosedPlayer]]<br />
<br />
The pose will not make a difference in regards to performance and optimization. It was added so if you wanted to stage a scene for screen shots or something along those lines, this allows you to put the posed player into various positions.<br />
<br />
====Can Possess====<br />
<br />
[[File:RODebugPosedPlayerProperties_CanPossess.jpg|Can Possess Changes Color of RODebugPosedPlayer to BLUE]]<br />
<br />
==Placing RODebugPosedPlayer Actor in Map==<br />
<br />
====Posed Player Placement Guideline====<br />
<br />
*Expected player count is 64 player which would be the worse case scenario in regards to performance<br />
*Use Can Possess on posed players that have vantage view on a particular high traffic area/areas of performance pits<br />
*Any particular player SHOULD NOT see 100% of the map nor players<br />
*Place the actors where players will be<br />
*Do not unnaturally bunch up the posed players<br />
*Distribute the posed players evenly across scene<br />
*More actors near objective spaces, spawn areas, and known fight spaces<br />
*Position RODebugPosedPlayers ~16 Unreal Units above surface to avoid posed player clipping/failure to spawn<br />
<br />
====Create a NEW sublevel====<br />
<br />
[[FILE:LevelBrowser_CreateNEW.jpg|Create a new sub level]]<br />
<br />
=====Naming the Sub Level=====<br />
<br />
[[FILE:LevelBrowser_LevelName.jpg|Give the new sub level a name]]<br />
<br />
Give the sub level a name. It really doesn't matter what you call it as long as you know what it is.<br />
<br />
=====Setting Streaming Method=====<br />
<br />
[[File:LevelBrowser_StreamingMethod.jpg|Set Streaming Method to Always Loaded]]<br />
<br />
We always use Always Loaded so that every time the persistent is loaded, so is this sublevel. Done this way there is no need to have Kismet handle it.<br />
<br />
Options:<br />
*Kismet- Used when you want to use a Kismet node to stream in the sub level. <br />
*Distance- Used when you want to use a certain distance.<br />
*Always Loaded- Used when you want the sub level always loaded when the persistent is loaded.<br />
<br />
[http://udn.epicgames.com/Three/LevelStreamingHome.html Epic Games' UDN Page]<br />
<br />
=====Making New Sub Level Current=====<br />
<br />
[[FILE:LevelBrowser_MakeCurrent.jpg|Set the new sub level as CURRENT]]<br />
<br />
Make the new sub level current and we are ready to start placing actors.<br />
<br />
<br />
==Results==<br />
<br />
[[FILE: PosedPlayer_Placed_L.jpg|This is what we got in Grain Elevator]]<br />
<br />
=Doing the Profile=<br />
<br />
I will document what was done at TWI. Our profiling parameters and data gathering points were specific to our needs for our designs.<br />
<br />
==Profiling Machine Hardware Specifications==<br />
<br />
These are the specifications of the test machine used at TWI<br />
<br />
*Intel Quad 2.40GHz<br />
*4GB RAM<br />
*ATI Radeon HD 5800<br />
*Test Done on High Settings<br />
<br />
==Console Commands==<br />
<br />
*SpawnPosedPlayers<br />
<br />
*PossessPosedPlayer<br />
<br />
==Polling the Results==<br />
<br />
*Location @<br />
*Frame Time<br />
*Game Time<br />
*FPS<br />
*Draw Time (ms)<br />
*GPU Time (ms)<br />
*DrawPrimitive Calls<br />
*Triangles Drawn<br />
*Static Mesh Tris<br />
*Skel Mesh Draw Calls<br />
*Per Object shadows<br />
*Preshadows<br />
*Adjusted FPS<br />
<br />
==Store Results for Future Profiles==<br />
<br />
=RO2 Static Mesh Combining Tool=<br />
<br />
This tool allows for you to combine similar staticmeshes into one staticmesh allowing you to reduce the overall draw calls per scene frame. We had a number of guidelines that we worked with to get the best results that we could.<br />
<br />
NOTE: When you are combining meshes it's a good idea to keep an eye on Properties -> Static Mesh Component -> Override Light Map Res and it's Boolean bit as well. Having a non default value will result in lightmap errors.<br />
<br />
[[File:StaticMeshProperties_LightmapOverride.jpg|thumb|300px|center|Keep an eye on Properties -> Static Mesh Component -> Override Light Map Res]]<br />
<br />
To override the lightmap of combined meshes, do it at the asset itself in the package. StaticMesh Asset Properties -> Light Map Resolution -> [INTEGER]<br />
<br />
[[File:StaticMeshProperties_AssetLightmapOverride.jpg|thumb|300px|center|Override the lightmap resolution here instead]]<br />
<br />
==Combining Tool Guidelines==<br />
<br />
*Do not combine meshes that do not share that same material(s) in the same slots<br />
*Do not combine too many meshes that you fight with the natural occlusion systems as even the smallest of pixel of a mesh being rendered will render the entirety of the mesh<br />
*Do not combine meshes that will give you exceedingly high poly counts. (>5000)<br />
*Do not combine meshes that you cannot use over and over as this fights with the engine's instancing capability<br />
*Culling > Occlusion<br />
<br />
==Combining Process==<br />
<br />
===Combine Mesh Context Menu===<br />
[[image:CombineMesh_ContextMenu.jpg|thumb|300px|center|RMB -> Combine Mesh from context menu]]<br />
<br />
===Create New Asset Location===<br />
[[image:CombineMesh_NewAssetLocation.jpg|thumb|300px|center|Select the Package, Group, and Name of the Asset]]<br />
<br />
==Combine Convex Collision===<br />
[[image:CombineMesh_ConvexCollisionCombine.jpg|thumb|300px|center|Takes all the convex collision hull primitives and adds them together]]<br />
<br />
===Replace Actors in Scene===<br />
[[image:CombineMesh_ReplaceActor.jpg|thumb|300px|center|Replace the actor in the scene?]]<br />
<br />
==UnCombining Process==<br />
<br />
RMB -> UnCombine Mesh<br />
<br />
This will simply uncombine the meshes and replace them with the stored reference of the original assets in the combined mesh. Do not uncombine more than one combined mesh at a time.<br />
<br />
=Procedural bCastDynamicShow System=<br />
<br />
Every static mesh object in the map has the capability to cast a dynamic shadow. A dynamic shadow uses the cascade shadowing system to make nice crisp shadows for the world objects when the player gets near them. The down side is that they can be an expensive render, relatively, when the engine must cast a dynamic shadow into an already shadowed space. To save from having to check this on each and every object in the world a new system was introduced that traces a line from the 8 corners of the bounding box of the static mesh actor back to the DominantDirectionalLight in the map. If ANY of the traces hit the DominantDirectionalLight, the bCaseDynamicShadow Boolean variable is set to TRUE. If none of the traces touches the DominantDirectionalLight then the variable is set to FALSE.<br />
<br />
Some times you can get a false readings in situations where all 8 corners of the bounding box are contained in another mesh (such as walls with a pillar on each side of each section of wall). In this case we've given the capability for the Level Designer to override the procedural system.<br />
<br />
StaticMeshActor Properties -> StaticMeshComponent -> Lighting -> Allow Auto Cast Dynamic Shadow Override</div>Keithhttps://wiki.tripwireinteractive.com/index.php?title=File:CombineMesh_ReplaceActor.jpg&diff=1364File:CombineMesh ReplaceActor.jpg2012-07-06T14:50:01Z<p>Keith: </p>
<hr />
<div></div>Keithhttps://wiki.tripwireinteractive.com/index.php?title=File:CombineMesh_ConvexCollisionCombine.jpg&diff=1363File:CombineMesh ConvexCollisionCombine.jpg2012-07-06T14:49:44Z<p>Keith: </p>
<hr />
<div></div>Keithhttps://wiki.tripwireinteractive.com/index.php?title=File:CombineMesh_NewAssetLocation.jpg&diff=1362File:CombineMesh NewAssetLocation.jpg2012-07-06T14:49:32Z<p>Keith: </p>
<hr />
<div></div>Keith