Instantiate buttons

Hi! I have trouble with instantiated buttons.
How can instances access the main script they were instantiated from?
I want to determine which button is clicked.

Main.cs

public GameObject myButton; //drag & drop in Inspector
//myButton is a prefab with attached script

for(int i=0;i=10;i++){
    GameObject b= Instantiate(myButton, new Vector3(5*i,0,0), Quaternion.identity) as GameObject;  
    b.GetComponent<ButtonScript>().ID = i; //tell new button his ID
} 

ButtonScript.cs

public int ID;

void Clicked(){
    Debug.Log("Hi! I am button nr "+ID); // few drag+drops in Inspector, works fine.    
}

The problem is that I cannot access a method or field in Main.cs. This makes sense because the buttons are created in runtime. Therefore any reference with objects in the scene cannot be guaranteed. So I understand the problem, however I don’t see an elegant solution.

Can I give a reference, just as I would do in more ‘classic C#’ calling constructor-method:
button = new Button(this); (or something like it)

Any thoughts?
Thanks!

Hi @Frunobulax,
There are many ways to accomplish what you want, but easiest way might be to get Main reference in the button script like this:

ButtonScript.cs

public int ID;
private Main mainReference;
        
void Start() {
    mainReference = FindObjectofType<Main>();
}

void Clicked(){
    Debug.Log("Hi! I am button nr "+ID); // few drag+drops in Inspector, works fine.
    mainReference.anyFunction(ID);    
}

So, there you have it, you can access Main functions.

Thanks @TanselAntinel!
This will work indeed and is very practical. A bit of a drawback is the lack of encapsulation. If I would rename Main, it wouldnt work anymore. I can imagine there are different solutions that are considered good practice. Can you give another solution?

Behind my question about instances lies a deeper quest for good practice of architecture :slight_smile:

Thanks for your help, it is much appreciated!