What I want: I want the player to be able to click on instantiated objects and get points, then have those points show in the score-keeping text.
What I’ve done: I’m currently using the following “FindGameObjectsWithTag” code to retrieve the buttons that are components of the instantiated prefab objects:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
public class CPointScore : MonoBehaviour
{
public TextMeshProUGUI CPointsText;
private float ScoreNum;
private GameObject[] CButtonGmeObjsHolder;
private void CTagFinder()
{
CButtonGmeObjsHolder = GameObject.FindGameObjectsWithTag("Ctag");
foreach (GameObject CButtonGmeObj in CButtonGmeObjsHolder)
{
Debug.Log("GmeObj Found");
Button CButton = CButtonGmeObj.GetComponent<Button>();
CButton.onClick.AddListener(AddScore);
}
}
public void AddScore()
{
ScoreNum += 1;
Debug.Log("Point Added # " + ScoreNum);
}
void Start()
{
InvokeRepeating("CTagFinder", 1f, 15.1f);
}
void Update()
{
CPointsText.text = ScoreNum.ToString();
}
}
Because FindGameObjectsWithTag only calls once I have the InvokeRepeating code in start. I have game objects spawning throughout the duration of the game so it needs to be constantly checking for tags.
Issue: So the code finds the tags, the buttons are able to be clicked, and the score-keeping text updates which is great. The problem is that if I click one tagged button it will register a point for itself and every tagged button currently in the scene that spawned after it. For example, lets say I have 4 spawned objects currently on scene, when the first object spawned is clicked it will add 4 points instead of 1. If the second object spawned is clicked it will add 3 points instead of 1. I would like to have only the tagged button that is clicked register a point.
Question: What can I change in my code so that only the tagged button that is clicked registers a point?
Thank you
I think there are two things here:
FindGameObjectsWithTag
is also quite inefficientYour main issue is the repeated calling.
For each repeated call of
CTagFinder
you go through all existing buttons and doso these existing buttons end up with multiple listeners attached!
You either want to make sure it is only called once per button, e.g. keeping track of those you already did this for:
and then
or alternatively make sure you remove the callback before you add it like
In general I would not use FindGameObjectWithTag an poll objects repeatedly. Rather make your code event driven. This would already avoid the issue at all since there would be no repeated attaching of the listener anyway.
I would simply have a dedicated component
YourComponent
attached to the sameGameObject
as the buttons and have a globaland in this dedicated component do
and in your
CPointScore
listen to this event like