Intended action only happens on final object in my foreach loop

Hello all,

For an facetracking AR game I’m working on, I created a “manual” raycast if you will; Picture a long (invisible) collider sticking out from your nose that makes contact with 6 squares (buttons, for all intents and purposes) in a 2D UI menu. These 6 buttons sit underneath a larger rectangular slot; the intent being that the 6 buttons act as a “remote control” that changes whatever currently showing on the “TV” above. When the protruding beam makes prolonged contact with any square, its outline is enabled and a radial wipe begins on the large rectangular slot.

All my collider stuff works fine.

However, I noticed that the radial wipe only plays when I make contact with the last item in the squares array (in this case, Tile 6), and need help figuring out why.

Here is [most of] my code. Lines 60-64 are my radial wipe. Editor screenshots are included below.

[SerializeField]
    private float requiredHoldTime;

    public UnityEvent onLongClick;

    //[SerializeField]
    //public Image[] fillImage;
    public Image[] fillImages;


    void Start () {

    }
   
    void Update()
    {
        //RaycastHit theHit;

        if (Physics.Raycast(transform.position, transform.TransformDirection(Vector3.forward), out theHit))
        {
            for (int i = 0; i < 7; i++)
                if (pointerTarget.name == (string)theHit.collider.gameObject.name)
                {
                    tiles2[i].GetComponent<Outline>().enabled = true;
                }
                else{
                    tiles2[i].GetComponent<Outline>().enabled = false;

                }
        }

        // if outline is on, pointerDown is true
        for (int i = 0; i < 7; i++)
        {
            if (tiles2[i].GetComponent<Outline>().enabled == true)
            {
                pointerDown = true;
                Debug.Log("pointerDown = true");
            }
            else if (tiles2[i].GetComponent<Outline>().enabled == false)
            {
                pointerDown = false;
                Debug.Log("pointerDown = false");
            }

        }


        if (pointerDown)
        {
            pointerDownTimer += Time.deltaTime;
            if (pointerDownTimer >= requiredHoldTime)
            {
                if (onLongClick != null)
                    onLongClick.Invoke();

                Reset();
            }

            //radial wipe - seems to only affect the very last square in the array
            foreach (Image image in fillImages)
            {
                image.fillAmount = pointerDownTimer / requiredHoldTime;
            }

        } else if (!pointerDown) {
            Reset();
        }
           

    }

    private void Reset()
    {
        pointerDown = false;
        pointerDownTimer = 0;

        foreach (Image image in fillImages)
        {
            image.fillAmount = pointerDownTimer / requiredHoldTime;
        }
    }

Here is a screenshot of what happens when Button 6 is highlighted, which is intended:


Here, Buttons 1-5 do not activate the radial wipe:

Here is the Inspector:

Thank you to anyone who has time to offer any insight on this!

        for (int i = 0; i < 7; i++)
        {
            if (tiles2[i].GetComponent<Outline>().enabled == true)
            {
                pointerDown = true;
                Debug.Log("pointerDown = true");
            }
            else if (tiles2[i].GetComponent<Outline>().enabled == false)
            {
                pointerDown = false;
                Debug.Log("pointerDown = false");
            }
        }

This is where the mistake is.
Lets assume you hit tile 1 (or any other tile than the last one):
First time it enters, tiles2[0].enabled = true… so it sets pointerDown to true and then continues on to the next tile. tiles2[1].enabled = false … so it sets pointerDown to false now. Your debuglog will probably show something like true, false, false, false, false, false.
If you change the above code to the code below, you will not overwrite pointerdown anymore after it’s set to true:

        for (int i = 0; i < 7 && !pointerDown; i++)
        {
            if (tiles2[i].GetComponent<Outline>().enabled == true)
            {
                pointerDown = true;
                Debug.Log("pointerDown = true");
            }
            else if (tiles2[i].GetComponent<Outline>().enabled == false)
            {
                pointerDown = false;
                Debug.Log("pointerDown = false");
            }
        }
2 Likes

Thank you, AlexN2805!

That worked like a charm :slight_smile: