Reputation: 19
I have about 10 buttons with each button a unique value added through script. I want to know which button was clicked when interacting with the buttons using MRTK hands.
I have tried adding an updateField method to the button which gets the currently selected object using default EventSystem. However, when i debug the value is null.
public void UpdateField()
{
int dayNumb = EventSystem.current.currentSelectedGameObject.GetComponent<DayButton>().CurrentNumber();
}
NullReferenceException: Object reference not set to an instance of an object UpdateInputField.UpdateField () (at Assets/Scripts/UpdateInputField.cs:35) UnityEngine.Events.InvokableCall.Invoke () (at C:/buildslave/unity/build/Runtime/Export/UnityEvent.cs:166) UnityEngine.Events.UnityEvent.Invoke () (at C:/buildslave/unity/build/Runtime/Export/UnityEvent_0.cs:58) Microsoft.MixedReality.Toolkit.UI.InteractableOnPressReceiver.OnUpdate (Microsoft.MixedReality.Toolkit.UI.InteractableStates state, Microsoft.MixedReality.Toolkit.UI.Interactable source) (at Assets/MixedRealityToolkit.SDK/Features/UX/Interactable/Scripts/Events/InteractableOnPressReceiver.cs:71) Microsoft.MixedReality.Toolkit.UI.Interactable.InternalUpdate () (at Assets/MixedRealityToolkit.SDK/Features/UX/Interactable/Scripts/Interactable.cs:525) Microsoft.MixedReality.Toolkit.UI.Interactable.Update () (at Assets/MixedRealityToolkit.SDK/Features/UX/Interactable/Scripts/Interactable.cs:506)
Upvotes: 0
Views: 3113
Reputation: 19
Solved it!! I added a listener on each button in the start method. Then called the function to get the components of those objects.
Here is how i did it............
using UnityEngine.UI;
using UnityEngine.EventSystems;
using UnityEditor;
using Microsoft.MixedReality.Toolkit.UI;
public class UpdateInputField : MonoBehaviour {
public InputField mainInputField;
private Calendar calendar;
private GameObject dateCanvas;
public int dayNumb;
void Start(){
var allInteractables = GameObject.FindObjectsOfType<Interactable>();
foreach (var i in allInteractables)
{
i.OnClick.AddListener(() => UpdateField(i));
}
}
public void UpdateField(Microsoft.MixedReality.Toolkit.UI.Interactable index)
{
dayNumb = GameObject.Find(index.gameObject.name).GetComponent<DayButton>().CurrentNumber();
calendar = GameObject.FindObjectOfType<Calendar>();
mainInputField.text = calendar.ReturnDate(dayNumb);
}
}
Upvotes: 1
Reputation: 90580
Regarding the exception
EventSystem.current.currentSelectedGameObject.GetComponent<DayButton>().CurrentNumber();
offers a lot of possibilities. Basically the reference before each .
can possibly by null
. Most likely it is either currentSelectedGameObject
when simply no object is selected currently or GetComponent<DayButton>()
when the selected object simply has no such component.
I know nothing about your classes and very little about MRTK but maybe you could use an event system pattern like e.g.
public class DayButton : WhateverType
{
// public static event everyone can add listeners to
// in order to wait for any DayButton click
public static event Action<DayButton> OnButtonClicked;
// Just assuming for now this is the method called on click
public void OnClick()
{
// Fire the static event and inform every listener
// that this button was clicked by passing yourself in as parameter
OnButtonClicked?.Invoke(this);
}
}
Then you could have one (or different) listener classes waiting for the event and checking which button was pressed like
public class SomeListener : MonoBehaviour
{
privtae void Awake()
{
// Add a listener to the global event
DayButton.OnButtonClicked += HandleOnButtonClicked;
}
private void OnDestroy()
{
// Make sure to always remove listeners once not needed anymore
// otherwise you get NullReferenceExceptions!
DayButton.OnButtonClicked -= HandleOnButtonClicked;
}
// By passing the according DayButton reference in you have access
// to all its public fields and methods
private void HandleOnButtonClicked(DayButton button)
{
Debug.Log("The Button with the name {button.name} and number {button.CurrentNumber} was clicked!", this);
}
}
Upvotes: 2
Reputation: 2630
The following code will print the name of each button that was clicked in the scene. Note that instead of adding the event listeners on startup, you could just add these listeners when you create your buttons from code.
using Microsoft.MixedReality.Toolkit.UI;
using UnityEngine;
/// <summary>
/// On startup, adds event handlers for every Interactable aka button
/// in the scene that logs the name of the button pressed.
/// You can similarly add such a listener when adding the buttons dynamically
/// </summary>
public class PrintWhichButtonPressed : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
var allInteractables = GameObject.FindObjectsOfType<Interactable>();
foreach (var i in allInteractables)
{
i.OnClick.AddListener(() => Debug.Log(Time.time + ": " + i.gameObject.name + " was clicked"));
}
}
}
Upvotes: 2