Issue auto-clicking a button on start()

Hi, everyone! I have a rather unique situation where I need some help… Also, I’m new to programming so pardon me if I’m slow at times…

Basically, I’m adapting the Adventure Creator’s inventory system to look and feel similar to some JRPGs, like persona or the most recent Tales, where you get a tabbed menu with different item categories, each tab with a Single column of cells/slots, each slot with the Item name and the number of items carried, each tab also has a panel for the item image and a panel for the Text Description. I’m doing this for joystick/keyboard controls only.

There are two situations, though. 1st: is that AC’s inventory slots/cells are designed for mouse interaction, so you have to first click the cell/slot so that it displays its description and image in their respective panels. 2nd: you have to click the slot once again to de-select the slot (else it will keep showing the info of the first item). This is because AC’s items are meant to be dragged out of the menu, or combined with other items. But in a modern JRPG, Item information should be displayed immediately when an item is highlighted.

Now, my first idea was to fake clicks whenever the button gets Selected/Deselected. I do this with OnSelect and OnDeselect using ExecuteEvents.Execute. That works, but I also need the click to be simulated when the menu has just opened and whenever the player presses left or right to change tabs. Now, I’ve managed to get the script to work when a player changes tabs… But, I can’t for the life of me, get the first slot to get auto-clicked when the menu first opens… I have no clue where I’ve gone wrong, and I don’t have a clue how to verify the button states which are triggered from the commencing of the script, so I can’t even tell if by mistake the click has been done twice, de-selecting the slot… weird thing is, it works perfectly after changing tabs… it’s only when the menu first starts that it doesn’t work…

I would appreciate it, if anyone can point out where I have messed up in the logic, or if I’ve messed up in the code or something…

Anyway, here is the script, by the way I attached this script to all my Slot (buttons). The fade in and out of the parents is done in the UI manager I made, which is parented under the canvas. Also, I’ve made sure all of the slots have been setup correctly… (Originally I was trying to get the first click to happen in the Start() function, but I though, maybe it doesn’t have enough time to do it after changing the navigation? so I passed the code to the Update(), where it works fine when tabbing, but still doesn’t work for when the script just started…)

using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Events;
using UnityEngine.EventSystems;

public class InventorySlotController : MonoBehaviour, ISelectHandler, IDeselectHandler, ISubmitHandler
{

    //Load Rewired Player
    [Tooltip("Rewired's player ID")]
    public int playerId = 0;
    private Rewired.Player player;

    //counter to verify if the axis was already pressed
    private bool PressedRight = false;
    private bool PressedLeft = false;

    //Toggle to verify if the player has clicked the item or not
    private bool AlreadyPressed = false;

    //counter to verify if First selected was already highlighted
    private bool IsFirstHighlighted = false;

    //My UI manager, holds the slot's parents data.
    [SerializeField]
    private GameObject MyUIManager;

    //First or Last slot toggle.
    [SerializeField]
    private bool IsFirstSlot = false;
    [SerializeField]
    private bool IsLastSlot = false;

    //Previous and next buttons used by the first and last
    [Tooltip("The button the First Button will navigate to when pressing Down")]
    [SerializeField]
    private UnityEngine.UI.Button NextButton;
    [Tooltip("The button the First Button will navigate to when pressing Up")]
    [SerializeField]
    private UnityEngine.UI.Button PreviousButton;

    [Tooltip("The index number of the parent object of this slot - Indexes must start from 0")]
    [SerializeField]
    private int InventoryBoxNumber;

    private Navigation MyNavigation = new Navigation();

    // Use this for initialization
    void Start () {
        //initializing the player information
        player = Rewired.ReInput.players.GetPlayer(playerId);
        //Setup slot navigation
        NavigationHandler ();
    }


    // Update is called once per frame
    void Update () {
        //if parent UI object is visible
        if (MyUIManager.GetComponent<UIInputControl> ().MyInventoryBoxes [InventoryBoxNumber].GetComponent<CanvasGroup> ().alpha == 1) {
            //if it's the first slot and it's not yet pressed
            if (IsFirstSlot == true && AlreadyPressed == false) {
                SimulateClick();
            }
        }

        // if player is presing the "Right" key, check visibiity
        if ((player.GetAxis ("Horizontal")) > 0.0f && PressedRight == false) {
            //click to deselect current
            SimulateClick();
            //recheck navigation
            NavigationHandler ();
            //change counter
            PressedRight = true;
            //Reset the First Secledt counter to allow Selecting the slot when there's change
            IsFirstHighlighted = false;
            AlreadyPressed = false;
        }


        // if player is presing the "Left" key, check visibiity
        if ((player.GetAxis ("Horizontal")) < 0.0f && PressedLeft == false) {
            //click to deselect current
            SimulateClick();
            //recheck navigation
            NavigationHandler ();
            //change counter
            PressedLeft = true;
            //Reset the First Secledt counter to allow Selecting the slot when there's change
            IsFirstHighlighted = false;
            AlreadyPressed = false;
        }


        // if the player has stopped pressing the left or Right key.
        if ((player.GetAxis ("Horizontal")) == 0) {
            PressedLeft = false;
            PressedRight = false;
        }
         
    }


    public void OnSelect(BaseEventData eventData)
    {
        //do your stuff when selected
        //auto click to select the button to show Description and item Image.
        SimulateClick();

    }

    public void OnDeselect(BaseEventData eventData)
    {
        //do your stuff when selected
        //auto click to Deselect
        SimulateClick();
    }

    public void OnSubmit(BaseEventData eventData)
    {
        //do your stuff when you submit
        //if this click was called by a button press
        if (player.GetButtonDown (0)) {
            //run a prompt to ask player what to do. Then, in the promt, run your item's actionlist, etc
            Debug.Log ("player pressed the InteractionA input");
        } else {
            //means this was an auto-click to show Description and item Image. So change counter.
            AlreadyPressed = true;
        }
    }

    public void SimulateClick(){
        //auto click this slot - sending click event
        var fakePointer = new PointerEventData(EventSystem.current);
        ExecuteEvents.Execute (this.gameObject, fakePointer, ExecuteEvents.submitHandler);

    }

    private void HighlightFirstSlot(){
        //if it's the first and its highlighted toggle is false
        if (IsFirstSlot == true && IsFirstHighlighted == false) {
            //if the parent is visible
            if (MyUIManager.GetComponent<UIInputControl> ().MyInventoryBoxes [InventoryBoxNumber].GetComponent<CanvasGroup> ().alpha == 1) {
                //if it's not already selected
                if (EventSystem.current.currentSelectedGameObject != this.gameObject) {
                    EventSystem.current.SetSelectedGameObject(this.gameObject);
                }

                //change counters
                IsFirstHighlighted = true;
            }
        }
    }

    //Sets the buttons navigation depeding on it's position and if the parent's visibility is 1
    private void NavigationHandler(){
        //if the parent inventory box is visible enable navigation, if !visible then disable navigation
        if (MyUIManager.GetComponent<UIInputControl>().MyInventoryBoxes [InventoryBoxNumber].GetComponent<CanvasGroup> ().alpha == 1) {
            //enable button navigation
            //if it's the first slot and its not been activated already
            if (IsFirstSlot == true && IsFirstHighlighted == false) {
                //set navigation to explicit, setting the next button to go to
                MyNavigation.mode = Navigation.Mode.Explicit;
                MyNavigation.selectOnDown = NextButton;
                this.GetComponent<Button>().navigation = MyNavigation;

                //have event system focus on this slot
                HighlightFirstSlot();

            //if it's the last slot
            } else if (IsLastSlot == true) {
                MyNavigation.mode = Navigation.Mode.Explicit;
                MyNavigation.selectOnUp = PreviousButton;
                this.GetComponent<Button>().navigation = MyNavigation;
            } else
            {
                MyNavigation.mode = Navigation.Mode.Vertical;
                this.GetComponent<Button>().navigation = MyNavigation;
            }
        } else
        {
            //disable button navigation
            MyNavigation.mode = Navigation.Mode.None;
            this.GetComponent<Button>().navigation = MyNavigation;
        }
    }
1 Like

Simulating button clicks is generally bad practise. When you click something, you can call a function. In Start() event you can directly call the same function too, and that’s really all there is to … not actually simulating a button click, but executing the event that clicking it would do.

void Start() {
  ClickButtonX();
}

public void ClickButtonX() {
  // Do something
}
1 Like

Umm… I’m not sure I managed to explain myself properly… I’m not trying to simulate a click to run any functions, perse. As I said, Adventure creator by default needs the player to click a button before it will display things like description or item image, it also needs a click to deselect that item. I have no clue how to call those functions, neither I have any clue if I can disable that functionality, I would have to actually request the guy who made the asset to tell me how to do things I’m not even sure were even supposed to be in the API for the end user (or which make break other features if they’re changed)… What I’m trying to do, is simply do those two clicks automatically, so that the player doesn’t have to do it him/herself, which would give away it’s a menu originally intended for mouse and keyboard combo…

AFAIK you can’t, if it is possible its probably harder than calling the method you need anyways. Just find out what methods those buttons call when you click them, and send the same data to the script.

Alright, I’ll try talking to Chris, then…

1 Like
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class AutoButtonClick : MonoBehaviour {

    public int TimeForClick = 4;


    // Use this for initialization
    void OnEnable () {

    gameObject.GetComponent<Button> ();

        while (TimeForClick < 5)
        {
            TimeForClick++;
        }

        if (TimeForClick == 5)
            {
            Button.onClick.Invoke ();
            }

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

we are in the same boat, I’ve tried