Announcement

Collapse
No announcement yet.

[WalkThrough] How to make a mesh particlesystem shield appear when actor is shot

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    [WalkThrough] How to make a mesh particlesystem shield appear when actor is shot

    Hi There!

    What you will have when you are done with this Walkthrough Tutorial:

    A cool feature for your enemy actors:
    if they have a shield equipped (a simple boolean can control this), when your projectiles hit them:

    - a glowing energy shield appears in front of them, even as they move around, telling the player that they are shielded.

    - This shield is in full 3d, so as you rotate around the actor you just hit, you can see the shield from other angles, and this tells the player clearly what is going on and why they are doing less/no damage.

    ~~~

    You do not need to have any art assets for this tutorial other than what comes with the UDK.

    ~~~

    In these pictures the green gem-shaped thing is the enemy actor








    Review of Key Features of this tutorial:

    1. create a mesh-based particle effect that spawns a shield-looking colorful barrier in front of an actor when the actor is hit by your custom projectile.

    2. How to do the unrealscript code so that the shield mesh particle is always facing the camera when it first spawns, but then as you rotate around it you can see the full 3D-ness of the mesh.

    3. How to set up the particle system so that the shield mesh is attached to the actor you hit, and moves with the actor, always staying in front so it is fully visible, and not getting left behind

    3. How to set up the material from scratch for the above mesh-based particle

    4. What code to add to your custom projectile class so that the shield barrier particle spawns when the projectile collides with the actor that you are shooting.

    I do not cover:

    -how to make a custom projectile class
    -the basics of setting up your custom playercontroller/enemies to use the custom projectile

    A tutorial of mine to review:
    Spawning ParticleSystems that explode/loop once

    ~~~

    The Art Assets Used

    I will be relying on on you having a udk version that includes the default meshes and materials that I use in this tutorial:

    Material
    Material'Envy_Effects.Materials.M_FX_HeadshotShiel d_Fragment'

    Mesh
    StaticMesh'Envy_Effects.Mesh.S_FX_Headshield_Fragm ent'
    (get rid of that space in fragment, not sure how to get rid of it in how this displays)

    I do this for the speedyness of this walkthrough, and so you don't have to create your own art assets from scratch to follow along with the overall process.

    This tutorial will give you a sense of how to do this for your own art assets though!

    ~~~

    The material

    I am using the following material as a base, make a copy of this material in the UDK, right click -> make copy

    save it in your package or make a new one.

    Here is the original material




    Here is the modification I am making, I am using a bias of 64 as per a Hourences tutorial (thank you Hourences )

    use the search bar in upper right and type in "alpha" to find this module.

    What does this do?

    If you want your mesh to be able to fade in and fade out you need this addition (alpha over life).

    You don't really need the DepthBasedAlpha, you can do a direct link from the alpha of the mesh vertex,

    but depthbased alpha will look prettier if your mesh collides with other level geometry edges in-game.



    ~~~

    The Particle System

    Make a new particle system, go the Required Module, and enter your material that you made

    right click on your system and Data -> add mesh data

    click on the meshdata module, which is black, and use this mesh:

    StaticMesh'Envy_Effects.Mesh.S_FX_Headshield_Fragm ent'
    (anyone now how to make that space stop appearing? it's not in the forum code version)

    I have another particle component in my system in the pictures above and below, you can look up info on making particlesystems to create your own additional components.

    But for this tutorial all the focus is on the particle component with the mesh data.

    Set up your "required" section as per below picture.

    What these fields do:

    use local space = makes sure the particle system will travel with whatever actor it is attached to, essential to keep the shield in front of the actor as it moves

    kill on complete/deactivate = makes sure the shield only appears once, and is then removed from the game, when it is spawned by unrealscript code.

    loops = 1, essential to ensure shield only appears once per projectile collision with actor.



    Then set up your "Spawn" Module as per below pic

    What the fields do:

    you do not want to spawn ANY instances of this effect using the traditional means, so it must be 0

    you are using Burst, which makes sure particle instances spawn at the specified time intervals

    time 0 = the instant the particlesystem is spawned using unrealscript

    This again ensures the shield only appears once per projectile collision



    ~~~

    Size

    the size of the mesh will default to around 25, which is generally HUGE.

    Try using something in range of 1 to 5 for the xyz of both min and max, or set it to be a constant xyz only.

    ~~~

    Color Over Life

    To change the shield's color during its life span, click on the Color Over Life module and then the little graph button so it shows up in the graphing section in lower right.

    Then click each of the colors on and off and arrange them as you like along the lifespan of your effect.

    There's lots of videos on this on youtube.

    Here's a great series:
    Particle Effects by GizmoSan
    ~~~

    Alpha Over Life

    If you want the shield to fade in, and then fade out, as is generally pretty-looking,

    you must set the color over Life module's Alpha over Life



    PLEASE NOTE

    Only set the alpha over life in the range 0 to 1 in the time scale.

    Even if your effect lasts 17 seconds long.

    The alpha over life time scale is mapped relative to the actual duration of the life of the effect.

    so if you want the alpha to peak at second 3 and second 7 in a span of 10 seconds

    you would create peaks at time 0.3 and 0.7, using an out value of 1.


    please note

    in value = time
    out vale = the alpha value at that time

    so in 0.3
    out 1

    means use alpha of 1 at 0.3 seconds


    please

    save yourself

    re-read this

    I spent 2.5 hours figuring this out since I could not find this info on the net

    you can read my post about it here hee hee:

    Rama's hunt for functional alpha over particle system life

    ~~~

    Save Your Package

    Save your package, right click your particle system to get its full path "copy full path to clipboard"

    Let's say your particlesystem is called:

    ParticleSystem'JoyPackage.Particles.ShieldCenter'


    ~~~

    The UnrealScript Code


    In Your Projectile Class Code:

    This is the code for the projectile you will be shooting at your enemy actor.

    Let's say your enemy actor class is called: Critter.uc


    In this example, the projectile class extends UTGame.UTProjectile.uc

    Code:
    function spawnShieldEffect(vector HitLocation, vector HitNormal, Critter theCritter) {
    	//local ParticleSystemComponent ProjExplosion;
    	local vector modifiedHitNorm;
    	local rotator shieldRot;
    
    	//set shield to same facing as player camera
    	shieldRot = InstigatorController.Rotation; 
            
            //your projectile must have access to your playercontroller class
            //InstigatorController is in engine.projectile.uc
            //If your projectile extends a UDK base classes this should be set for you
            //you can also set this at the time of spawning the projectile
    
    	//remove pitch so shield is always upright
    	shieldRot.pitch = 0;
    	
    	//the "normal" is perpendicular to the surface where projectile collided
    	modifiedHitNorm = HitNormal;
    	
    	//remove z so that the shield is always appear level with ground, off
    	//the point of the surface the projectile hits.
    	modifiedHitNorm.z = 0;
    	
    	
    	
    	//Can set the ProjExplosion var here 
           //if want to store/modify created particle
    	WorldInfo.MyEmitterPool.SpawnEmitter(
    		ParticleSystem'JoyPackage.Particles.ShieldCenter', 
    		HitLocation + modifiedHitNorm * 56, 
    		shieldRot, 							
    		theCritter);									
    	//56 is distance away from surface,
            //the hitlocation, in the direction of the modified hitnormal
    
             //The last parameter tells the particlesystem to be attached to
             //the actor that the projectile collided with.
    }
    
    //If your critter is a pawn	
    simulated function ProcessTouch (Actor Other, vector HitLocation, vector HitNormal)
    {
    if ( Other != Instigator && Other != joyBall)
    {
    		
    	if ( !Other.IsA('Projectile') || Other.bProjTarget )
    	{
    		MomentumTransfer = (UTPawn(Other) != None) ? 0.0 : 1.0;
    			
    		//hit a critter?
    			
    	         if (Other.isA('Critter')) {		
                         //if Critter(Other).hasShield) {
    			spawnShieldEffect(Location, HitNormal, IneffTendency(Wall));
    					
    			//Other.TakeLessDamage();
     
    			//base off of function below
    			//or just change the Damage value to Damage/2 or something
    					
    			//if commented out, critter takes no damage when it has a shield
    					
    			//remove projectile
    			Destroy();
    			}
    		//}
    		//else{ 
    			//Explode(Location, HitNormal);
    			//Other.TakeDamage(Damage, InstigatorController, HitLocation, 
                                     MomentumTransfer * Normal(Velocity), MyDamageType,, self);
    		//}
    	}
    }
    }
    
    //if your enemy critter class is based off of staticmesh/dynamicSM like mine is
    //you could use HitWall instead
    simulated event HitWall(vector HitNormal, Actor Wall, PrimitiveComponent WallComp)
    {
    local KActorFromStatic NewKActor;
    local StaticMeshComponent HitStaticMesh;
    	
    //do not explode on the actor who fired this projectile
    if (Wall == instigator) {
    		
    	Destroy();
    	return;
    }
    	
    //Critter
    else if (Wall.isA('Critter')) {
    			
    	//if (critter(wall).hasShield) {
    	        
           //defaulting to always showing the shield graphic for testing
    	spawnShieldEffect(Location, HitNormal,Critter(Wall));
    		
    	//}
    	//else 
    	//Explode(Location, HitNormal);
    	//Critter(Wall).returnToInfinite();
    					
    	//remove the projectile
    	Destroy();
    
    	return;
      }
    	
      //for use with kactors, use ApexDefaultParameters for apex
      MomentumTransfer = 1.0;
    
      TriggerEventClass(class'SeqEvent_HitWall', Wall);
    	
      if ( Wall.bWorldGeometry )
      {
        HitStaticMesh = StaticMeshComponent(WallComp);
        if ( (HitStaticMesh != None) && HitStaticMesh.CanBecomeDynamic() )
      {
         NewKActor = class'KActorFromStatic'.Static.MakeDynamic(HitStaticMesh);
         if ( NewKActor != None )
    	{
    	   Wall = NewKActor;
    	}
      }
    }
       ImpactedActor = Wall;
       if ( !Wall.bStatic && (DamageRadius == 0) )
    	{
    	Wall.TakeDamage( Damage, InstigatorController, Location, 
                MomentumTransfer * Normal(Velocity), MyDamageType,, self);
    	}
    
    	ImpactedActor = None;
    	
    }

    Remember you can spawn your custom projectile using:

    Code:
    function Projectile fire(){
      // Spawn projectile
      local Projectile SpawnedProjectile;
     
      SpawnedProjectile = Spawn(class'JoyProjectile',,, player.Location); 
      //pseudo code, replace with your location var 
      if( SpawnedProjectile != None && !SpawnedProjectile.bDeleteMe )
      {
        JoyProjectile(SpawnedProjectile).JoyInit( Self.Rotation,joyBall);
        JoyProjectile.InstigatorController = Self; 
         //assuming code is in your controller class
         //fires projectile in direction of player camera.
      }
    
      return SpawnedProjectile;
    }
    and in your projectile class:

    Code:
    function joyInit(vector Direction) {
    	
    	local vector v;
    	
    	//drawscale adjust
            // you can use this to resize your weapon projectile
    	v.x = 2;
    	v.y = 2;
    	v.z = 4;
    		
    	Init(Direction);
    	
    	//"IT WORKS!!! ASSYMETIC DRAW SCALE!"
            //I was quite pleased when I figured this out
    	SetDrawScale3D(v);
    	
    }

    Compile your code, shoot your enemy critter with your custom projectile, and enjoy!

    Now you know how to spawn projectile/explosion particlesystem effects that you create in the UDK, and connect them to actors and have them stick onto your actors! With 3D mesh shapes!


    Let me know if you enjoy this walkthrough!



    Rama

    PS:

    If something is not working

    make sure you saved your package via the udk!

    #2
    Hey Rama you know what stuns me is that you aren't working for epic games you should apply since you have a helpful post everywhere here.

    Comment


      #3
      Aww thanks

      Well guess what my next new tutorial is almost done!

      Using Tethers / Grapple Hooks with Skeletal Mesh Actors!



      Rama

      Comment


        #4
        Rama, could you please include source files for this?

        Mainly because I want to see how you set up your controller class correctly.

        Comment


          #5
          what is your question exactly?

          I dont use the controller class in this tutorial so what specifically are you wanting to know?

          Rama

          Comment

          Working...
          X