Access the TM Pro InputField text in Unity - unity3d

I've been working on this solidly for hours and can't seem to get anywhere, so your help will be much appreciated.
I have created a few TextMeshPro UI InputFields in Unity and can't seem to access the text after a user has inputted something. I can do it when it's a normal InputField but not with the TM Pro version. I've created a Serializefield of type TMP_InputField which I have hooked up in the inspector (also including using TMPro namespace).
Could somebody please outline the steps required to get the text into a variable because I am stumped! The script is currently sitting on a different GameObject. I have an array of type TMP_InputField called theFields and when I debug theFields[0].name that seems to work fine (using FindObjectsOfType<>) but when I try to just access a specificField.text it throws a null reference objection when trying to edit the field during the game. Any tutorials/support would be very welcome!

Did you try with UnityEvents fields on the Inspector of TMP_InputField?
I make a simple script and it combines with TMP_InputField
using UnityEngine;
public class InputfieldListener : MonoBehaviour
{
public void OnChangedInputField(string input)
{
Debug.Log("[OnChangedInputField] " + input);
}
public void OnEndedInputField(string input)
{
Debug.Log("[OnEndedInputField] " + input);
}
public void OnSelectedInputField(string input)
{
Debug.Log("[OnSelectedInputField] " + input);
}
public void OnDeslectedInputField(string input)
{
Debug.Log("[OnDeslectedInputField] " + input);
}
}
Then you can find the log of each event.
FYI, the creator has a youtube channel and there is a related video tutorial.

using TMPro;
public TMP_InputField TMP_IF;
TMP_IF.interactable = true;
TMP_IF.text = "whatever you want";
For those interested in year 2020 :)
Seems that property interactable is instantly disabled, solution was to enable it so it text could be updated...

I just code it up and then in the editor drag the TMP_InputField object into the corresponding slots in the script.
So, code-wise, I would have script like Milorad Zivanovic shows.
If you want multiple ones you might have:
public TMP_InputField [] myInputs;
In the editor (as described above in my first sentence) you just hit the plus button and drag them in. Or just highlight them all and drag in all at once. If you lock your object in the editor to do this (little lock icon up top right) don't forget to unlock it.
To access in your code you either loop or use an index. Like to get the first one you would do this:
{//... in some method
myInputs[0].text = "something";
}
PS: I did not have to explicitly set the interactable field.
PPS: The answer that HyoJin KIM gave is great and best if you like using Unity's Event. I just gave this answer so you'd have an additional way of doing it that might match your original attempt(s).
Be aware that if you do choose this latter approach it is very easy to make the mistake of choosing the static version of the same method (they are listed twice!) Many times I make this mistake. Choose the top one (non-static, aka Dynamic) for most cases!

Related

The type or namespace name 'Forms' does not exist in the namespace 'System.Windows' FIX

Can someone please help me with this, am trying to use OpenFileDialog class from System.Windows.Forms to open a file dialog and read the selected file. Then, this error showed up. I've referenced it but still the same, below is the code.
`using UnityEngine
using UnityEngine.UI
using System.Windows.Forms;
public class OpenFileButtonScript : MonoBehaviour
{
public TextFieldScript textFieldScript;
public void OpenFile()
{
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.Filter = "Text Files (*.txt)|*.txt|All Files (*.*)|*.*";
openFileDialog.FilterIndex = 1;
openFileDialog.Multiselect = false;
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
string filePath = openFileDialog.FileName;
string text = System.IO.File.ReadAllText(filePath);
textFieldScript.inputField.text = text;
}
}
}`
It may look like you have access to all of the native Window system libraries, but it just looks like it. In actuality, a lot of the time you're simply given stubs, or shims, that look like the full Window libraries, because there's a certain element that Unity wants to use from those namespaces. If you think about it, the code you present above, what do you think it should do on Android or Nintendo devices? The simple answer is, it simply won't work.
Generally in cases like this, you have to gain access to the native operating system, and perform those calls directly. For example, there is a file browser asset on the Asset Store, that does this for you. It's not free, because the process isn't trivial.
Depending on how much effort you want to put in, you CAN read files from the local file stores (to varying degrees based on platform). It's possible to read the list of files in a location, and use either uGUI or UIToolkit to create your own File Open Dialogue box. Again, this isn't a trivial task either. So you have to be sure that you'd want to go down that path.

Assign UIElements button.clickable, using Visual Scripting Graph

I am trying to use Unity3D's UIToolkit with Visual Scripting Graph...
Typically, I can Query for the proper element, and then add the necessary function to the callback... However, as I am new to Visual Scripting, I am not sure how to get to this point. I've got the 'clickable' object of the button isolated, but I'm not sure how to assign the follow-up execution in the graph.
Usually in the code, I would do something like
clickable.clicked += ExampleFunction();
What I am messing up in the graph, is how to access the '.clicked' part. I can get the proper button element, and I can isolate it's clickable property, but I can't figure out how to assign some kind of functionality to react to the button getting clicked.
I could use a custom node to make this work, but I am looking for a way to do this with built-in nodes, if possible.
Alright... I had to write a custom node, but I figured this out. Here is the graph for the solution.
You have to grab the UIDocument from whichever GameObject it is attached to... You then need to get the Root Visual Element, do NOT clone or instantiate it. You then need to Query for the desired button, using the name you gave it in the UI Builder. It is easier if you use the U Query Extensions nodes... After that, I just made a custom node to subscribe the functionality. I am not familiar of any nodes that do this.
Here is the 'Subscribe Start Result' node code:
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.UIElements;
public class SubscribeStartResult : Unit
{
[DoNotSerialize]
[PortLabelHidden]
public ControlInput inputTrigger;
[DoNotSerialize]
[PortLabelHidden]
public ValueInput element;
protected override void Definition()
{
element = ValueInput<Button>("element");
inputTrigger = ControlInput("inputTrigger", (flow) =>
{
flow.GetValue<Button>(element).clicked += () =>
{
Debug.Log("Button clicked");
};
return null;
});
}
}
With this setup, clicking the 'Start Button' in play-mode will log "Button clicked" in the Console.
The 'return null;' line is an artifact of the lambda. It is required to continue the control flow in the event this node has a follow-up... Otherwise, this combination of nodes and code allow you to assign callbacks for the UI Builder elements, using the Visual Scripting Graph.

MRTK - can't get the value from UI_KeyboardInputField object

Hello i am using the MRTK 2.7.3 and I am trying the read the value from a UI_KeyboardInputField object but seems something is wrong on my code
using Microsoft.MixedReality.Toolkit.Experimental.UI;
public void onSubmit()
{
GameObject username = GameObject.Find("Username");
UI_KeyboardInputField inputUsername = username.GetComponent<UI_KeyboardInputField>();
Debug.Log("username" + inputUsername.Text); <<<ERROR
}
'UI_KeyboardInputField' does not contain a definition for 'Text' and no accessible extension method 'Text' accepting a first argument of type 'UI_KeyboardInputField' could be found (are you missing a using directive or an assembly reference?)
Maybe my approach is wrong how can i get the text value from this field ?
thanks
From UI_KeyboardInputField
Only used in Unity 2018.4. No longer used in Unity 2019.3 and later versions (becomes an empty MonoBehaviour and is only around for compatibility) and you can safely remove it if you wish
And also
A component that can be added to InputField to make it work with Windows Mixed Reality's system keyboard.
Sounds to me like this is/was only a helper component for forwarding the virtual keyboard input and the actual thing is all happening in a usual InputField component attached to the same GameObject and you rather want to access the .text of that one.

Unity Scriptable Objects issue

I have a list in RoomSO that contains premade ButtonSOs that i created in the editor and dragged and dropped into the list. RoomSO is also premade (made in the editor) Then at runtime i create an instance of a ButtonSO and tried adding it to RoomSO buttons. I look at the RoomSO in the editor and i get "Type mismatch". I canĀ“t understand why?
RoomSO script:
[CreateAssetMenu(fileName = "New Room", menuName = "Rooms/Room")]
public class RoomSO : ScriptableObject
{
public List<ButtonSO> buttons;
public void AddButton()
{
ButtonSO bt = (ButtonSO) ScriptableObject.CreateInstance<ButtonSO>() as ButtonSO;
bt.buttonText = "Hello";
buttons.Add(bt)
}
}
My ButtonSO script:
[CreateAssetMenu(fileName = "New Button", menuName = "Rooms/Button")]
public class ButtonSO : ScriptableObject
{
public string buttonText;
}
You issue isn't really an "issue".
What happens is that usually Unity expects a ScriptableObject asset reference assigned to the fields in the Inspector. Because the actual use-case of ScriptableObject is to have certain exchangeable data/behaviour container assets.
What you are doing is creating instances on runtime. These instances are only stored in the temporary memory since you never actually store them as assets into your project.
You will see the type mismatch in the Inspector, but actually this means there is a valid reference - otherwise it would say either None (ButtonSO) or Missing (ButtonSO), it only won't be saved once the Playmode ends. The later Missing (ButtonSO) you will see after ending the Play Mode since the List<ButtonSO> will still exist, also the items within it - but the according references you created during runtime will be destroyed.
Your runtime code should still work as expected as long as the Play mode is running.
The same happens btw if you assign e.g. a GameObject field within a ScriptableObject with a reference from the Scene during runtime.
In general though: If you create these instances on runtime - why do they need to be ScriptableObjects? You could just use a normal class.

Unity How to use Editor Script to remove StateMachineBehaviour

I have a problem use editor script to remove a statemachinebehaviour,like this:
I use AnimatorState.AddStateMachineBehaviour add the behaviour
The Documentation said use Object.Destroy,I use this api,but it appears:
I want to know how to use Editor Script to implement the function as "remove"
thanks for any idea!!!
In order to remove the state machine behaviour you have to grab the state machine behaviour array, remove the behaviour that you're after, and then reassign the array.
Something along these lines should do it:
using UnityEditor;
using UnityEditor.Animations;
//how you invoke this is up to you
[MenuItem("CONTEXT/StateMachineBehaviour/Remove Test")]
public static void RemoveBehaviour(MenuCommand command)
{
Object selection = Selection.activeObject;
AnimatorState state = selection as AnimatorState;
if(state != null)
{
StateMachineBehaviour behaviour = command.context as StateMachineBehaviour;
StateMachineBehaviour[] theBehaviours = state.behaviours;
ArrayUtility.Remove(ref theBehaviours, behaviour);
Undo.RegisterCompleteObjectUndo(state, "Removed behaviour");
Undo.DestroyObjectImmediate(behaviour);
state.behaviours = theBehaviours;
}
}
This will remove the behaviour using the state machine dropdown menu, with added undo and redo support, an optional bonus.
Depending on how you want to handle the remove, this approach will change but in terms of removing the behaviour, this should be what you're after.
Also, for animator state machines the approach is exactly the same, you just cast the selection object to an AnimatorStateMachine instead.
Hopefully this helps.