I'm trying to make an app in Unity which requires your name and other details. I'm using the legacy Input Field to get the answers from the player which worked, but I can't seem to use the Input in any way other than Debug.Log.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ReadInput : MonoBehaviour
{
private string input;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
public void ReadStringInput(string s)
{
input = s;
Debug.Log(input);
}
}
I used this simple script to get the input but I have no clue how to actually use it in the game. It want it to say, for example, Welcome,(Person's Name/Input) outside of the log and actually into a text object.
If you right click in the hierarchy, under UI you can add a text object. I like to use a free package called Text Mesh Pro, which you can get in the asset store, but you don't need to.
Once you've made your text object, it should appear as a child of a gameobject called the Canvas. The text object should have a text field that you can access from script.
Text mytext;
public void UpdateMyText(string s)
{
mytext.text = s;
}
Here's the documentation
Just drag the text object into the script's mytext field in the inspector, and call that function when you want to update your text.
Is there any way to cycle text with textmesh script?
I'm interested in cycling text so i can display different text on my 2D game.
I have try the script on this website. But I don't think it works. Maybe I'm doing something wrong?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
public class CyclingText : MonoBehaviour
{
public TMP_Text text;
void Update()
{
TextMeshPro textmeshPro = GetComponent<TextMeshPro>();
textmeshPro.SetText("The first number is {0} and the 2nd is {1:2} and the 3rd is {3:0}.", 4, 6.345f, 3.5f);
// The text displayed will be:
// The first number is 4 and the 2nd is 6.35 and the 3rd is 4.
}
}
Can someone provide me with an answer or explained what I done wrong?
You seem a bit confused about the use of TMP
1
If you set the TMP in the inspector as public you can simply
public TMP_text text;
And then simply drag the text inside the inspector and simply:
text.text = "Text displayed";
2
If you don't create a public variable but a private, you can:
private TMP_text text;
And then, if you script is in the text object you can:
text = this.gameObject.GetCOmponent<TextMeshPro>();
And
text.text = "Your text";
First of all i want to say Sorry for my bad english and bad grammar
i have a problem and that is when i press play in the editor my array i made in my custom editor disapares(also does that when i update the script)!
First i got a script called “ColorChangerSingle” which is the script i declare varibles
using UnityEngine;
public class ColorChangerSingle
{
public GameObject gameObjectToChange;
public Color color;
}
then i have a script called “ColorChanger” which is the script i make a custom inspector for and all it got is a static list of “ColorChangerSingle”
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ColorChanger : MonoBehaviour {
public static List<ColorChangerSingle> single = new List();
}
and i have the custom inspector script called “CustomChangeColorInspector” which is the custom inspector script.
using UnityEditor;
using UnityEngine;
[CustomEditor(typeof(ColorChanger))]
public class CustomColorChangerInspector : Editor
{
public override void OnInspectorGUI()
{
for (int i = 0; i < ColorChanger.single.Count; i++)
{
EditorGUILayout.BeginHorizontal();
ColorChanger.single[i].gameObjectToChange = (GameObject)EditorGUILayout.ObjectField(ColorChanger.single[i].gameObjectToChange, typeof(GameObject));
ColorChanger.single[i].color = EditorGUILayout.ColorField(ColorChanger.single[i].color);
EditorGUILayout.EndHorizontal();
if (ColorChanger.single[i].gameObjectToChange != null)
if (ColorChanger.single[i].gameObjectToChange.GetComponent() != null)
ColorChanger.single[i].gameObjectToChange.GetComponent().material.color = ColorChanger.single[i].color;
}
EditorGUILayout.BeginHorizontal("box");
if (GUILayout.Button("Add To Array"))
{
ColorChanger.single.Add(new ColorChangerSingle());
}
if (GUILayout.Button("Remove Object In Array"))
{
ColorChanger.single.RemoveAt(ColorChanger.single.Count - 1);
}
EditorGUILayout.EndHorizontal();
}
}
when i add arrays in “not play mode” everything works(setting objects / changing the color of them) but when i press play the array gets “reset”, i think it has to do with the “ColorChanger” script where i set the list equal to a new list of ColorChangerSingle :/
any help is greatly appreciated!
Pictures:
https://gyazo.com/167ab826b6d578ec5a66d9d2586479e8
https://gyazo.com/847a063f9885478200c5a504be1dae2a
thanks for your time and have a great day! //Jrp0h
btw i hope the catagory is good and i know i can clean up the code alot but i made this really quick becuse im working on a secret project and did not want to use that code :)
I don't think your problem comes from the public static List<ColorChangerSingle> single = new List(); line.
What I'd recommend is adding [SerializeField] attributes to your single field and [System.Serializable] to your ColorChangerSingle class. Also are you sure your scene is saved before entering Play mode (this is a common mistake I used to do earlier on) ? If not you can add something like this at the end of the OnInspectorGUI() method :
if(GUI.changed && !Application.isPlaying)
{
EditorUtility.SetDirty(m_Target);
EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene());
}
EDIT : Also you have to give your custom inspector script a reference to the instance of the script you want to edit (think of many of your GameObjects holding a ColorChanger script), when you call ColorChanger.single[i].gameObjectToChange = [...]; your CustomColorChangerInspector inspector script doesn't know which of your GameObject you refer too.
This is why you have to reference it. The way I usually do it for quick custom inspetocrs (there is more than one way to do it, using serialization for example) is :
[CustomEditor(typeof(ColorChanger))]
public class CustomColorChangerInspector : Editor
{
// I like to declare it once for all but you can also call "(ColorChanger)target" each time to refer to the target
private ColorChanger m_Target;
public override void OnInspectorGUI()
{
m_Target = target as ColorChanger;
for (int i = 0; i < ColorChanger.single.Count; i++)
{
EditorGUILayout.BeginHorizontal();
m_Target.single[i].gameObjectToChange = (GameObject)EditorGUILayout.ObjectField(m_Target.single[i].gameObjectToChange, typeof(GameObject));
[...]
}
}
}
As I'm currently developing a Unity Engine based Game right now I need a PointerEnter EventTrigger to change my Text dynamically. Specifically:
If the user hovers with the Mouse in the MainMenu over a Text, I want an indicator on which Option he is pointing at.
So from Options the Text should turn to ▶ Options.
What I did is the following:
Text text;
string ContinueText = "▶ Continue";
void Awake()
{
// Set up the reference.
text = GetComponent<Text>();
}
public void Test()
{
text.text = ContinueText;
}
But if I hover over the Text I get
NullReferenceException: Object reference not set to an instance of an object
pointing at text.text = ContinueText;
So I searched around the Web and found that void Update() is sometimes called before Awake(), the Error stays the same anyway. The Canvas-Text is named "Text_Options", in case you need that.
Thanks for helping me out!
Here is an working example.
A canvas with an empty gameobject (has a vertical layout group, but thats not relevant) that is a container for two text objects.
I've added two event triggers each, OnPointerEnter and OnPointerExit. Both text objects have my script HoverText on them:
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class HoverText : MonoBehaviour
{
Text text;
public string content = "Text A";
public string contentHighlighted = "▶ Text A";
void Awake()
{
text = GetComponent<Text>();
text.text = content;
}
public void Highlight()
{
text.text = contentHighlighted;
}
public void UnHighlight()
{
text.text = content;
}
}
Text_A has itself as gameobject for it's both event triggers and Text_B itself respectively. The public strings for the two different text contents are set via inspector (default value from script is actually matching Text_A in my example).
That's it, works fine.
I am trying to make an easy to use button inside the Unity Editor for Character and Item creation.
I will throw out a little extra info here to help explain my issue.
My game is structured like this;
Game Controller >> Character Script >> (PlayerName)Script
A character object has both the character script and a script named after it, on it.
I want to be able to click "Create New Character" in the Unity editor and it do the following;
1) Prompt for a Name to use.
2) Create Empty Game Object named Name from whatever the user typed in.
3) Create a new C# Script named the same, and add it to the object.
-I want the generated script to have some pre-determined "Character Template" code in it.
4) Attach the new Script to the new empty game object, and attach a "Character Script" to it as well.
Thanks in advance.
One last sub-question.
Would it be better to Access the PlayerNamedScript from the GameController by a public monobehaviour on the Character Script?
Or can the CharacterScript Dynamically extend the PlayerNamedScript, sibling.
I hope that is clear. Thanks again.
Try this out
Put the CharacterCreatorEditor.cs in a folder named Editor somewhere in your project.
CharacterCreatorEditor.cs
using UnityEngine;
using System.Collections;
using UnityEditor;
using System.IO;
using System.Text.RegularExpressions;
public class CharacterCreatorEditor : EditorWindow {
#region Character Fields
//Add as many character specific fields / variables you want here.
//Remember to update the same thing in the "CharacterTemplate.txt"!
public string characterName = "John Doe";
public float characterHealth = 10;
public int characterCost = 1000;
public bool isBadGuy = false;
#endregion
private bool needToAttach = false; //A boolean that checks whether a newly created script has to be attached
private float waitForCompile = 1; //Counter for compile
GameObject tempCharacter; //A temporary GameObject that we assign the new chracter to.
//A Menu Item when clicked will bring up the Editor Window
[MenuItem ("AxS/Create New Character")]
public static void CreateNewChar () {
EditorWindow.GetWindow(typeof(CharacterCreatorEditor));
}
void OnGUI () {
GUILayout.Label("Here's a sample Editor Window. Put in more variables as you need below.");
GUILayout.Space(10);
//Note on adding more fields
//The code below is broken into groups, one group per variable
//While it's relatively long, it keeps the Editor Window clean
//Most of the code should be fairly obvious
GUILayout.BeginHorizontal();
GUILayout.Label("Character Name", new GUILayoutOption[0]);
characterName = EditorGUILayout.TextField(characterName, new GUILayoutOption[0]);
GUILayout.EndHorizontal();
GUILayout.Space(10);
GUILayout.BeginHorizontal();
GUILayout.Label("Character Health", new GUILayoutOption[0]);
characterHealth = EditorGUILayout.FloatField(characterHealth, new GUILayoutOption[0]);
GUILayout.EndHorizontal();
GUILayout.Space(10);
GUILayout.BeginHorizontal();
GUILayout.Label("Character Cost", new GUILayoutOption[0]);
characterCost = EditorGUILayout.IntField(characterCost, new GUILayoutOption[0]);
GUILayout.EndHorizontal();
GUILayout.Space(10);
GUILayout.BeginHorizontal();
GUILayout.Label(string.Format("Is {0} a Bad Guy?", new object[] { characterName }), new GUILayoutOption[0]);
isBadGuy = EditorGUILayout.Toggle(isBadGuy, new GUILayoutOption[0]);
GUILayout.EndHorizontal();
GUILayout.Space(10);
GUI.color = Color.green;
//If we click on the "Done!" button, let's create a new character
if(GUILayout.Button("Done!", new GUILayoutOption[0]))
CreateANewCharacter();
}
void Update () {
//We created a new script below (See the last few lines of CreateANewCharacter() )
if(needToAttach) {
//Some counter we just keep reducing, so we can give the
//EditorApplication.isCompiling to kick in
waitForCompile -= 0.01f;
//So a few frames later, we can assume that the Editor has enough
//time to "catch up" and EditorApplication.isCompiling will now be true
//so, we wait for the newly created script to compile
if(waitForCompile <= 0) {
//The newly created script is done compiling
if(!EditorApplication.isCompiling) {
//Lets add the script
//Here we add the script using the name as a string rather than
//it's type in Angled braces (As done below)
tempCharacter.AddComponent(characterName.Replace(" ", ""));
//Reset the control variables for attaching these scripts.
needToAttach = false;
waitForCompile = 1;
}
}
}
}
private void CreateANewCharacter () {
//Instantiate a new GameObject
tempCharacter = new GameObject();
//Name it the same as the Character Name
tempCharacter.name = characterName;
//Add the ChracterScript component. Note the use of angle braces over quotes
tempCharacter.AddComponent<CharacterScript>();
//Loading the template text file which has some code already in it.
//Note that the text file is stored in the path PROJECT_NAME/Assets/CharacterTemplate.txt
TextAsset templateTextFile = AssetDatabase.LoadAssetAtPath("Assets/CharacterTemplate.txt",
typeof(TextAsset)) as TextAsset;
string contents = "";
//If the text file is available, lets get the text in it
//And start replacing the place holder data in it with the
//options we created in the editor window
if(templateTextFile != null) {
contents = templateTextFile.text;
contents = contents.Replace("CHARACTERCLASS_NAME_HERE", characterName.Replace(" ", ""));
contents = contents.Replace("CHARACTER_NAME_HERE", characterName);
contents = contents.Replace("CHARACTER_HEALTH_HERE", characterHealth.ToString());
contents = contents.Replace("CHARACTER_COST_HERE", characterCost.ToString());
contents = contents.Replace("CHARACTER_BAD_GUY_HERE", isBadGuy.ToString().ToLower());
}
else {
Debug.LogError("Can't find the CharacterTemplate.txt file! Is it at the path YOUR_PROJECT/Assets/CharacterTemplate.txt?");
}
//Let's create a new Script named "CHARACTERNAME.cs"
using(StreamWriter sw = new StreamWriter(string.Format(Application.dataPath + "/{0}.cs",
new object[] { characterName.Replace(" ", "") }))) {
sw.Write(contents);
}
//Refresh the Asset Database
AssetDatabase.Refresh();
//Now we need to attach the newly created script
//We can use EditorApplication.isCompiling, but it doesn't seem to kick in
//after a few frames after creating the script. So, I've created a roundabout way
//to do so. Please see the Update function
needToAttach = true;
}
}
Put the below text file into the path "YOUR_PROJECT/Assets/CharacterTemplate.txt" If you don't, the code WON'T WORK!
CharacterTemplate.txt
using UnityEngine;
using System.Collections;
public class CHARACTERCLASS_NAME_HERE : MonoBehaviour {
public string characterName = "CHARACTER_NAME_HERE";
public float characterHealth = CHARACTER_HEALTH_HERE;
public int characterCost = CHARACTER_COST_HERE;
public bool isBadGuy = CHARACTER_BAD_GUY_HERE;
public void SomeMethod () {
}
}
Explanation of the code
First, the editor script takes all the input variables (should be fairly obvious what they are)
Once you click the done button, the following happen
A new GameObject is Instantiated
The instantiated GameObject is named the same as the Character Name in the Editor (eg. John Doe)
The CharacterScript (your common script) is attached
The template text file ("CharacterTemplate.txt") is read, and all the data is replaced with the data you entered in the Editor Window
This is then written to a new script file
We refresh the Asset Database, and wait until the newly created script is compiled (eg. JohnDoe.cs)
Lastly attach the script to the GameObject instantiated in Step 1
For your second question, what you'll need to do is to have all your PlayerNamedClass extend the same base class. This way, you can type the variable you'll expose in CharacterScript
So, for example, if you call the base class "NamedCharacterScripts"
In JohnDoe.cs
public class JohnDoe : NamedCharacterScripts
In JaneDoe.cs
public class JaneDoe : NamedCharacterScripts
In CharacterScript.cs
public NamedCharacterScripts namedCharacterScript;
void Awake () {
//This will assign JohnDoe.cs for the GameObject named "John Doe" &
//JaneDoe.cs to the GameObject named "Jane Doe"
namedCharacterScript = GetComponent<NamedCharacterScripts>();
}
Hope this answers your questions. If you have trouble, just leave a comment
My script is not production-ready like Venkat's answer, but it should be easier to understand for educational purposes.
using UnityEngine;
using System.Collections;
using UnityEditor;
using System.IO;
[ExecuteInEditMode]
public class CharacterTools : MonoBehaviour
{
[SerializeField, HideInInspector]
private string className;
private bool waitForCompile = false;
private void Update()
{
if (string.IsNullOrEmpty(className))
return;
if (waitForCompile && EditorApplication.isCompiling)
waitForCompile = false;
if (!waitForCompile && !EditorApplication.isCompiling)
{
var gameObject = new GameObject(className);
Debug.Log("Attempting to add " + className);
var c = gameObject.AddComponent(className);
className = null;
}
}
[ContextMenu("Create character")]
private void CreateCharacter()
{
string name = "Number" + Random.Range(0, 100).ToString();
string nameTemplate = "{0}Character";
string contentTemplate = #"using UnityEngine;
public class {0} : MonoBehaviour
{{
}}
";
var className = string.Format(nameTemplate, name);
var path = Application.dataPath + "/" + className + ".cs";
var scriptFile = new StreamWriter(path);
scriptFile.Write(string.Format(contentTemplate, className));
scriptFile.Close();
AssetDatabase.ImportAsset(path, ImportAssetOptions.ForceSynchronousImport);
AssetDatabase.Refresh();
this.className = className;
this.waitForCompile = true;
}
}
Usage:
Add this script to any object on scene.
Right click on just added component in inspector.
Choose “Create character”.
Wait few seconds.