22
\$\begingroup\$

Im currently attempting to make a firefly effect on a dark forest. The level has very low light and the player is one of the few light sources. To let the player see the level better, I am attempting to making glowing fireflies appear randomly on the map. One way is to use a particle system. But I cant make the particles cast light one the surroundings. Is there a way to do this?

\$\endgroup\$
  • 3
    \$\begingroup\$ The real issue here is that "light is expensive." You might be better off placing some fixed point lights that light up the area sufficiently, bake the lights into a lightmap, then use the particles to explain where the light source is coming from, rather than using dozens of horribly expensive dynamic lights. \$\endgroup\$ – Draco18s Dec 21 '15 at 16:00
  • \$\begingroup\$ @Draco18s There is not gonna be dozens of fireflies. They are only going to appear within the view of the player. It is top down and as such easy to control. And at any given time there should only be less than 10 fireflies. I dont suppose 10 dynamic point light is expensive? \$\endgroup\$ – DarkDestry Dec 21 '15 at 16:06
  • \$\begingroup\$ By default, Unity lets only two active dynamic lights illuminate geometry at a time (although it may be different for a 2D setup). You can increase this, of course, but keep in mind that +1 light is x2 impact on draw calls. \$\endgroup\$ – Draco18s Dec 21 '15 at 16:19
  • 2
    \$\begingroup\$ @Draco18s this may be true of the forward rendering path, but as stated in the docs "When using Deferred Shading, there is no limit on the number of lights that can affect an object" - Many small lights that affect only a small portion of the screen is exactly the kind of use case deferred rendering paths excel at handling efficiently. (At a typical cost of one draw call per unique light, rather than a multiplier as with forward rendering) \$\endgroup\$ – DMGregory Dec 21 '15 at 17:05
  • \$\begingroup\$ That's a good point. I forget about the different rendering paths most of the time. \$\endgroup\$ – Draco18s Dec 21 '15 at 17:11
31
\$\begingroup\$

Heads-Up:

This answer is outdated. Unity now supports point light particles natively. Please see this answer for full details.

I'll leave post this here for anyone curious, or using old versions of Unity, or needing more manual control than the native method offers - just note that the native support is likely to be much more efficient and scalable than the approach presented below.


I'm not sure why so many answers claim this is difficult or impossible. Handling a few dozen dynamic point lights is pretty conventional for a modern deferred rendering pipeline running on PC.

Here's a quick example I cooked up: Example of fireflies with lights

I use this script to dynamically spawn enough lights for my max particles (make sure you adjust your Particle System settings so the max is reasonable - the default of 1000 will not make your graphics card very happy), and then updates them to follow the active particles:

[RequireComponent(typeof(ParticleSystem))]
public class ParticleLights : MonoBehaviour {

    public Light lightPrefab;

    ParticleSystem _system;
    ParticleSystem.Particle[] _particles;
    Light[] _lights;


    void Start () {
        _system = GetComponent<ParticleSystem>();
        _particles = new ParticleSystem.Particle[_system.maxParticles];

        _lights = new Light[_system.maxParticles];
        for(int i = 0; i < _lights.Length; i++)
        {
            _lights[i] = (Light)Instantiate(lightPrefab);
            _lights[i].transform.parent = transform;
        }
    }

    void Update () {

        int count = _system.GetParticles(_particles);
        for(int i = 0; i < count; i++)
        {
            _lights[i].gameObject.SetActive(true);
            _lights[i].transform.localPosition = _particles[i].position;

            // Looks like the GetCurrentColor function was added in 5.3.
            // You can use other methods in earlier Unity versions.
            _lights[i].color = _particles[i].GetCurrentColor(_system);
        }

        for (int i = count; i < _particles.Length; i++)
        {
            _lights[i].gameObject.SetActive(false);
        }
    }
}

Edit: you can create a prefab by first creating a game object (in this case, Create -> Light -> Point Light), setting it up with the name/parameters/scripts/children you want, then dragging it from your Hierarchy into your Project explorer. This saves the object as an asset you can reuse across multiple scenes & scripts, with a degree of inheritance. You can delete the copy in your scene and the asset will remain in your Assets folder to be referenced when needed.

Make sure the lightPrefab has a relatively small range and is not shadowcasting, to give you the most performance headroom for everything going on in your scene. You don't need to make the lightPrefab itself green (or the colour of your fireflies) - it will pick it up from the particles' colour.

You might find though that you have better control over the fireflies' flight if you make each one its own GameObject, with a billboarded quad and a light attached with a custom movement/blinkig script, since getting a convincing wander takes more particle system artistry than I know. ;)

\$\endgroup\$
  • \$\begingroup\$ Actually... although I said not to use shadowcasting for the fireflies, I just tried turning it on in my example scene and it didn't cause any problems. The way the shadows swing around as the fireflies pass objects is really cool, and could add to a spooky atmosphere. Your mileage may vary based on the complexity of your scene and your target hardware, so profile to be sure, but this might be a case of premature optimization on my part. :) \$\endgroup\$ – DMGregory Dec 21 '15 at 18:20
  • \$\begingroup\$ How do you create a light prefab? \$\endgroup\$ – DarkDestry Dec 21 '15 at 22:54
  • \$\begingroup\$ Also, for some reason, ParticleSystem.Particle refers to the legacy particle. There isnt a GetCurrentColor or GetCurrentSize method for it. \$\endgroup\$ – DarkDestry Dec 21 '15 at 23:19
  • \$\begingroup\$ @DarkDestry I've added a note to the answer about creating prefabs. As for the missing functions, this could be a version issue - I'm working in 5.3, in earlier versions of Unity you might do this a different way. Let's discuss implementation details in chat, using the room Hamza Hasan kindly created. \$\endgroup\$ – DMGregory Dec 21 '15 at 23:47
  • \$\begingroup\$ So a light prefab is the same as a normal prefab. Was confused when it is mentioned as a light prefab. \$\endgroup\$ – DarkDestry Dec 21 '15 at 23:53
6
\$\begingroup\$

Light emiting particles is now a built in Unity feature in 5.5.

Simply enable Lights in the particle inspector, throw in a reference to a light prefab (both point and spot lights work), and change the Ratio to 1.

enter image description here

And voilà, particles that emit lights: ![enter image description here

Turns out, this is a rather optimized setup, running at 1500+fps on my rig even with maximum lights in the hundreds.

Edit: After some observation, it seem to me that the particle lights toggle between per fragment lighting and vertex lighting (presumably for optimization?). This might produce small amounts of visual artifacts if maximum lights is set too high.

Edit2: As pointed out by DMGregory, the artifacts are a byproduct of forward rendering optimizations. Deferred lighting solves the issue. Added nicer gif

\$\endgroup\$
  • 1
    \$\begingroup\$ That's good news! :) This answer would be even better if it included some step-by-step instructions for how to set this up with the new particle system features. \$\endgroup\$ – DMGregory Sep 29 '16 at 16:33
  • 1
    \$\begingroup\$ The vertex lighting behaviour you're seeing sounds a bit like some of the optimisations Unity applies in forward rendering. Do you see the same behaviour when you use the deferred path? \$\endgroup\$ – DMGregory Sep 30 '16 at 14:04
  • \$\begingroup\$ You're right! The artifacts are no longer present when using the deferred rendering path. \$\endgroup\$ – eclmist Sep 30 '16 at 14:20
3
\$\begingroup\$

Years ago, before dynamic lights were affordable, we would simply use a 2D-billboarded particle effect with additive blending. It would brighten the scene towards white. By drawing it with the correct depth of the firefly, you get almost correct sorting. Additive alpha doesn't need sorting when overdrawing itself compared to alpha blending. It won't light up ALL the scene, but it will light up the area surrounding the firefly. You could then take a dynamic light and pick one of the fireflies every few seconds to actually light the scene, if you need it.

There's a question & answer already about glow effects How to achieve lighting like this in Unity for 2D games?

\$\endgroup\$
0
\$\begingroup\$

Unfortunately, I've not had much experience with Unity in it's current form (I toyed around with it many years ago), so I don't know exactly what feature sets you have to work with in the engine.

In any case, no matter what engine you work with, dynamic lights are something to avoid whenever you can. They are very computationally expensive, and tend to add scene complexity in a very exponential way. However, as is the order of the day for most 3D rendering, there are many ways you can achieve similar effects by cheating;

A possible way to achieve a similar effect is to map a premade glow texture to the terrain below your fireflies, (assuming a Y = up/down coord. system) with X and Z positions controlling location of the glow on the terrain and Y offset from the terrain controlling the texture's alpha (brighter = closer to terrain)

There are of course several drawbacks to this method. You won't cast shadows as no light is used, and you won't affect any other geometry in the world (props, foliage, etc)

\$\endgroup\$
-1
\$\begingroup\$

Use Light at the origin of fire and play with its size in script so it will give effect of burning. And use your particle system :)

\$\endgroup\$
  • \$\begingroup\$ Theres no fire in the scene. Im having scarce particles appear in and out of existance. Theres no fixed position for the particles at all. Please read the question. \$\endgroup\$ – DarkDestry Dec 21 '15 at 16:05
  • \$\begingroup\$ So, what is the deal? you can attach light to your particle prefab rather then at pre defined positions \$\endgroup\$ – Hamza Hasan Dec 21 '15 at 16:09
  • \$\begingroup\$ The question is how to do this. I am using unity's particle system. And i dont see a prefab there. Unless you are asking me to just create a prefab that has a light and generate base on script \$\endgroup\$ – DarkDestry Dec 21 '15 at 16:10
  • \$\begingroup\$ So you have particle gameObject in the scene. Attach a light to same game object and make prefab of it by dragging that gameObject to Unity File Explorer. \$\endgroup\$ – Hamza Hasan Dec 21 '15 at 16:12
  • \$\begingroup\$ I have a Particle System gameObject in the scene. Not a particle. \$\endgroup\$ – DarkDestry Dec 21 '15 at 16:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.