BASIC TELEPORTING QUEST: ‘Blink World Light’ - Solutions

Feel free to share your solutions, ideas and creations below. If you get stuck, you can find some ideas here for completing this challenge.

For my blinking light I just had a secondary directional light left disabled with default values that i’d just flick on and off with a co-routine. (I was using the primary one to set a lighting tint to the darkness :stuck_out_tongue:

1 Like

I got stuck for a few hours on this one but it works now! finally!

My coroutine kept getting interrupted by the DeactivateObject(); bit so i used an invoke on that last bit.

I always thought that a coroutine made all other bits of the code stop/pause until the coroutine was done. I guess I was wrong there.

I ended up writing a Game Controller script and dropping it on the Gameplay object. This let me better control elements that weren’t specific to the teleporters. This let me adjust the last challenge so that I could designate the “First Teleporter” and make it glow without breaking up the prefab.

Specific to this challenge:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GameController : MonoBehaviour {

    [SerializeField] Teleport FirstTeleportPad;
    [SerializeField] Light worldLight;
    [SerializeField] Light dimLight; // Ignore me, I want to be able to see the editor but make the game pitch black otherwise

    void Start()
    {
        FirstTeleportPad.Initialize();
        StartCoroutine ("BlinkWorldLight");
        dimLight.enabled = false; 
    }

    void Update()
    {
                
    }

    IEnumerator BlinkWorldLight()
    {
		while (true)
		{
            if (worldLight.enabled)
			{
                yield return new WaitForSeconds(1);
            }
			else
			{
                yield return new WaitForSeconds(3);
            }
            worldLight.enabled = !worldLight.enabled;
        }

    }
}

2 Likes

I activated the teleport script on both teleporters so the start() method is called. Each has one of the directional lights hooked up.
At the start I turn off all lights, then start the coroutines to blink them on for a couple of seconds (adjustable per SerializedField).

Here are the adjustments I made:

    [SerializeField] float worldLightBlinkTime = 5f;

    void Start() 
    {
        mainWorldLight.enabled = false;
        areaLight.enabled = false;
        StartCoroutine(nameof(BlinkWorldLight));
    }

    IEnumerator BlinkWorldLight()
    {
        mainWorldLight.enabled = true;
        yield return new WaitForSeconds(worldLightBlinkTime);
        mainWorldLight.enabled = false;
    }
2 Likes
    IEnumerator BlinkWorldLight(float timer)
    {
        mainWorldLight.enabled = true;
        yield return new WaitForSecondsRealtime(timer);
        mainWorldLight.enabled = false;

    }
3 Likes

I also used a coroutine, but i added variables for the amountToBlink and durationToBlink

    [SerializeField] private int amountToBlink = 24;
    [SerializeField] private float durationToBlinkOn = .1f;
    [SerializeField] private float durationToBlinkOff = .05f;
    IEnumerator BlinkWorldLight()
    {
        mainWorldLight.enabled = false;

        for (var i = 0; i < amountToBlink; i++)
        {
            mainWorldLight.enabled = true;
            yield return new WaitForSeconds(durationToBlinkOn);
            mainWorldLight.enabled = false;
            yield return new WaitForSeconds(durationToBlinkOff);
        }
    }
1 Like

I used something similar to one of the other ones here. Only because I got stuck trying to get it to work the Unity Scripting API was a little confusing.

  [SerializeField] Light mainWorldLight;
  [SerializeField] float worldlightBlinkTime = 3;
   void Start() 
    {
        StartCoroutine(BlinkWorldLight());
    }
void TeleportPlayer(Collider other)
    {
        if(player || hasTriggered == false)
        {
            player.transform.position = teleportTarget.position;
            IlluminateArea();
            StartCoroutine(BlinkWorldLight());
            DeactivateObject();
        }
    }
 IEnumerator BlinkWorldLight()
    {
        yield return new WaitForSeconds(worldlightBlinkTime);
        mainWorldLight.enabled = true;
        yield return new WaitForSeconds(worldlightBlinkTime);
        mainWorldLight.enabled = false;
    }
1 Like

Nice

Nice and clear code :slight_smile:

Welcome

Thats what this is all about having fun learning :slight_smile:

Co-routines are great for many things! Spawners, flashing lights and running things for a period of time.

Kurt

I implemented a paradigm very similar to @DGR_Dev.

Added properties for blink rate and number of blinks to Teleport:

[Range(2, 10)] [SerializeField] int LightBlinkCount = 3;
[Range(0.1f, 2f)] [SerializeField] float LightBlinkRate = 0.5f;

Took care of initial light states in Teleport :: Start():

        if (!AreaLight || !MainWorldLight) return;
        if (AreaLight.enabled)
            AreaLight.enabled = false;
        if (MainWorldLight.enabled)
            MainWorldLight.enabled = false;

Then implemented the desired light blinking in Teleport :: BlinkWorldLight():

    IEnumerator BlinkWorldLight()
    {
        if (!MainWorldLight)
            yield return null;

        var numBlinks = LightBlinkCount > 2 && LightBlinkCount % 2 == 0 ? -1 : 0;
        do
        {
              MainWorldLight.enabled = !MainWorldLight.enabled;
              yield return new WaitForSeconds(LightBlinkRate);
        } while (numBlinks++ <= LightBlinkCount);

        MainWorldLight.enabled = false;
    }

The modulo arithmetic used in the initial value assignment of the local counter variable numBlinks properly reconciles an odd or even LightBlinkCount property setting with the fact that a “blink” consists of the light being turned on and then off.