How to use UI.Text as a prefab in Unity? - c#

I've tried using this
Instantiate(entry, new Vector3(x, y, 0), Quaternion.identity);
It successfully created objects, as seen in my hierarchy. But I cannot see the text on the screen, even though there is a text assigned to it. I can only see an empty game object on the screen.
These screenshots show the game on play, and the selected object is the object instantiated through the script.
When I drag the prefab, it does not show anything on the scene. This happens to all my prefabs. The following are its components:

In new Unity3D UI system, every UI (Text, Button, Panel etc.) component that will be renderer on screen must have a parent Canvas component.
You actually do use such approach in your project, where you have Toolbar, List etc. that have parent called Canvas and which I suppose has Canvas component attached.
What you need to do is to move instantiated gameObject to be child of other gameObject that holds Canvas component.
As there can be multiple components of Canvas type, I would suggest to add possibility to assign root for instantiated objects inside your Script.
Script:
//Drag and drop this from inspector; make sure that dragged gameObject
//has Canvas component in it or above it (in parent)
public Transform EntriesRoot;
void Start()
{
var entry = Instantiate(entry, new Vector3(x, y, 0), Quaternion.identity);
//Put parent to our EntriesRoot
//EntriesRoot will be our new parent for entry in hierarchy
entry.transform.SetParent(EntriesRoot)
}

they need to be a child of a Canvas, that displays them.
// find canvas
GameObject canvas = GameObject.Find("Canvas");
// clone your prefab
GameObject text = Instantiate(entry, new Vector3(x, y, 0), Quaternion.identity);
// set canvas as parent to the text
text.transform.SetParent(canvas.transform);

For each instance, you might have to manually enable the guiTexture.

Related

Unity: Change UI gameObject parent and position without moving Child gameObject

I have a UI in Unity where I constantly move items from one place to another.
Some of said items are containers, and I decided to give each containers their own child gameObject representing and containing the actual container's content once opened (aka activated the gameObject). I chose to do it this way to be easier to track each container's actual containers.
What I want: When changing the item's parent (aka moving it around since all my parents have layout groups), the child gameObject should remain at the same world position
What I have: When changing the item's parent, the child gameObject changes world position
What I can do: I could reset the position of the child gameObject each time, as I do the first time the gameObject is instantiated using this code (the relative gameObject is stretched)
Vector3[] corners = new Vector3[4];
transform.parent.parent.GetComponent<RectTransform>().GetWorldCorners(corners);
float width = corners[2].x - corners[0].x;
float height = corners[1].y - corners[0].y;
RectTransform itemTransform = item.transform.GetChild(1).GetComponent<RectTransform>();
itemTransform.position = new Vector3(width / 2, height / 2);
What I want to know: Is there something built in Monobehavior or Unity that prevents a child gameObject from moving
Here are images step by step of one of the cases it would apply:
Here I have a bag item called "sac a dos" in my room
Now I have opened The bag, which shows up in the middle of the screen
I now have created a chest item called "Coffre" at the same place, causing the bag to be put as child of the chest's container child gameObject
Here I opened the chest, positioned at the right place, and showing the bag that was put as child of the chest's container child gameObject
Here I opened the bag in the chest, causing the bag's child gameObject to be misplaced since the bag's position changed
I think You should separate items data from their display.
When You have a common display of your elements write a Show method, where you could pass showed item data.
Example:
public class ItemDisplay : MonoBehaviour
{
public void Show(ItemData itemData)
{
this.gameObject.SetActive(true);
foreach (var property in itemData.properties)
{
DisplayProperty(property);
}
}
private void DisplayProperty(){...}
}

Unity: UI prefabs go invisible when i Instantiate it

I have a custom UI element in the Mainmenu scene that works fine, but when i make a prefab out of it, all the text and images become invisible, and the rect transform goes blank
The orginal prefab
the instatiated invisible prefab
You should instantiate it as a child object of Canvas.
Instantiate(prefab, thatCanvas.transform);

Reason for automatic creation of RectTransform

I'm creating 2 GameObjects.
One automatically gets a RectTransform without explicitely adding one, the other doesn't.
In this case, a RectTransform isn't added, but it can be accessed:
GameObject nCanvasGO = new GameObject("CanvasContainer");
Canvas nCanvas = nCanvasGO.AddComponent<Canvas>();
nCanvas.renderMode = RenderMode.WorldSpace;
nCanvasGO.AddComponent<CanvasScaler>();
nCanvasGO.AddComponent<GraphicRaycaster>();
RectTransform rtCanvasGO = nCanvasGO.GetComponent<RectTransform>(); //can be accessed, isn't null
This one does not have a RectTransform:
GameObject nAnimInfo = new GameObject("AnimInfo");
RectTransform rtAnimInfo = nAnimInfo.GetComponent<RectTransform>(); // is null
I would therefore like to ask if adding a Canvas component to a GameObject add a RectTransform or what else might be the reason here.
Thank you.
Yes, Adding a canvas to a Gameobject will automatically change the Transform to a RectTransform. This is because the rect transform is the 2D equivalent of Transform, with some additional functionality like anchoring.
From the Unity docs:
The Rect Transform component is the 2D layout counterpart of the Transform component. Where Transform represents a single point, Rect Transform represent a rectangle that a UI
element can be placed inside. If the parent of a Rect Transform is also a Rect Transform, the child Rect Transform can also specify how it should be positioned and sized relative to the parent rectangle.
The docs don't actually clearly state anywhere that a transform gets replaced by RectTransform automatically though...
Furthermore Canvas depends on RectTransform, and can thus not be used without having a RectTransform. You can see ths when you try to delete the rect transform from a canvas. It will pop up saying "Can't remove RectTransform because Canvas depends on it".
Any other UI component you add to a GameObject will also automatically add the Recttransform component (I.E image, text etc.). this has the same reason as Canvas, that they depend on RectTRansform.
You will also notice that any GameObject you make that is a child of a canvas will also have a RectTransform by default, so that it can anchor itself relative to the parents (canvas in this example) rect transform. You can delete the rectTransform from these Objects as long as none of its components depend on RectTransform. Though i don't see why this would be desired, as any child of a canvas should be some form of UI like an image or text. And should thus require the RectTransform.

Unity prefab as an object in inspector asking for attaching object

I am initiating prefabs as objects and then trying to do something using these objects that have those prefabs. However, in the inspector, its asking to attach objects that are actually already attached via code.
Code
public float hitspeed=2f;
public GameObject target, mytarget;
public GameObject arrow,myarrow;
//Use this for initialization
void Start (){
myarrow = Instantiate(arrow, new Vector3(0.02f, -3.98f, 0), transform.rotation);
mytarget = Instantiate(target, new Vector3(-0.06435323f, 2.325303f, 0f), transform.rotation);
}
Inspector
Error
[06:34:34] UnassignedReferenceException: The variable arrow of knife has not been assigned. You probably need to assign the arrow variable of the knife script in the inspector.
[06:34:39] UnassignedReferenceException: The variable myarrow of knife has not been assigned. You probably need to assign the myarrow variable of the knife script in the inspector.
With your object selected so you can see the inspector shown in the image
Go to your Project window, find your prefab.
Drag it to the the inspector where it says "none."
You can also click the little target/circle next to "none" and choose from a list.
It is true that you seem to have assigned myarrow and mytarget, however, you have instantiated them using target and arrow. You have set target using the gui, but not arrow. You must also set arrow.
In general, and to quote from another answer:
[arrow and target have] to be a prefab that you've already created in the Editor and
dragged/dropped onto the Inspector window for this object.
Ensure you:
Created a prefab
Selected this object in the Editor, so the Inspector appears
Drag/dropped that prefab onto the "arrow"/"target" field in the Inspector

Gameobject instantiated in canvas shows up behind other canvas items

In my game, if it is the first time the player has ever played the game then I have an image that is displayed. I instantiate it in the canvas like so:
if (PlayerPrefs.GetInt("First Time", 1) == 1)
{
introEnabled = true;
//pause all activity
pause.pauseOrResume();
intro = Instantiate (Resources.Load ("intro"), transform.position, Quaternion.identity) as GameObject;
Canvas canvas = GameObject.Find("Canvas").GetComponent<Canvas>();
intro.transform.SetParent(canvas.transform, false);
//robot = Instantiate (Resources.Load ("robot"), transform.position, Quaternion.identity) as GameObject;
PlayerPrefs.SetInt("First Time", 0);
PlayerPrefs.Save();
}
I can see in the inspector when the game is running that when the object is created, it does show up in the canvas. I just have no idea why it won't show up on top of all of the other objects in the canvas.
The canvas rendering mode is set to "Screen space - Overlay" and it is set to 0 in the sort order. The game object being instantiated also has a sort order of 0 and it is in the default layer.
Nothing I have tried has worked. The z values make no difference and even putting the canvas and the instantiated object in the Default layer and setting the canvas to a sort order of 2 and the instantiated object to a sort order of 1 (so it is rendered first) does not make a difference.
What you want is to use transform.SetAsLastSibling() . The CanvasRenderer renders the GameObjects in order according to their sibling index's (position in the hierarchy), from top to bottom.
However, after examining your code further I noticed something and I should say that if you are trying to instantiate the intro screen, I would highly recommend to instantiate it with it's own Canvas, instead of parenting it to the existing one. Something that significant should have it's own dedicated Canvas.
Update: The problem here is that you are instantiating GameObjects with a transform and Sprite renderer. Canvas UI gets rendered last, over all mesh layers, so if you want your newly instantiated GameObjects to participate, they will need to have RectTransform and Image components instead.
Instead of Default layer change its layer to UI.
You code seems fine, it might be problem related to the gameobject where this script is attached (because you are passing transform.position in Instantiate). it might be positioning the Instantiated game object off the canvas. Try like this once it might work.
intro = Instantiate (Resources.Load ("intro")) as GameObject;
and after setting its parent(very important), set it's position like this
intro.transform.localPosition = new vector3(0,0,0);

Categories

Resources