About a year ago I’ve bought PS4 to play the newest installment of one of my belowed franchises – inFamous: Second Son. I was stunned by the effects the Sucker Punch team made to represent various powers of Delsin (the main character). One of the best for me was the Neon power, the run as well as the absorbtion. Last year at GDC Matt Vainio (technical director) talked about the effects in inFamous SS and how they did it (you should look it up, there’s a ton of useful information). In my free time I wanted to mimic the particle effect from neon run power in Unity3D but to be scalable also for mobiles (so not using DX11 just regular ParticleSystem).
Looking at the reference image of this effect (Neon run reference) you can see that particles are being spawned accordingly to Delsins body creating its shape. It is done by placing them at vertices and spawning them after some distances to make it look like the character is leaving ‚body shape memories’. Of course the effect is addinionaly composed from so called ribbons (trails) not only for movement flow but also representing together with particles body volume (on the reference it can be seen on the shape right behind Delsin) and I won’t cover that since I’m only focusing on particles.
Edit: As Michal Piatek mentioned in the comments section there's also planar intersection effect added on character. To know more about it scroll down and check out links Michal provided.
I’ve started by creating ParticleSystem and a script that will handle them. According to Unity’s documentation you can GetParticles() on the system to ‚pull’ the particles array of particles that are alive, manipulate them and then use SetParticles() to apply these changes to ParticleSystem.
Hint: Remember to use ParticleSystem.Particle not Particle itself since it belongs to outdated ParticleEmitter!
I think that properly getting particles was the hardest part to figure it out. Since particle manipulation is done from script, emission on ParticleSystem have to be disabled. This is very important and otherwise it will not work. First I needed of course to get ParticleSystem component and create array of particles.
The amount of particles and frames to generate can be set from script that means the total amount of particles one frame will be created of will be just: particlesCount / frames. It’s therefore convinient when it comes to scale it down for mobiles.
I’m doing my calculation in LateUpdate so just before scene rendering update and of course only if the object moved above the given distance to spawn another shape. First of all I use Emit() method on ParticleSystem and emit all particles, then pull the array using mentioned method GetParticles().
Next I take the total number of vertices the mesh has and calculate the step I will traverse vertices to spread particles evenly (which has to greater or equal 1). During for loop I’m traversing particles from the current frame and place them at vertices positions and set their lifetime. After that I use SetParticles() method. That’s it (the basics of course).
Of course it will look ordinary, so I’ve added few tweaks here and there to make it look like this:
Particles at vertices
First of all I’ve changed particles lifetime to iterated value from deltaTime (calculated according to spawn cycle) to 0 by a given step. That way I’ve achieved a frame-like and not so smooth disappearing effect on particles which I think looks very much better. Next I’ve added lights at spawns (later on I additionally scaled down their intensity so it looked like less particles produced less light).
One thing that could make this system better is to place particles more evenly, because characters head usually have greater density of vertices it will therefore have more particles spawned in one area which will not look good.
What about skinned mesh?
Of course it can be used on animated objects, the one difference is that you have to create your own Mesh object and during update use Bake() method on Skinned Mesh Renderer. That way proper vertex positions according to animation frame are obtained. The result using Unitys standard assets can be observed below:
I’ve tested the Sphere version first (so the static mesh). The best performance I’ve got using of course vertex lighting and it was about 80-90FPS. The version using pixel lights was almost 2x slower. This was done using forward rendering (deferred killed the performance giving around 15FPS).
I did the same using Unity demo scene and SkinnedMeshRenderer. The scene itself (without my effect) run on my device at ~45FPS. Using 2500 particles, pixel lights and nice fading transitions during run it dropped down to ~20FPS. Using 500 particles and vertex lights I’ve achieved ~35FPS which is not so bad. Properties can be optimized here and there to find a sweet spot for your game, or adjust it according to quality settings.
Of course properties of ParticleSystem can be used accordingly like color over lifetime, forces or collision. Combining those effects could produce some amazing effects. Just a simple tweak using collision and force that is applied over lifetime can be seen here. The shape starts standing still and then random particles drop down and bounce of a floor.
I think I’ve succesfully managed to create neon run effect from inFamous in Unity. Of course it can be made better (visual wise and performance wise), however I wanted to show that using the basic ParticleSystem in Unity each Particle can be fully controlled from script to produce some interesting effects.
You can download the script used in above exampleshere.