- Home /
How to implement a pulsating point light with delays in between?
Hi folks,
I'm quite new to Unity, but have a decent amount of knowledge about the basics of programming. I got along in creating a simple top-down 2D game with enemies and pick-ups, but seemd to hit my limits right now.
In theory it sounds quite simple, and maybe it is: create a pulsating point light with delays in between.
With the help of a tutorial from the official Unity site I created a pulsating light, but I simply cannot get my head around how to implement yield and WaitForSeconds. I looked online and understand the basic principle to some degree, but I have absolutely no idea how to implement it. Hope you guys can help me out and give me a basic approach to my problem. Maybe I'm simply lacking the complete overview yet.
This is my code so far for the pulsating light:
using UnityEngine;
using System.Collections;
public class LightToggle : MonoBehaviour
{
private Light myLight;
public float fadeSpeed = 2.5f;
public float highRange = 10.0f;
public float lowRange = 0.5f;
public float changeMargin = 0.2f;
public bool lightOn;
private float targetRange;
public void Awake()
{
myLight = GetComponent<Light>();
myLight.light.range = 0f;
targetRange = highRange;
lightOn = true;
}
public void Start()
{
}
public void Update()
{
if(lightOn)
{
myLight.light.range = Mathf.Lerp(myLight.light.range, targetRange, fadeSpeed * Time.deltaTime);
CheckTargetRange();
}
else
myLight.light.range = Mathf.Lerp(myLight.light.range, 0f, fadeSpeed * Time.deltaTime);
}
void CheckTargetRange ()
{
if(Mathf.Abs(targetRange - myLight.light.range) < changeMargin)
{
if(targetRange == highRange)
targetRange = lowRange;
else
targetRange = highRange;
}
}
}
UnityGems provides a good overview of Coroutines, so that's a good place to start.
Basically they are a a state machine where execution is paused and resumed according to how you yield. Unity will check the Coroutine after each Update to see if execution should be resumed... if you specify WaitForSeconds it will only resume once X seconds have passed since the yield. If you "yield return null" the coroutine will execute once per frame, up until the next yield statement.
In your case you probably want smooth pulsing so you should use "yield return null", store a timer in the coroutine that oscillates between the low and high pulse values that control your light. You can use $$anonymous$$athf.PingPong for this.
Nice, thanks for the tip. I tried PingPong as well and it worked out pretty well. $$anonymous$$aking it pulsating seems to be easy at this point, but I guess I just have to dive into Coroutines to make it work properly.^^ I will check out UnityGems!
Answer by iwaldrop · Nov 22, 2013 at 08:12 AM
I'm a big fan of keeping it simple.
using UnityEngine;
using System.Collections;
[RequireComponent(typeof(Light))]
public class PulsingLight : MonoBehaviour
{
public bool startOn;
public float maxBrightness;
public float transitionTime;
public float peakDelay;
private bool isLit;
void Awake()
{
isLit = startOn;
light.intensity = isLit ? maxBrightness : 0;
}
void OnEnable()
{
StartCoroutine(Transition(!isLit));
}
void OnDisable()
{
StopAllCoroutines();
isLit = false;
light.intensity = 0;
}
IEnumerator Transition(bool turnOn)
{
float initialBrightness = light.intensity;
float targetBrightness = turnOn ? maxBrightness : 0;
float startTime = Time.time;
float endTime = startTime + transitionTime;
while (endTime >= Time.time)
{
light.intensity = Mathf.Lerp(initialBrightness, targetBrightness, (Time.time - startTime)/transitionTime);
yield return null;
}
isLit = turnOn;
yield return new WaitForSeconds(peakDelay);
StartCoroutine(Transition(!isLit));
}
}
Tried the code, but it doesn't want to work out. ^^ Everything stays black. Did I miss something I have to do in advance?
Did you set the values in the inspector to what you want?
Answer by yatagarasu · Nov 22, 2013 at 10:31 AM
You can declare you brightness value as [SerializeField] and control it from animation.
Answer by Gruffy · Nov 24, 2013 at 12:16 AM
hey bud, I hope this helps. Gruffy 2013 using UnityEngine;
[RequireComponent(typeof(Light))]
public class Light_Fader : MonoBehaviour
{
public float minIntensity = 0.0f;
public float maxIntensity = 5.0f;
public float multiplier = 2.0f;
//public float minFlickerSpeed = 1f;
//public float maxFlickerSpeed = 400f;
float random;
void Start()
{
random = Random.Range(0.0f, 65535.0f);
}
void LateUpdate()
{
float noise = Mathf.PerlinNoise(random, Time.time * multiplier);
light.intensity = Mathf.Lerp(minIntensity, maxIntensity, noise);
}
}
It doesnt look like you really need explaining to
I'm quite new to Unity, but have a decent amount of knowledge about the basics of programming
but, this simply takes in a min and max value, creates a perlin noise float value from them and passes this to the light intensity. it updates and changes to produce a random like glow/intensity change. Hope you like it gruffy 2013
hey bud, not to push you or anything, but if you look above this comment. I have given you a pretty succinct and optimized answer.
If you attach script to a gameobject and face your camera towards that gameobject whilst in play mode, you will see it do exactly as you wished.. Just saying really. I mean in fairness other have answered this for you too, $$anonymous$$e just does it in 23 easy to read lines of code. :)
In agreeance with what iwaldrop said
I'm a big fan of keeping it simple.
I say optimized...
float noise
could go into declerations i suppose aswell, but hey ho :)
Although I really like your solution, it doesn't provide for delays in between the pulses, which is what the OP was looking for.
ah ha, good point @iwaldrop my man.. I stand corrected! $$anonymous$$y pragmatic side crept out and somehow reduced scope to create an organic like fade in and out of the light (hence, use of the perlin wrapper - a handy knowledge piece, I hope atleast) which occurs as a rule not an option.
This script could be rectified to include a conditional or indeed through use of a conditionally fired coroutine. However, iwaldrop is right, his answer is the more succinct in carrying out a controllable light out of the box type thing.
I wonder, is he trying to make a flashlight with a problematic battery mechanic or something like a light switch for an unreliable set of lights in a room? Always interests me that :) Apologies for any controversy there mr iwaldrop. Gruffy
No apologies necessary! I quite liked your solution, even if only slightly off the mark. :)