In Unity, how to access children component of the prefab using script? - c#

Prefab hierarchy:
Button
1 Text
2 Image
I wish to access Image child component of the prefab.
I tried the following code:
GameObject addTypeButton = (GameObject)Instantiate(prefabButton);
addTypeButton.transform.SetParent(ParentPanel, false);
//set text
addTypeButton.GetComponentInChildren<Text>().text ="Some string";
//get image
WWW www = new WWW("someImagelink");
yield return www;
//set image
addTypeButton.GetComponentInChildren<Image>().sprite = Sprite.Create(www.texture, new Rect(0, 0, www.texture.width,www.texture.height), new Vector2(0, 0));
However, the above code is accessing Image script of Button (inbuilt).
Not the Image UI component.
How do I access UI Image (child) component?
Please help.
Thanks!

The Cause
GetComponentInChildren will also return component on the gameObject itself.
public Component GetComponentInChildren(Type t);
Returns the component of Type type in the GameObject or any of its children using depth first search.
Solutions
If the index of child GameObject 1 Text and 2 Image is fixed. You can get them by Transform.GetChild(index).
var buttonTransform = addTypeButton.transform;
var text = buttonTransform.GetChild(0);
var image = buttonTransform.GetChild(1);
If the order is not fixed, use Transform.Find(childName).
var buttonTransform = addTypeButton.transform;
var text = buttonTransform.Find("1 Text");
var image = buttonTransform.Find("2 Image");
The safest solution:
Drag your prefab to scene and attach a script to your Button GameObject:
using UnityEngine;
using UnityEngine.UI;
public class MyButton : MonoBehaviour
{
public Text text;
public Image image;
}
Then drag 1 Text and 2 Image to text and image field in the inspector of the Button.
Remember to press apply button and Ctrl+S to save that into your prefab.
In this way you can access the text and image like:
var mybutton = addTypeButton.GetComponent<MyButton>();
mybutton.text.text = "Some string";
mybutton.image.sprite = Sprite.Create(...);

Before accessing the child object, please make sure that that child object is enabled in prefab before enabling or disabling it after getting instantiated.
Like in my case, I had a UI Text game object with an image child object. I disabled it in the prefab with the hope to enable it by reference in the script after instantiating it. It only worked if I kept the image(child) component enabled in the prefab.

Try changing
addTypeButton.GetComponentInChildren<Image>().sprite = Sprite.Create(www.texture, new Rect(0, 0, www.texture.width,www.texture.height), new Vector2(0, 0));
To
addTypeButton.GetComponent<Image>().sprite = Sprite.Create(www.texture, new Rect(0, 0, www.texture.width,www.texture.height), new Vector2(0, 0));

Related

Transform TextMesh in Unity

I've created a text mesh in Unity like this:
var theText = new GameObject();
var textMesh = theText.AddComponent<TextMesh>();
var meshRenderer = theText.AddComponent<MeshRenderer>();
textMesh.text = name;
textMesh.transform.position = new Vector3(0, 5, 0);
theText.transform.position = new Vector3(0, 5, 0);
The same kind of transformation works on other objects such as a quad. I do not really know which object I should transform, so I tried both textMesh and theText, also separately.
When I click "Play" in Unity and select the created object in the scene, then the contour of the text is highlighted in orange at the correct position. However, the visible white text is still at (0, 0, 0).
This is not only in scripting; when I create a "3D Object/3D Text" via the Unity UI and drag it around with the mouse, it's the same issue.
Why are you creating the text mesh in code? Just go to GameObjects -> UI -> Text or Text Mesh Pro and create it and place it in your scene. If you need to move it just reference
gameObject.transform.position
in a script attached to it.
edit: try removing
textMesh.transform.position = new Vector3(0, 5, 0);
second edit: sorry wasn't paying attention, you just need to change move theText (the game object)
If you assign a color to your text you will be able to see it. Try this code:
var theText = new GameObject();
var textMesh = theText.AddComponent<TextMesh>();
var meshRenderer = theText.AddComponent<MeshRenderer>();
textMesh.text = name;
textMesh.color = Color.red; //THIS IS THE NEW LINE
textMesh.transform.position = new Vector3(0, 5, 0);
theText.transform.position = new Vector3(0, 5, 0);
Hope I've helped you.
I changed TextMesh to TextMeshPro (which requires the import using TMPro;). TextMeshPro is experimental/unstable at the time of writing, and also the positioning seems to be inconsistent with the positioning of the basic 3D objects, but it's an acceptable solution for me at the moment.
If someone finds a real solution using TextMesh, I'm happy to select their answer as correct!

How to Add Display text and Click Event to a Dynamic Prefab Object created on Runtime in Unity

How to Add Display text and Click Event to a Dynamic Prefab Object created on Runtime in Unity.
This is my c# code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class InstantiateMarkerPin : MonoBehaviour
{
[Header("Settings")]
public Vector3 TargetPosition = new Vector3(0.09f, 0.5f, 1.1f);
// Instead of using Resources simply reference the
// created Prefab here
public GameObject gameObjectPinPrefab;
[Header("Outputs")]
public GameObject gameObjectPinInstantiate;
private void Start()
{
TargetPosition = new Vector3(0.09f, 0.5f, 1.1f);
gameObjectPinPrefab = (GameObject)Resources.Load("gameObjectPinPrefab");
//The object the script is attached to
GameObject world = this.gameObject;
//Instantiate the prefab
gameObjectPinInstantiate = Instantiate(gameObjectPinPrefab, TargetPosition, Quaternion.identity, world.transform);
Debug.Log("InstantiateMarkerPin class : Marker Location 2 :X, Y, Z : " + gameObjectPinInstantiate.transform.position);
}
}
Globe with pin object
In the Pin object i want to add a label and a click event
To add a Component to an object in code you can do something like:
Text t = gameObject.AddComponent<Text>();
t.text = "Whatever";
Also the label will noot render unless the object you are adding it is a child of a Canvas. You may want to get a reference to your canvas in the code and use gameObject.transform.parent = \\canvas object
Regarding the onclick I would just add a button to this object from the code:
Button b = gameObject.AddComponent<Button>();
b.onClick.AddListener(OnClick);
From here you just need to define a function elsewhere named OnClick, or whatever you choose to call it, that handles the click event. You may also want to make your button invisible and do whatever else seems necessary.

How to create new parent child gamobjects at runtime?

For a button click two new gameObjects are created and the second one is setting as a child of first one and first one is child of attached object. But it is not working / showing on hierarchy but the created object is not appearing in game window.
Here is the code:
public void CreateTextButtonClick(string text)
{
Debug.Log("Hey starting of this..");
//Create Canvas Text and make it child of the Canvas
GameObject txtObj = new GameObject("myText");
txtObj.transform.SetParent(this.transform, false);
GameObject pan = new GameObject("text");
pan.transform.SetParent(txtObj.transform);
//Attach Text,RectTransform, an put Font to it
Text txt = pan.AddComponent<Text>();
txt.text = text;
Font arialFont = Resources.GetBuiltinResource<Font>("Arial.ttf");
txt.font = arialFont;
txt.lineSpacing = 1;
txt.color = Color.blue;
//image
//GameObject back = new GameObject("image");
//back.transform.SetParent(txtObj.transform);
//Image i = back.AddComponent<Image>();
Debug.Log("Hey its done..");
}
What can be a solution to achieve this multi level object making?
You used SetParent properly in the first Object you want to be child of your Canvas by passing false to it which causes it to keep its local orientation:
GameObject txtObj = new GameObject("myText");
txtObj.transform.SetParent(this.transform, false);
But you did not do this for the "text" Object that will be child of the object above:
GameObject pan = new GameObject("text");
pan.transform.SetParent(txtObj.transform);
You can fix that by also passing false to it so that the UI component to keep its local orientation. Unrelated but I also think you should add a RectTransform the parent object too. Add RectTransform to anything that will be under the Canvas.
Your new code:
public void CreateTextButtonClick(string text)
{
Debug.Log("Hey starting of this..");
//Create Canvas Text and make it child of the Canvas
GameObject txtObj = new GameObject("myText");
txtObj.AddComponent<RectTransform>();
txtObj.transform.SetParent(this.transform, false);
GameObject pan = new GameObject("text");
pan.transform.SetParent(txtObj.transform, false);
//Attach Text,RectTransform, an put Font to it
Text txt = pan.AddComponent<Text>();
txt.text = text;
Font arialFont = Resources.GetBuiltinResource<Font>("Arial.ttf");
txt.font = arialFont;
txt.lineSpacing = 1;
txt.color = Color.blue;
}
In your commented code, it looks like you plan to add another child object with Image component too and I can already see that mistake there. Do not forget to do this too. You must otherwise, you will have issues. This applies to everything you plan to place under the Canvas.

UI text is not rendered but appearing in hierarchy — what is missing?

trying to show text dynamically created to the canvas but its not rendering.
After creating canvas an empty gameObject attached as child and the following script is attached to that. After running the object appears in hierarchy but not rendered.maybe I'm missing something:
GameObject o;
void Start() {
GameObject test = new GameObject("myTextGO");
test.transform.SetParent(this.transform);
// test.transform.SetParent(o.transform);
Text myText = test.AddComponent<Text>();
myText.text = "Hello there!";
}
Also tried few other combination but not text is not rendering. Need to know solution.
Three things required to do when creating UI text dynamically and manually:
Font
Proper Parenting
RectTransform (Now, automatically attached by Unity when UI component
is attached to a GameObject)
I assume that you are using the latest Unity version so you just need to do the first two:
Supply font for the Text component to use as mentioned this answer. Also, when using transform.SetParent, you have to supply false to it. This causes the UI component to keep its local orientation.
void CreateText(GameObject canvas, string text)
{
//Create Canvas Text and make it child of the Canvas
GameObject txtObj = new GameObject("myTextGO");
txtObj.transform.SetParent(canvas.transform, false);
//Attach Text,RectTransform, an put Font to it
Text txt = txtObj.AddComponent<Text>();
txt.text = text;
Font arialFont = Resources.GetBuiltinResource<Font>("Arial.ttf");
txt.font = arialFont;
txt.lineSpacing = 1;
txt.color = new Color(50 / 255, 50 / 255, 50 / 255, 255 / 255);
}
Usage:
public GameObject canvas;
void Start()
{
CreateText(canvas, "Hello there!");
}
That's how to create a text component manually but that should no longer be used. Let Unity do this automatically. The DefaultControls should be used to create UI Objects. It reduces the chances that the creation code will fail or that you'll run into similar issues in your question. Create the Text resources with DefaultControls.Resources then the Text itself with DefaultControls.CreateText.
void CreateText(GameObject canvas, string text)
{
DefaultControls.Resources uiResources = new DefaultControls.Resources();
GameObject uiText = DefaultControls.CreateText(uiResources);
uiText.transform.SetParent(canvas.transform, false);
uiText.GetComponent<Text>().text = text;
//Change the Text position?
//uiText.GetComponent<RectTransform>().sizeDelta = new Vector2(100f, 100f);
}
There is no font attached to the Text-object.
Try adding this line
myText.font = Resources.GetBuiltinResource<Font>("Arial.ttf");

Instantiate prefab in Unity

I'm instantiating a prefab panel in unity and i'm settings it's parent to another panel like this :
GameObject notificationPanel = (GameObject) Resources.Load("NotificationWindow");
Text notificationText = notificationPanel.GetComponentInChildren<Text>();
if (notificationType == NotificationType.Warning)
{
notificationText.color = Color.red;
}
notificationText.text = text;
GameObject newNotificationWindow =
(GameObject) Instantiate(notificationPanel, new Vector3(0, 0, 0), Quaternion.identity);
newNotificationWindow.transform.SetParent(Settings.NotificationHolder.transform);
However when instantiated it's with an insane size, the parent panel has a layout group with a fixed size of the cell's inside of it why isn't this affecting it ? The new panel is around 10 times bigger than my screen. In the hierarchy view the new panel appears as a child correctly under it's parent. Also the 'z' position is around - 3900 why ?
So After reading the Unity Documentation: Instantiating the UI element all you have to do is to call:
newNotificationWindow.transform.SetParent(Settings.NotificationHolder.transform, false);
The "false"represents worldPositionStays parameter and this scales the UI.
Let me know if this works for you.

Categories