Hello hello dear people it’s Anna!
I am working on a piece where I have point lights with rigid bodies flying around. When they collide with certain game Objects they change color and make a sound. This already works perfectly. But now I want them to increase range and intensity over time and then go back to normal (maybe during 2 sec). For some reason it doesn’t seem to be working.
This is the code at the moment:
public float minimumIntensity = 7f;
public float maximumIntensity = 100f;
public float minimumRange = 1f;
public float maximumRange = 10f;
//starting value for lerp
//Make slider
[SerializeField]
[Range(0f, 1f)]
public float t = 0.0f;
void OnCollisionEnter(Collision collisionInfo)
{
if (collisionInfo.collider.tag == "Musicplant" || collisionInfo.collider.tag == "Plant")
{
currentColor = colorList[random.Next(0, colorList.Count - 1)];
pointLight.intensity = Mathf.Lerp(minimumIntensity, maximumIntensity, t);
pointLight.range = Mathf.Lerp(minimumRange, maximumRange, t);
//increase the t interpolater
t += 0.2f * Time.deltaTime;
Once this works, I would add this second part to decrease it again:
// now check if the interpolator has reached 1.0
// and swap maximum and minimum so game object moves
// in the opposite direction.
if (t > 1.0f)
{
float temp = maximumIntensity;
maximumIntensity = minimumIntensity;
minimumIntensity = maximumIntensity;
minimumIntensity = temp;
float tempp = maximumRange;
maximumRange = minimumRange;
minimumRange = maximumRange;
minimumRange = tempp;
t = 0.0f;
}
}
}
I think the problem lies with time.deltaTime since pointLight.intensity += 20f works
but pointLight.intensity += 20f * time.deltaTime doesn’t do anything at all.
Anybody has an idea or a solution? Thanks for reading!
The problem is that OnCollisionEnter only runs when a collision is detected, and so your code only runs when it detects a collision.
Time.deltaTime is the time since the last frame. If you do 20f * time.Delta time your result will be a single value that you then add on. This approach is correct, however you’re only doing it once when you register a collision when instead you need to do it every frame for 2 seconds.
What you want is a coroutine that executes on collision:
//We want somewhere to store the coroutine so we can stop it on another collision
Coroutine myCoroutine;
void OnCollisionEnter(Collision collisionInfo)
{
if (collisionInfo.collider.tag == "Musicplant" || collisionInfo.collider.tag == "Plant")
{
//Set the colour of the light on collision
currentColor = colorList[random.Next(0, colorList.Count - 1)];
//First we want to check for an existing coroutine. If we have one, we need to stop it!
if (myCoroutine != null)
StopCoroutine(myCoroutine);
//Then we initiate a new coroutine to run the light
myCoroutine = StartCoroutine(LightCoroutine());
}
}
IEnumerator LightCoroutine()
{
float t = 0;
while (t < 1f) //This will take 1 second
{
//T will work towards 1, giving us the maximum intensity
pointLight.intensity = Mathf.Lerp(minimumIntensity, maximumIntensity, t);
pointLight.range = Mathf.Lerp(minimumRange, maximumRange, t);
t += Time.deltaTime; //Add the time since the last frame
yield return null; //Wait for the next frame
}
while (t > 0f) //This will take 1 second
{
pointLight.intensity = Mathf.Lerp(minimumIntensity, maximumIntensity, t);
pointLight.range = Mathf.Lerp(minimumRange, maximumRange, t);
t -= Time.deltaTime; //Subtract the time since the last frame
yield return null; //Wait for the next frame
}
}
The coroutine is then called every time there is a valid collision. It will stop the old one beforehand too in case you get another collision within 2 seconds. What would happen is the coroutine will run again starting from 0!
There’s probably other approaches towards this that might be better, but I thought I would try to retain the basic logic of your code in my answer!