using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Security.Cryptography.X509Certificates;
using UnityEngine;
using UnityEngine.UI;
public class LetterRandomiser : MonoBehaviour
{
public char[] characters;
public Text textbox;
public InputField mainInputField;
void Start() /*when the game starts*/
{
char c = characters[Random.Range(0,characters.Length)];
textbox.text = c.ToString();
}
void Update()
{
if (Input.GetKeyDown(KeyCode.KeypadEnter) && mainInputField.text.Contains(textbox.text) == true)
{
char c = characters[Random.Range(0, characters.Length)];
textbox.text = c.ToString();
mainInputField.text = "";
}
else if (Input.GetKeyDown(KeyCode.KeypadEnter) && mainInputField.text.Contains(textbox.text) == false)
{
mainInputField.text = "";
}
}
}
Reference to my game
I'm trying to program my game so that the two textboxes (firstChar and secondChar) would choose one randomly generated letter each.
Then when a player types in a word in the input box, the game would check if the word contains the two randomly generated.
If it does, then the program would randomise the two textboxes again and the input field would be blank.
Otherwise the program wouldn't randomise those two textboxes and the player will have to try again.
However the program doesn't work. There are no errors but when I press enter, nothing happens, like shown on the image.
Answered by #DerDingens.
You are checking for KeypadEnter. The normal / big Enter ist Return:
docs.unity3d.com/ScriptReference/KeyCode.KeypadEnter.html.
Related
I have a pretty strange problem. I was coding a simple dialogue system, for now it will only display a letter every 0.1 seconds.
I have a TextMeshPro text that contains the text to be displayed.
Here is attached my DialogueLine.cs script:
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
namespace DialogueSystem
{
public class DialogueLine : DialogueBaseClass
{
private TextMeshProUGUI textHolder;
[Header ("Text Options")]
[SerializeField] private string input;
private void Awake()
{
textHolder = GetComponent<TextMeshProUGUI>();
StartCoroutine(WriteText(input, textHolder));
}
}
}
it gets the value of my "input" variable, setted from Unity interface. The script calls the "WriteText" coroutine, in the DialogueBaseClass.cs script:
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
public class DialogueBaseClass : MonoBehaviour
{
protected IEnumerator WriteText(string input, TextMeshProUGUI textHolder)
{
for (int i= 0; i < input.Length; i++)
{
textHolder.text += input[i];
yield return new WaitForSeconds(0.1f);
}
}
}
A pretty simple script that adds on my "textHeader" component a letter from the input every 0.1 seconds.
But, here is the problem. The output of my component is only the first letter of the input variable: if in the input I write "Hello" it displays "H".
I really can't find the problem in this script...
This is my original code and it's working fine but the text content is already in the editor in a Text UI and therefore it's also in the variable textField.
So I don't want to type the text over again also inside the code. For example the word toBeSearched is "almost" so using the string format it will generate new random number each time I press on space between the words: "almost" and "hours".
But since the text is already in the textField variable I want to parse the place I want to add the random numbers automatic using indexof and substring.
using System.Collections;
using System.Collections.Generic;
using System.Text;
using UnityEngine;
using UnityEngine.UI;
public class CustomText : MonoBehaviour
{
public string toBeSearched;
public Text textField;
private void Start()
{
GenerateRandomHour();
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
GenerateRandomHour();
}
}
private void GenerateRandomHour()
{
string numberName = Random.Range(1, 10).ToString();
textField.text = string.Format("Hello my friend, It's about time to wakeup. You were sleeping for almost {0} hours. My name is NAVI and i'm your navigation helper in the game.", numberName);
}
}
This is the code with the indexof and substring I tried to use but it#s not working good.
using System.Collections;
using System.Collections.Generic;
using System.Text;
using UnityEngine;
using UnityEngine.UI;
public class CustomText : MonoBehaviour
{
public string toBeSearched;
public Text textField;
private void Start()
{
GenerateRandomHour();
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
GenerateRandomHour();
}
}
private void GenerateRandomHour()
{
string result = null;
string result1 = null;
int ix = textField.text.IndexOf(toBeSearched);
if (ix != -1)
{
result = textField.text.Substring(0, ix + toBeSearched.Length);
result1 = textField.text.Substring(ix + toBeSearched.Length, textField.text.Length - (ix + toBeSearched.Length));
}
result1 = result1.TrimStart();
string numberName = Random.Range(1, 10).ToString();
textField.text = string.Format(result + " {0} " + result1, numberName);
}
}
Again the word toBeSearched is "almost" and I used a breakpoint and result contain the text until almost: "Hello my friend, It's about time to wakeup. You were sleeping for almost" and the variable result1 contain the rest of the text: "hours. My name is NAVI and i'm your navigation helper in the game."
But now when I'm pressing the space key it's inserting each time a new random number but it's not replacing the whole text like in the original code above.
So the result is many numbers in the text.
Not sure why it's not working like the original code.
The reason why it's not working is because you're changing the value of textField.text, so when you repeat the process the substrings are generated with this new value, including the number. You shouldn't give up your first solution, it's much cleaner. Store the original value of the text field on Start:
using System.Collections;
using System.Collections.Generic;
using System.Text;
using UnityEngine;
using UnityEngine.UI;
public class CustomText : MonoBehaviour
{
public string toBeSearched;
public Text textField;
private string defaultValue;
private void Start()
{
defaultValue = textField.text;
GenerateRandomHour();
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
GenerateRandomHour();
}
}
private void GenerateRandomHour()
{
string numberName = Random.Range(1, 10).ToString();
textField.text = string.Format(defaultValue, numberName);
}
}
Add the {0} directly to your text field value in the inspector:
Hello my friend, It's about time to wakeup. You were sleeping for almost {0} hours. My name is NAVI and i'm your navigation helper in the game.
The problem is when you are adding a number in a specified spot, so every time you press space, it is using the existing text as the template and thus the old number stays,along with adding a new one.
Instead, you want to search between the two words "almost" and "hours" so you can replace whatevers between them. You can do this the by adding another indexOf search, but itll be easier using regex.
string result = Regex.Replace(textField.text, "(? <=almost).+?(?=hours)" , numberName);
textField.text = result;
Although your first solution looks cleaner, and if you want to keep the text in the inspector, Nathalia's answer would work
my character shoots arrows. She starts without zero arrows and cannot shoot any until she picks up an arrow icon. Arrow icons have a value of 3. After this she can shoot arrows. That code works fine. Now I have to make it so these arrows decrease in value through the UI text display. The UI text value changes from 0 to 3 when an arrow icon is picked up, but it doesn't decrease when I shoot an arrow. I have another game object with a script that will detect when an arrow is shot. when this happens, it tells that main script that, "hey, an arrow was just shot." The focus is on getting the Text to decrease when I shoot an arrow.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class arrowManager : MonoBehaviour {
private Text text;
public static int arrowCount;
public static int arrowRecount;
private int maxArrows = 99;
void Start ()
{
text = GetComponent<Text> ();
arrowCount = 0;
}
void Update ()
{
FullQuiver ();
arrowCounter ();
}
void arrowCounter()
{
if (arrowCount < 0) {
arrowCount = 0;
text.text = "" + arrowCount;
}
if (arrowCount > 0)
text.text = "" + arrowCount;
}
public static void AddPoints(int pointsToAdd)
{
arrowCount += pointsToAdd;
}
public static void SubtractPoints(int pointsToSubtract)
{
arrowCount -= pointsToSubtract;
}
public void FullQuiver()
{
if (arrowCount >= maxArrows)
{
arrowCount = maxArrows;
}
}
}
the game object with the script that detects arrows looks like this.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class arrowDetector : MonoBehaviour {
public int pointsToSubtract;
void OnTriggerEnter2D(Collider2D other)
{
if (other.gameObject.tag == "arrow")
{
arrowManager.SubtractPoints (pointsToSubtract);
}
}
}
Forgive me if I've misunderstood, but it looks to me like you are subtracting from the wrong variable.
Since you are displaying the 'arrowCount' variable, I imagine that's what should be subtracted from.
public static void SubtractPoints(int pointsToSubtract)
{
if (arrowCount > 0) {
arrowCount -= pointsToSubtract;//pointsToSubtract is an int value passed to this script from my player script whenever she shoots an arrow.
}
}
In SubtractPoints method you are detracting from the variable "arrowRecount".
Wouldn't you want to be subtracting from "arrowCount" instead? If you used "arrowCount" your text value should update properly.
I figured it out. Before, I was trying to get it to detect my arrows whenever a bool became true from my player script. That wasn't working so I said screw it and just made an empty that detects gameobjects with the tag "arrow." Then I updated the script in here to reflect that. I was dead tired last night after not getting any sleep for two days so I forgot to put in a value of pointsToSubtract in the hierarchy. Thanks everyone for their responses.
I have an array InputFields, in my situation - six InputFields. How can I get the text and save it from each InputField?
Everything should work like this: I turn on the app, I change one, two or all of the input field, then turn off the application. Again, I turn on, and input fields have to be values which I wrote earlier.
I have a code that must seem to work properly, but this code works like this: it takes only the last value entered by the user and writes it to the last input field.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class SaveText : MonoBehaviour {
public GameObject[] InputFields;
public static string n;
public void Start ()
{
for(int i = 0; i < InputFields.Length; i++)
{
InputFields[i].GetComponent<InputField> ().text = PlayerPrefs.GetString (InputFields[i].name);
Debug.Log (PlayerPrefs.GetString (InputFields[i].name));
n = InputFields[i].name;
var input = InputFields[i].GetComponent<InputField> ();
var se = new InputField.SubmitEvent ();
se.AddListener (SubmitName);
input.onEndEdit = se;
}
}
public void SubmitName(string arg)
{
PlayerPrefs.SetString (n, arg);
}
An array of input fields I initialize dragging in Unity each input field in free cell in Script Component.
Well, you are using a single variable for all the different player prefs variables, n. So when you change a field (with SubmitName) it uses that n pref variable and changes it. This will correspond to the last value you gave to n in your loop.
An option would be to have that be an array too (private string prefValues[]) or to pass the calling input field to SubmitName (or rather it's name) and use that instead of n.
A little example (from your code you can actually change your GameObject[] to InputField[] which saves some GetComponent calls):
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class EventTest : MonoBehaviour
{
public InputField[] inputFields;
void Start ()
{
foreach(InputField field in inputFields)
{
var se = new InputField.SubmitEvent();
se.AddListener(delegate {
SubmitText(field.name, field.text);
});
field.onEndEdit = se;
}
}
public void SubmitText(string prefKey, string prefVal)
{
Debug.Log("Saved " + prefVal + " to " + prefKey);
}
}
Edit:
Added lines for saving/loading from prefs in the code below. For my test setup I just have two scenes. Both have two input fields and a button that calls that scene change. I can type stuff on the fields as I like, change scenes and it stays. Also upon restarting playmode in the editor.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
public class EventTest : MonoBehaviour
{
public InputField[] inputFields;
void Start ()
{
foreach(InputField field in inputFields)
{
// Get field values from player prefs if existing
// (it should only not exist the very first time or if you delete/clear the prefs)
if(PlayerPrefs.HasKey(field.name))
field.text = PlayerPrefs.GetString(field.name);
var se = new InputField.SubmitEvent();
se.AddListener(delegate {
SubmitText(field.name, field.text);
});
field.onEndEdit = se;
}
}
public void SubmitText(string prefKey, string prefValue)
{
// store the typed text of the respective input field
PlayerPrefs.SetString(prefKey, prefValue);
}
public void ChangeScene()
{
if(SceneManager.GetActiveScene().name == "Scene1")
{
SceneManager.LoadScene("Scene2");
}
else
{
SceneManager.LoadScene("Scene1");
}
}
}
If you want to save the data, after the application stopped or if it gets paused, you need to add some more functions to your MonoBehavior so that it can handle additional actions on a system end or pause.
Look at following functions in the documentation
OnApplicationQuit()
OnApplicationPause()
These functions will be called automatically. Inside these functions you need to iterate through the textfields and save them. It is one of the last functions that will be called before the program will lose it's recourses.
Regarding the Scene change, you would need the new scene to tell the old one to do any further actions. Like you can read in this post, there is only a way to know if a new scene was loaded.
Maybe you have a place where you can save the last active scene object and then call the last scenes function to do the saving process while the object is not cleared.
I'm wondering if it's possible to store keyboard input history into a array and execute them at a later time? Basically I have a 3D grid game and a character moving around the grid. I want the user to enter all the movement instructions via right down left up keys while the player remains still, and once I press enter the player will begin to execute each instruction that is stored into the array.
any suggestions?
I would recommend using a List<T>
Example:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class Training : MonoBehaviour {
public List<KeyCode> previousActions;
void Update(){
if(Input.GetKeyDown(KeyCode.A)){
Debug.Log("Do something");
previousActions.Add(KeyCode.A);
}else if(Input.GetKeyDown(KeyCode.S)){
Debug.Log("Do something else");
previousActions.Add(KeyCode.S);
//---Check the list--//
}else if(Input.GetKeyDown(KeyCode.D)){
Debug.Log("Check the list");
for(int i = 0;i < previousActions.Count;i++){
Debug.Log(previousActions[i]);
}
}
}