So, I allow the player to place buildings in my game. Once they have clicked and decided on a spot for the building, I would like to confirm that they actually want the building there, since there is no deleting buildings in my game.
I want a simple “yes/cancel” confirmation dialog to pop up, only problem is, I’m not sure how I should run all the methods I want to once the player has pressed a button on the confirmation box.
By that I mean, I have all the methods and variables in the Script attached to the Building I’m placing, and once I click, this method runs:
GameObject placedObject = Instantiate(finalObject, transform.position, Quaternion.identity); //Instantiate the final version of the Object
gameObject.SetActive(false); //deactivate the placement version of the Object
//CREATE CONFIRMATION BOX
//if press "yes", use up the resource cost, Destroy the placement version of the object and continue
//if press "cancel", Destroy "placedObject" and re-activate the placement version of the object and repeat process
All the methods and variables I want to access when the player presses a button on the confirmation box is in the “Placement Object”-Script where I create the confirmation box from, how do I access these from a Script attached to the confirmation box object? Or do I create some sort of callback? not sure what the best approach is for this.
Why not use a subscriber pattern? Create the gameObject as you have then do
var dialog = placedObject.GetComponent();
dialog.onResult += MethodToHandleResult;
using Unity’s UI have the buttons OnClick point to Dialog->OnResult and then put an int to represent the resulting confirmation code. 0 could be No/Cancel 1 could be Yes/Ok.
using UnityEngine;
public class Dialog : MonoBehaviour {
public System.Action<int> onResult = (result) => {
Debug.Log("Result: " + result);
};
public void OnResult(int result) {
this.onResult(result);
}
}
If you have an enum that holds all possible results then you can cast the int to your enum that would also work then just edit the System.Action and it will work the same.
Hmm, am I missing something? The debugs are not being printed.
IEnumerator ShowConfirmationDialog()
{
// whatever you're doing now with the temporary / placement preview building
ConfirmationDialog dialog = Instantiate(confirmationDialog, canvas.transform); // instantiate the UI dialog box
while (dialog.result == dialog.NONE)
yield return null; // wait
if (dialog.result == dialog.YES)
{
// place the real building
Debug.Log("Yes");
}
else if (dialog.result == dialog.CANCEL)
{
// remove the temporary / preview building
Debug.Log("Cancel");
}
My ConfirmationBox Script:
public class ConfirmationDialog : MonoBehaviour
{
[HideInInspector]
public int NONE = 0, YES = 1, CANCEL = 2;
[HideInInspector]
public int result = 0;
private void Start()
{
Button yesBtn = transform.GetChild(1).gameObject.GetComponent<Button>();
yesBtn.onClick.AddListener(OnYesBtnPressed);
Button cancelBtn = transform.GetChild(2).gameObject.GetComponent<Button>();
cancelBtn.onClick.AddListener(OnCancelBtnPressed);
}
public void OnYesBtnPressed()
{
result = YES;
//if I debug here it prints
}
public void OnCancelBtnPressed()
{
result = CANCEL;
}
}
public class Builder : MonoBehaviour
{
public ConfirmationDialog confirmationDialog;
public Canvas canvas;
private Coroutine coroutine;
private void Start()
{
coroutine = null;
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.Space) == true)
{
if (coroutine == null)
{
coroutine = StartCoroutine(ShowConfirmationDialog());
}
}
}
IEnumerator ShowConfirmationDialog()
{
// whatever you're doing now with the temporary / placement preview building
ConfirmationDialog dialog = Instantiate(confirmationDialog, canvas.transform); // instantiate the UI dialog box
while (dialog.result == dialog.NONE)
{
Debug.Log("Builder.ShowConfirmationDialog() - Yielding");
yield return null; // wait
}
if (dialog.result == dialog.YES)
{
// place the real building
Debug.Log("Builder.ShowConfirmationDialog(): Yes");
}
else if (dialog.result == dialog.CANCEL)
{
// remove the temporary / preview building
Debug.Log("Builder.ShowConfirmationDialog(): Cancel");
}
Destroy(dialog.gameObject);
coroutine = null;
}
}
Are you sure you’re not missing something in regards to starting the coroutine, or starting it multiple times, or keeping the object that it’s running on active or anything like that?
After adding your debugs I can see that my Coroutine only prints “Builder.ShowConfirmationDialog() - Yielding” Once, then nothing else happens. I’m fairly certain its started the proper way:
coroutine = StartCoroutine(ShowConfirmationDialog()); //called once when building is placed
EDIT: Found the culprit: “Coroutines are run on the GameObject that had the script that called StartCoroutine.”