0
\$\begingroup\$

I am making a game where I need these black rings to appear and disappear one after another. I am in Unity 2D so what I did is simply changed their Z transform. I am also trying to run this code asynchronously so that it doesn't choke up and slow down when I am running other things in the main Update. Right now when I run the game, all the other things happen perfectly in sync but the rings don't turn on and off in sync and then after all the other game objects have stopped moving, they start blinking rapidly and chaotically. How do I fix this?

My code:

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

public class ring1 : MonoBehaviour
{
    // Start is called before the first frame update
    public GameObject ring;
    public GameObject ring2;
    public GameObject ring3;
    public GameObject ring4;
    private bool isCoroutineExecuting = false;
    async void Start()
    {
        ring.GetComponent<GameObject>();
        ring2.GetComponent<GameObject>();
        ring3.GetComponent<GameObject>();
        ring4.GetComponent<GameObject>();
    }

    // Update is called once per frame
    void Update()
    {

        
        
    }

    void FixedUpdate()
    {
        //ring.transform.position = new Vector3(ring.transform.position.x, ring.transform.position.y, 0);
        //WaitForSeconds(1);
        //ring.transform.position = new Vector3(ring.transform.position.x, ring.transform.position.y, 100);

        //print("fixed");
        StartCoroutine(ExampleCoroutine());
    }

    IEnumerator ExampleCoroutine()
    {
        //Print the time of when the function is first called.
        Debug.Log("Started Coroutine at timestamp : " + Time.time);

        ring.transform.position = new Vector3(ring.transform.position.x, ring.transform.position.y, 0);
        ring2.transform.position = new Vector3(ring2.transform.position.x, ring2.transform.position.y, 0);
        ring3.transform.position = new Vector3(ring3.transform.position.x, ring3.transform.position.y, 0);
        ring4.transform.position = new Vector3(ring4.transform.position.x, ring4.transform.position.y, 0);

        ring.transform.position = new Vector3(ring.transform.position.x, ring.transform.position.y, 100);
        yield return new WaitForSeconds(1);
        ring2.transform.position = new Vector3(ring2.transform.position.x, ring2.transform.position.y, 100);
        yield return new WaitForSeconds(1);
        ring3.transform.position = new Vector3(ring3.transform.position.x, ring3.transform.position.y, 100);
        yield return new WaitForSeconds(1);
        ring4.transform.position = new Vector3(ring4.transform.position.x, ring4.transform.position.y, 100);
        yield return new WaitForSeconds(1);

        //After we have waited 5 seconds print the time again.
        Debug.Log("Finished Coroutine at timestamp : " + Time.time);
    }
}

```
\$\endgroup\$
1
  • 1
    \$\begingroup\$ You seem to have a boolean declared that should indicate whether a coroutine is running, but you never check or set it. \$\endgroup\$
    – Weckar E.
    Nov 3 '20 at 15:56
2
\$\begingroup\$

You can simplify this code a lot.

  • You're not using threading, so using System.Threading; is unnecessary.

  • GetComponent<GameObject>() is meaningless. GameObject is not a kind of Component. You don't need to "warm up" a game object reference by calling a special method on it. It's already a valid game object reference without calling this method.

  • Your Update method is empty. If you're not using it, delete it.

  • You're starting a new copy of your Coroutine every single physics step. This is NOT what you want to do.

Here's a much simpler script that turns the rings on one after another.

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

public class RingAlternator : MonoBehaviour
{
    // If you want to do the same thing to a series of numbered variables,
    // just make an array and access them by index.
    public GameObject[] rings;

    // If we want one instance of a coroutine to fire when the object is activated,
    // we can just make the Start function a coroutine itself.
    IEnumerator Start()
    {
        // Loop this sequence forever.
        while (true) {
            // Make all rings disappear.
            foreach (var ring in rings) {
                ring.SetActive(false);
            }

            // Enable the rings one by one in order, then wait a second after each.
            foreach (var ring in rings) {
                ring.SetActive(true);
                yield return new WaitForSeconds(1);
            }
        }
    }
}
\$\endgroup\$
1
  • \$\begingroup\$ That is insanely simple and works like a charm. Thank you so much for helping! \$\endgroup\$ Nov 8 '20 at 19:27

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.