In two of my small projects I wanted to create some muzzle flashes for guns and i hate hand animating everything so i wanted a solution to do this automatically for me.
What I did was I parented a directional emitter to a specific joint, namely the hand of the character and made it directional. You will have to do just a little tweaking to get the emitter to point straight but once its done that's all for that.
So once you've done, setup your emitter rate. Your emitter rate is how many particles per second you want to emit, so 30 will give you 1 particle per 1 frame. So given that, let's say that your weapon of choice does 600 rounds per minute. 600 rounds per minute / 60 minutes = 10 rounds per second / 30 frames per second = 1 particle every 3 frames.. see how that works out? So 10 is what you would put in for your emitter rate. This will serve as your bullet or round. You want to set your speed up correctly because this is what we'll use to setup and create our muzzle flash. Now even though your scene is set to cm, its actually...meters.
Now you can hit play, but regardless of what it looks like, we're not done because those particles aren't going to go in the direction you want to yet. Expressions is how we will achieve the second part, and this is the meat and potatoes of this whole plate of food...
This first set of MEL will grab the direction and velocity of your bullet and create your muzzle flash
This goes into the creation expression of the bullet emitter, we are creating our muzzle flash from this
Code:
//get the location of the barrel emitter with xform //using tx will not work since you parent the emitter //to the weapon, parenting the emitter to the weapon //makes all translate in localspace 0 float $eLoc[3] = `xform -ws -q -t LH_LB_Emitter`; float $eLocX = $eLoc[0]; float $eLocY = $eLoc[1]; float $eLocZ = $eLoc[2]; //assign the emit command to a string string $emitCmd1 = ("emit -o LH_LB_MuzzleFlash \n"); string $emitCmd2 = ("emit -o LH_LB_MuzzleFlash \n"); //get a random count of how many particles for each command //you want to emit int $emitCount1 = rand(1500, 2500); //the start position for each particle is at the //location of the emitter in worldspace for($i = 0; $i < $emitCount1; $i++) { $emitCmd1 += " -pos " + $eLocX + " " + $eLocY + " " + $eLocZ + "\n"; $emitCmd2 += " -pos " + $eLocX + " " + $eLocY + " " + $eLocZ + "\n"; } //apply attribute velocity $emitCmd1 += " -at velocity\n"; $emitCmd2 += " -at velocity\n"; //give each particle their initial velocity //the sphrand function is used to give each a //general velocity, to get a bigger muzzle flash //adjust the rand(0, ##) higher 0 to whatever //You will need to adjust the divmod on the sparkShape //to get the desired muzzle flash effect, both go //hand in hand for($i = 0; $i < $emitCount1; $i++) { vector $randVel1 = sphrand(rand(0, 50)); vector $randVel2 = sphrand(rand(0, 15)); float $ranVelX = $randVel1.x; float $ranVelY = $randVel1.y; float $ranVelZ = $randVel1.z; $emitCmd1 += " -vv " + $ranVelX + " " + $ranVelY + " " + $ranVelZ + "\n"; $emitCmd2 += " -vv " + $randVel2.x + " " + $randVel2.y + " " + clamp(0, 30, $ranVelZ) + "\n"; } //set a random lifespan for each particle //adjust according to get the desired effect $emitCmd1 += " -at lifespanPP\n"; $emitCmd2 += " -at lifespanPP\n"; for($i = 0; $i < $emitCount1; $i++) { float $randls = rand(0, .025); $emitCmd1 += " -fv " + $randls + "\n"; $emitCmd2 += " -fv " + $randls + "\n"; } eval($emitCmd1); eval($emitCmd2);
For testing, lower the emit counter at the top to 150, 200
you'll also notice I have 2 emitCmd variables.. 1 is for the base of the muzzle flash and the other is for closer to the emitter, which is the clamped value.
So simply put, the above states, when we create our bullet particle, create the muzzle flash...
Once this has been created, now we need to shape our particles correctly...
This goes in the creation expression of the 2nd set of particles
Code:
vector $bulletVel = LH_LB_ParticlesShape.velocity; vector $muzFlVel = LH_LB_MuzzleFlashShape.velocity; int $partID = LH_LB_MuzzleFlashShape.particleId; float $divMod; float $angleBullet = angle($bulletVel, $muzFlVel); //the divmod adjust the distance at which particles will travel in the direction of the bullets. //higher numbers will make the muzzle flash shorter in distance. if($partID%5 == 0) { $divMod = rand(40, 80); } else { $divMod = rand(20, 40); } //bullet velocity is multiplied by angelbullet/divmod so the muzzle flash doesn't travel the //distance of the primary particle float $newVelX = (($bulletVel.x * ($angleBullet / $divMod)) + $muzFlVel.x); float $newVelY = (($bulletVel.y * ($angleBullet / $divMod)) + $muzFlVel.y); float $newVelZ = (($bulletVel.z * ($angleBullet / $divMod)) + $muzFlVel.z); //apply the new velocity direction to the muzzleflash LH_LB_MuzzleFlashShape.velocity = <<$newVelX, $newVelY, $newVelZ>>;
If you want to go a step further and create particles for the smoke...
in your muzzle flash particle's Runtime before dynamics expression..
Code:
vector $MuzPos = LH_LB_MuzzleFlashShape.worldPosition; int $partID = LH_LB_MuzzleFlashShape.particleId; if($partID%5 == 0) { //assign the emit command to a string string $emitCmd1 = ("emit -o MuzzleSmoke \n"); //get a random count of how many particles for each command //you want to emit int $emitCount1 = rand(0, 2); //the start position for each particle is at the //location of the emitter in worldspace for($i = 0; $i < $emitCount1; $i++) { $emitCmd1 += " -pos " + $MuzPos.x + " " + $MuzPos.y + " " + $MuzPos.z + "\n"; } //apply attribute velocity $emitCmd1 += " -at velocity\n"; for($i = 0; $i < $emitCount1; $i++) { vector $randVel1 = sphrand(rand(1, 5)); float $ranVelX = $randVel1.x; float $ranVelY = $randVel1.y; float $ranVelZ = $randVel1.z; $emitCmd1 += " -vv " + $ranVelX + " " + $ranVelY + " " + $ranVelZ + "\n"; } $emitCmd1 += " -at lifespanPP\n"; for($i = 0; $i < $emitCount1; $i++) { float $randls = rand(0, .75); $emitCmd1 += " -fv " + $randls + "\n"; } eval($emitCmd1); }
Hopeully this all makes sense! Let me know if you have questions!!