Search code examples
c#unity-game-enginetextmeshpro

How do I create and place an input text field from script?


I want to display an input field on the screen from a script, no editor, no template to work with. I think I need a TMP_InputField but I was unable to position it, see it or interact with it at all.

This is my code so far. I can see the grey background fine and the log has the "InputField created".

canvas = new GameObject("Canvas");
var c = canvas.AddComponent<Canvas>();
c.renderMode = RenderMode.ScreenSpaceOverlay;

background = new GameObject("Background");
background.transform.parent = canvas.transform;
var img = background.AddComponent<Image>();
img.color = new Color(0.2f, 0.2f, 0.2f, 0.8f);
var rect = img.GetComponent<RectTransform>();
rect.localPosition = new Vector3(0, 0, 0);
rect.sizeDelta = new Vector2(200, 200);

var textField = new GameObject("Input");
textField.transform.parent = canvas.transform;
inputField = textField.AddComponent<TMP_InputField>();
inputField.text = "example";

rect = textField.AddComponent<RectTransform>();
rect.localPosition = new Vector3(0, 0, 0);
rect.sizeDelta = new Vector2(200, 25);

inputField.Select();
inputField.ActivateInputField();

Debug.Log("InputField created");

Solution

  • You are not setting all the required settings for an Input Field. I've managed to initialize it; nevertheless, it's not clickable right now, check the code:

        // set it to inputFieldBackground Image
        [SerializeField] private Sprite sprite;
    
        private void Start()
        {
            var canvas = new GameObject("Canvas");
            var c = canvas.AddComponent<Canvas>();
            c.renderMode = RenderMode.ScreenSpaceOverlay;
    
            var background = new GameObject("Background");
            background.transform.parent = canvas.transform;
            var img = background.AddComponent<Image>();
            img.color = new Color(0.2f, 0.2f, 0.2f, 0.8f);
            var rect = img.GetComponent<RectTransform>();
            rect.localPosition = new Vector3(0, 0, 0);
            rect.sizeDelta = new Vector2(200, 200);
    
            var textField = new GameObject("Input", typeof(CanvasRenderer), typeof(RectTransform), typeof(Image),
                typeof(TMP_InputField));
            textField.transform.parent = canvas.transform;
            textField.GetComponent<RectTransform>().sizeDelta = new Vector2(160, 30);
            textField.GetComponent<RectTransform>().localPosition = Vector3.zero;
            textField.GetComponent<TMP_InputField>().text = "example";
            textField.GetComponent<TMP_InputField>().targetGraphic = textField.GetComponent<Image>();
            textField.GetComponent<Image>().type = Image.Type.Sliced;
            textField.GetComponent<Image>().sprite = sprite;
    
            var placeHolder = new GameObject("Placeholder", typeof(CanvasRenderer), typeof(TextMeshProUGUI),
                typeof(LayoutElement));
    
            var text = new GameObject("Text", typeof(CanvasRenderer), typeof(TextMeshProUGUI));
    
            var textArea = new GameObject("Text Area", typeof(RectMask2D), typeof(RectTransform));
    
            textField.GetComponent<TMP_InputField>().textViewport = textArea.GetComponent<RectTransform>();
            textArea.transform.SetParent(textField.transform);
            textArea.GetComponent<RectTransform>().localPosition = Vector3.zero;
    
            placeHolder.transform.SetParent(textArea.transform);
            text.transform.SetParent(textArea.transform);
            text.GetComponent<TextMeshProUGUI>().color = Color.black;
            
            text.GetComponent<RectTransform>().localPosition = Vector3.zero;
            placeHolder.GetComponent<RectTransform>().localPosition = Vector3.zero;
    
    
            textField.GetComponent<TMP_InputField>().textComponent = text.GetComponent<TextMeshProUGUI>();
    
            rect.localPosition = new Vector3(0, 0, 0);
            rect.sizeDelta = new Vector2(200, 25);
    
            textField.GetComponent<TMP_InputField>().Select();
            textField.GetComponent<TMP_InputField>().ActivateInputField();
    
            Debug.Log("InputField created");
        }