UDN
Search public documentation:
PhysicalMaterialSystem
日本語訳
中国翻译
한국어
Interested in the Unreal Engine?
Visit the Unreal Technology site.
Looking for jobs and company info?
Check out the Epic games site.
Questions about support via UDN?
Contact the UDN Staff
中国翻译
한국어
Interested in the Unreal Engine?
Visit the Unreal Technology site.
Looking for jobs and company info?
Check out the Epic games site.
Questions about support via UDN?
Contact the UDN Staff
Physical Materials
Document Summary: This page details the Physical Material system and gives some examples on how to create material based effects (e.g. impact effects, footstep sounds) preface. Document Changelog: created preface.Overview
This page is broken down into the following sections:-Overview of the PhysicalMaterial system.
-Detailing how to create a Hierarchy of Physical Materials.
-How to then use that Hierarchy for material based effects.
-Example Code of how to make material based footsteps work
Overview of Physical Material System
In UE3 you can attach a PhysicalMaterial to a Material or MaterialInstanceConstant. Attaching, as opposed to just having a material have additional properties, allows for you to reuse your PhysicalMaterialSystem on multiple Materials. A quick example would be the following: You have a gravelRoad Material which you have applied to the gravel road in the game. That gravelRoad Material has a PhysicalMaterial called gravel. In that gravel PhysicalMaterial you have set the various footstep sounds that play based on the PawnType whom is doing the foot stepping. When PawnTypeOne walks, it plays a sound from SoundCue A. When PawnTypeTwo walks, it plays a sound from SoundCue B. **Two physical materials on the same material are now supported on a single material. When a collision occurs the line check code finds the triangle hit, gets the texture UV at the hit location and looks up into a mask texture to determine if the hit pixel is black or white. The corresponding physical material will be returned.Details for Programmers
Details: Look at PhysicalMaterial.uc Specifically:var(PhysicalProperties) export editinline PhysicalMaterialPropertyBase PhysicalMaterialProperty;PhysicalMaterialPropertyBase.uc has the comments you will want to read! To get contextual footstep sounds and lay the framework for having other neat PhysicalMaterial based effects you would make a class:
class MyGamePhysicalMaterialProperty extends PhysicalMaterialPropertyBase collapsecategories editinlinenew hidecategories(Object); var(FootSteps) editinline MyGamePhysicalMaterialFootSteps MyGamePhysicalMaterialFootSteps;and then in class MyGamePhysicalMaterialFootSteps you have:
var() SoundCue ProtagonistFootSteps; var() SoundCue NPCTypeOneFootSteps; var() SoundCue NPCTypeTwoFootSteps;etc So now when a Pawn steps (either through AnimNotify_Footstep or some other method) you can call eventPlayFootStepSound which will then send that event to the correct pawn. Now that pawn can determine what sound to play based on its type and the physical material! e.g. NPC Ogre is walking along the gravel road. When it steps and eventPlayFootStepSound has been called then trace down, find the physical material, get the SoundCue? based on the pawn type and play it. NOTE: currently you will have to do a trace down to get the physical material. We are probably going to update eventPlayFootStepSound to pass a physical material as it will be more efficient to do the trace straight in c++ land and that this is a feature that most licensees want in their games. Contextual Footstep sounds are nice! Obviously with the PhysicalMaterial system and a framework of properties, like the above, you can do all kinds of really awesome contextual functionality (e.g. impact sounds, hit effects, decals, footsteps, etc.)
Hierarchy of Physical Materials.
Once your programming staff has created the specific game classes above, your content team can start making Hierarchies of Physical Materials and start populating them with the effects your game design demands.Details for Content Creators
The PhysicalMaterial has a var(Parent)PhysicalMaterial Parent; This allows you to create hierarchies of physical materials and thereby (in our example case) hierarchies of FootStep sounds. So you can have:Default ^ | Clay ^ | Wet ClaySo now your content team can be really specific in the physical materials they have in the game world. And when you want to have a Wet Clay footstep sound you can. If you don't have a Wet Clay footstep sound then you can look up the hierarchy until you find one or end up at the Default which should have your default footstep sound.
Using the Hierarchy
So now that you have both code support and a paramaterized Physical Material Hierarchy you can now assign Physical Materials to Materials! Once you have assigned them you should hear them playing in the game.Content Suggestions
When making footsteps (to continue our example) you should have your sound team make SoundCues with randomized footsteps in both the source sound and then the pitch and attenuation. This leads to a more believable foot step sound. Additionally it provides the correct abstraction to the Physical Material system.Example code.
/** * Event from c++ land that tells us to play a footstep **/ event PlayFootStepSound(int FootDown) { local vector PawnLoc; local float CurrHeight; local Actor TraceActor; local vector out_HitLocation; local vector out_HitNormal; local vector TraceDest; local vector TraceStart; local vector TraceExtent; local TraceHitInfo HitInfo; // kk here we need to do a tracez0r down down into the ground baby! // NOTE: this will eventually be moved to c++ land PawnLoc = self.Location; CurrHeight = self.GetCollisionHeight(); TraceStart = PawnLoc; TraceDest = PawnLoc - ( Vect(0, 0, 1 ) * CurrHeight ) - Vect(0, 0, 15 ); // trace down and see what we are standing on TraceActor = Trace( out_HitLocation, out_HitNormal, TraceDest, TraceStart, false, TraceExtent, HitInfo, true ); //DrawPersistentDebugLine( TraceStart, TraceDest, 255, 0, 0 ); if( TraceActor != none ) { // play the actual sound now ActuallyPlayFootStepSound( FootDown, HitInfo ); MakeNoise( 0.1f, 'NOISETYPE_FootStep' ); } // otherwise we hit nothing and are in the air else { // Log( " We are in the air" ); } } /** * This will figure out which material we are standing on and then play the * correct footstep sound. * It looks up the PhysicalMaterial tree until it finds a valid effect to Spawn. * If it does not find one then it defaults the effect coded in to the .uc file * for that specific weapon **/ function ActuallyPlayFootStepSound( int FootDown, TraceHitInfo HitInfo ) { local PhysicalMaterial ParentPhysMaterial; local SoundCue SC; local SoundCue FootStepSound; // XO5 HAX0R // if we are in the rain then play water footsteps // NOTE: right now terrain dows not return material for traces so we need to do this //if( IsTimerActive( 'DropRainDropsOnToPawn' ) == TRUE ) if( bShouldPlayWetFootSteps == TRUE ) { Self.PlaySound( SoundCue'FootSteps.SoundCues.Footsteps_Marcus_Water', FALSE, TRUE ); return; } // if we do not have a PhysicalMaterial if( HitInfo.PhysMaterial != none ) { FootStepSound = GetFootStepSound( HitInfo.PhysMaterial, FootDown ); } else { // check to see if there is a material // if there is no material then we must use the default PS_DefaultImpactEffect if( HitInfo.Material != none ) { FootStepSound = GetFootStepSound( HitInfo.Material.PhysMaterial, FootDown ); } else { // always play the "Default footsteps sounds" which is the dirt step Self.PlaySound( SoundCue'FootSteps.SoundCues.Footsteps_Marcus_Dirt', FALSE, TRUE ); return; } } // so here we need to look up the "hierarchy" if we have a none in the attribute we want // and we probably want to maybe have a code fall back to play some default // if the content doens't provide our hungry mouths with data // if we have no phys material if( HitInfo.PhysMaterial != none ) { ParentPhysMaterial = HitInfo.PhysMaterial.Parent; } // set the parent phys material here else { // check to see if the material has a phys material if( HitInfo.Material.PhysMaterial != none ) { ParentPhysMaterial = HitInfo.Material.PhysMaterial.Parent; } else { ParentPhysMaterial = none; } } // this will walk the tree until our parent is null or we have a footstep sound // at which point we will break out (which is basically an exception case) // but there are no exceptions in .uc land while( ( FootStepSound != none ) && ( ParentPhysMaterial != none ) ) { // look at our parent's data FootStepSound = GetFootStepSound( ParentPhysMaterial, FootDown ); ParentPhysMaterial = ParentPhysMaterial.Parent; } // use the material based effect if( FootStepSound != none ) { //Log( " Playing Sound: " $ FootStepSound ); SC = FootStepSound; } // do default behavior else { //Log( " Playing Default Sound" ); SC = SoundCue'FootSteps.SoundCues.Footsteps_Marcus_Dirt'; } Self.PlaySound( SC, FALSE, TRUE ); } /** * Looks to see if the Sound on the current PhysicalMaterial is valid. **/ function SoundCue GetFootStepSound( PhysicalMaterial PMaterial, int FootDown ) { local SoundCue Retval; Retval = none; // our Specific properties exists now we need to call our function to get out // the specificProperty if( ( none != PMaterial ) && ( none != PMaterial.PhysicalMaterialProperty ) && ( none != WarPhysicalMaterialProperty(PMaterial.PhysicalMaterialProperty) ) && ( none != WarPhysicalMaterialProperty(PMaterial.PhysicalMaterialProperty).WarPhysicalMaterialFootSteps ) ) { Retval = GetSpecificFootStepSound( WarPhysicalMaterialProperty(PMaterial.PhysicalMaterialProperty).WarPhysicalMaterialFootSteps, FootDown ); } else { Retval = none; } return Retval; } /** * Each object is going to override this and return the data based off the passed in * Object. (e.g. GetSpecificFootStepSound called on a marcus will look up the * marcus footstep sound, called on a locust will look up the locust sound) **/ function SoundCue GetSpecificFootStepSound( WarPhysicalMaterialFootSteps FootStepSounds, int FootDown ) { local SoundCue Retval; // do possible computation or what not. Retval = None; return Retval; } e.g. in class BigOgre function SoundCue GetSpecificFootStepSound( MyGamePhysicalMaterialFootSteps FootStepSounds, int FootDown ) { local SoundCue Retval; // do possible computation or what not. Retval = SoundCue'FootSteps.SoundCues.Footsteps_Player_Dirt'; // or make this a config and store the value in an .ini for editing by non programmers return Retval; } |