Unity UI (4.6.1) placeholder graphic for input field c#

I am using the following code to dynamically create a canvas with an input field in it at runtime.

The issue is that the placeholder requires a graphic class. This can be created in the unity GUI by draging the inputfield into this slot and it auto converts it from an input field into a graphic to display the placeholder text “hello world!”.

However if I try to assign the inputfield to the .placeholder the compiler complains that inputfield is not of type graphic.

I looked in the documentation and I couldn’t even see placeholder mentioned as part the the inputfield class, nevermind how to deal with this.

Any ideas?

using UnityEngine;
using UnityEngine.UI;
using System.Collections;

public class CreateCanvas : MonoBehaviour {

	public GameObject theCanvasGO;
	void Start() {
		GameObject theCanvasGO = new GameObject ();
		theCanvasGO.name = "TheCanvas";
		Canvas theCanvas = theCanvasGO.AddComponent<Canvas>();
		GraphicRaycaster theGraphicRaycaster = theCanvasGO.AddComponent<GraphicRaycaster> ();
		RectTransform theCanvasRT = theCanvasGO.GetComponent<RectTransform> ();
		theCanvas.renderMode = RenderMode.WorldSpace;
		theCanvasRT.sizeDelta = new Vector2 (1000f,1000f);
		theCanvasRT.localPosition = new Vector3 (0f,2.69f,0f);
		theCanvasRT.localRotation = new Quaternion (0f, 180f, 0f, 0f);
		theCanvasRT.localScale = new Vector3 (0.001f,0.001f,1f);
		// add imput field
		GameObject inputFieldGO = new GameObject ();
		inputFieldGO.name = "inputfield";
		inputFieldGO.transform.parent = theCanvasGO.transform;
		InputField inputfield = inputFieldGO.AddComponent<InputField> ();
		inputfield.text = "Hello World!";

		Graphic myGraphic = new Graphic ();
		inputfield.placeholder = myGraphic;
		inputfield.transition = Selectable.Transition.None;
		inputFieldGO.AddComponent<RectTransform> ();
		RectTransform inputFieldRT = inputFieldGO.GetComponent<RectTransform> ();
		inputFieldRT.sizeDelta = new Vector2 (871f,300f);
		inputFieldRT.localPosition = new Vector3 (13f,-70f,0f);
		inputFieldRT.localRotation = new Quaternion (0f, 180f, 0f, 0f);
		inputFieldRT.localScale = new Vector3 (1f,1f,1f);

		GameObject textGO = new GameObject ();
		textGO.name = "textob";
		textGO.transform.parent = inputFieldGO.transform;
		RectTransform textRT = textGO.AddComponent<RectTransform> ();
		Text textscript = textGO.AddComponent<Text>();
		textRT.sizeDelta = new Vector2 (871f,300f);
		textRT.localPosition = new Vector3 (13f,-70f,0f);
		textRT.localRotation = new Quaternion (0f, 180f, 0f, 0f);
		textRT.localScale = new Vector3 (1f,1f,1f);
		inputfield.textComponent = textscript;
		textscript.supportRichText = false;
		textscript.resizeTextForBestFit = true;
		textscript.resizeTextMaxSize = 300;
		textscript.resizeTextMinSize = 10;
		Font myFont = Resources.Load<Font> ("MyFont");
		textscript.font = myFont;
		textscript.text = "This was written second.";


ps: the font “MyFont” is a font I downloaded into my resources folder which is loaded at runtime, to get this to work for you substitute MyFont with a font of your choice placed into your resources folder.

When you first set inputfield.text = "Hello World!";, this won’t actually show or update the text visually. This is because internally .text also updates the .textComponent’s Text. But you haven’t created it yet, so there’s nothing to draw. inputfield simply stores/caches the value without drawing it.

Then when you do textscript.text = "This was written second.";, that’s what the inputfield will now show visually (because InputField itself isn’t a Graphic, it’s just a fancy wrapper and it needs an actual Text that will be drawn).

But you have created a scenario (which sounds like a Unity bug) where the input field’s text and corresponding text component’s text are different. So when you first click the input field, it uses the original .text value (“Hello World!”) and changes the .textComponent’s .text to it as well (because it assumes they should be the same).

If you had had created textscript first and assigned it as input field’s .textComponent, and only then set inputfield.text, it would have been overwritten textscript’s value immediately and you would have never seen whatever you manually assigned to textscript.text.

As for placeholder, it needs to be a separate game object (so there are 2 Texts children of inputfield). Graphic is Unity’s base class for all UI elements. This simply means .placeholder accepts any of them. Image is a Graphic, Text is a Graphic etc. So you really need to create whatever your placeholder will be: some Text (which is what Unity creates by default), some Image, or whatever makes sense.

If you want it to be some text, then you should create another child under inputFieldGO and add Text to it with the placeholder. Then link that text/image to your .placeholder. In very short:

GameObject placeholderGO = new GameObject();
Text myPlaceholderText = placeholderGO.AddComponent<Text>();
inputfield.placeholder = myPlaceholderText;

Edit: correction. Edit 2: expand.