How to associate Price with Different item in unity - unity3d

I am newbie in unity. i am facing a small Problem. I have a different number of items and i want to associate Different Price with them .
but i dont know How to access Text(script) component in Unity? ?????
Lets says Here is the book shop every book Container Have different price
Here what i try to do but i don't know how to access this text Using Script
Thanks in advance

Find the "NumericalScore" GameObject with GameObject.Find then get the Text component from it with the GetComponent function.
//Find the Text GameObject
GameObject textObj = GameObject.Find("NumericalScore");
//Get the Text component
Text text = textObj.GetComponent<Text>();
string bookText = text.text;
Now, let's say that the each book has different names but with a Child text with the-same name called "NumericalScore", find the book name first then use transform.Find to find the child Text GameObject before using the GetComponent function to get the Text component.
//Find Book
GameObject book = GameObject.Find("BookName");
//Find Child Text GameObject
GameObject textObj = book.transform.Find("NumericalScore").gameObject;
//Get the Text component
Text text = textObj.GetComponent<Text>();
string bookText = text.text;

Related

How do I arrange a list of buttons into rows of 4

I am trying to display the same game object in a table form of 4 columns and 2 rows so it would look like this:
GO GO GO GO
GO GO GO GO
G0 - gameObject
My gameObject is a button that can be pressed and has a text element on it to display the name of the profile on the button.
I have a List of strings of the names that i need to display on these GO buttons in the table form but i am struggling to position them correctly.
At the moment i have gotten to the point where i can Instantiate them so they all appear on the screen when the game is running, now i just need some advice on how i can position them properly in the format mentioned above.
How do i do this?
This is my code that i used to get the names and add them to the List:
private void GetProfiles()
{
List<string> profileNamesList = new List<string>();
if (Directory.Exists(filePath))
{
string[] files = Directory.GetFiles(filePath);
profileTileTemplate.SetActive(true);
foreach (var file in files)
{
string name;
name = file;
int index = name.IndexOf(filePath + "/", System.StringComparison.OrdinalIgnoreCase);
if (index >= 0)
{
int pathIndexEnd = index + filePath.Length + 1;
int stringLength = name.Length - pathIndexEnd - 5;
name = name.Substring(pathIndexEnd, stringLength);
}
profileNamesList.Add(name);
}
}
DisplayProfiles(profileNamesList);
}
private void DisplayProfiles(List<string> names)
{
}
I have tried using a for loop with in another for loop but i just end up instantiating multiple of the same game object.
This is what i get now:
And this is what i want it to look like:
This is kind of two questions, and I just realized that Unity has a built in component that will do this automatically, so I'll leave the three answers below.
How do I arrange UI gameobjects in rows?
Since it seems like you want to do this for UI elements there's actually a very easy solution. Add an empty GameObject as a child of your Canvas and add a Vertical LayoutGroup component. Add two children to that with horizontal layoutgroups. Add four placeholder prefabs of your gameobject to each horizontal layout group. Arrange them and configure the settings to get them looking the way you want (and make note of what happens if you add fewer than four items!)
Once you have it all set up, delete the placeholders. Then you can add your gameobjects to the horizontal group using Instantiate(Object original, Transform parent) (link) to parent them to the layout group, which will keep them arranged neatly. You can keep a list of those groups and each time you add four, switch to the next parent.
A neater way that seems to fit your use case (assuming there can potentially be more than 8 profiles) is to make a Scroll View that holds horizontal layout groups, which will each be a row of entries. That way instead of tracking which parent you want to add gameobjects to, you can just instantiate a new row every time you pass four entries.
If you're sure there will only ever be eight or fewer, the easiest thing to do would just be arrange eight blank buttons in the UI however you want them to appear. Then keep a list of the eight buttons and edit the text/image on them, no instantiation or looping necessary.
How do I split up a list of gameobjects into rows?
The actual code to process the list is below. This is just an example and there are plenty of different ways to do it, but I thought this demonstrated the logic clearly without depending on what UI elements you choose. As a rules of thumb, make sure to figure out the layout elements you like in Unity first using placeholders (like scroll view etc) and then figure out the code to fill them in. In other words, instantiating and laying out UI elements at runtime is a great way to give yourself a headache so it's best to only do it when you need to.
List<string> profileNamesList = new List<string>();
public int entriesPerRow; //only public so you can edit in the inspector. Otherwise, just use the number per row in your prefab.
public GameObject profileRowPrefab;
public GameObject scrollViewLayout;
private void DisplayProfiles(List<string> names)
{
int i = 0;
while( i < names.Count ) //"while the list has more names"
{
//create a new row as a child of the scroll view content area
//and save a reference for later
GameObject go = Instantiate(profileRowPrefab, scrollViewLayout);
for(j = 0; j < entriesPerRow; j++) //"add this many names"
{
if(i < names.Count)
{
//instantiate a button, or edit one in the row prefab, etc.
//depending on how you're doing it, this is where you'd use the go variable above
YourProfileButtonCreationMethod(names[i]);
i++;
}
else
{
//we've finished the list, so we're done
//you can add empty placeholders here if they aren't in the prefab
break;
}
}
}
}
YourProfileButtonCreationMethod will depend completely on how you want to implement the UI.
I wish I had thought of this an hour ago, but I've never used it myself. Unity has a built in layout feature that will do this for you (minus the scrolling, but you may be able to nest this in a scroll view).
How do I arrange UI elements in a grid?
Instead of making your own grid with horizontal and vertical layout groups, you can use the Grid Layout Group. Then just instantiate each item in the list as a button with the grid layout as their parent (see above). Here's a short video tutorial that shows what the result looks like.

How to get child sprite from Multiple Sprite?

I want to get spesific sprite like 'ArmL' from spritesheet with multiple mode.
I have lots of multiple sprites so I need to use like below;
How can i achieve that ?
Public Sprite[] itemArmors;
examplesprite.sprite=itemArmors[ArmL];
You need to drag and drop ArmL into the inspector
public Sprite[] itemArmors;
examplesprite.sprite=itemArmors[0]; // refers to the first element in the itemArmours sprite array
in the inspector make sure that the first element you add to itemArmours is ArmL. This is called indexing. If you just want to get ArmL don't use an array and just use:
public Sprite ArmL;
examplesprite.sprite = ArmL;

Unity Update Text on Gameobject initiated from script from other Gameobject

I am developing for the HoloLens and I Made an object that follows me around. This Gameobject is actually an UI Canvas with text in it which I set like this because i want to keep the original object as well. (Just like in the MS example):
/// <summary>
/// The object to tag along set in the unity editor
/// </summary>
public GameObject ObjectToTagAlong;
/// <summary>
/// The instantiated object to tag along that follows you around.
/// </summary>
private GameObject instantiatedObjectToTagAlong;
this.instantiatedObjectToTagAlong = GameObject.Instantiate(this.ObjectToTagAlong);
this instantiatedObject tags along just fine but now I want to update the Text on instantiatedObjectToTagAlong but have no idea how to do this. (I can very easily update the text on the 1st object but i want to do it this way)
Does anyone know how to update the text on a gameobject that is initiated from another GameObject?
To build on what Serlite commented with, you need to use GetComponent in combination with another script.
public class MyTextUpdater: MonoBehavior
{
public Text SuperText2;
}
Apply MyTextUpdater to your ObjectToTagAlong prefab (or GameObject if not a prefab) and, in the editor, set the value of SuperText2 to the Text object you want to update (typically this is a child of the ObjectToTagAlong GameObject).
Now anytime you want to update that Text object on your instance, instantiatedObjectToTagAlong, you can do this:
MyTextUpdater text = instantiatedObjectToTagAlong.GetComponent<MyTextUpdate>();
if (text!=NULL && text.SuperText2!=NULL) { /*do whatever you need to do on the text.SuperText2 object*/ }
EDIT:
When Unity instantiates a copy of a GameObject, it makes a "deep" copy of sorts, meaning that the copy will have the exact same structure of child GameObjects.
Original Copy
- Child A - Child A (copy)
- Child B Instanitate => - Child B (copy)
- - Grandchild A - - Grandchild A (copy)
Each child is instantiated with it's own new copy. On top of that, if Original has a MonoBehavior script that points to one of it's children (or grandchildren etc), Copy will have a script that points to the appropriately copied child.
MyTextUpdater [Original] MyTextUpdater [Copy]
- SuperText2 = Child B => - SuperText2 = Child B (copy)
Regarding the question of why have the extra script (the MyTextUpdater script):
Original is just a GameObject. In the editor you can see it has children, but that does not represent a class. You can not do something like this in a script:
Original.ChildB.Text = "Hello World!";
in the same way, you can't do this:
Copy.ChildB.Text = "Hello Copy World!";
You could create code to iterate through all the children of the GameObject looking for a child with the correct name ("ChildB"), but that is inefficient and probably bad programming.
The better way is to create a script class that actually does give you access to the child as a field in that class. And that is where the MyTextUpdater script comes in.
This would be invalid:
GameObject Copy = Instantiate(Original);
Copy.SuperText2.Text = "Some text here";
Copy does not have a field or method called SuperText2, or ChildB, or whatever you would call it. But you could do this:
GameObject Copy = Instantiate(Original);
MyTextUpdater mtu = Copy.GetComponent<MyTextUpdater>();
mtu.SuperText2.Text = "Some text here";
Assuming of course that you applied the MyTextUpdater script to Original and made the right connections to the child text component.

Do I have to create a reference for each text I have in a panel, if I want to access them to modify?

I have a panel with 8 text field, 4 are used as descriptive field (what a label would do, basically), while the other 4 are modified with values.
I am creating a GameObject variable for every element that I have in the panel, using find to find the specific text element. I can leverage on the fact that each text object has only one text object attached to it, so I can address to it directly with GetComponent
panel_info = GameObject.Find("infopanel");
textfield1 = GameObject.Find("text_name");
textfield2 = GameObject.Find("text_age");
textfield3 = GameObject.Find("text_role");
textfield4 = GameObject.Find("text_field");
textfield1.GetComponent<Text>().text = "joe";
textfield2.GetComponent<Text>().text = "22";
textfield3.GetComponent<Text>().text = "striker";
textfield4.GetComponent<Text>().text = "attack";
While this works, I can't foresee myself creating 20-30 objects if a panel has more info to display.
Since I have the reference to the object Panel, is there a way to address directly the text field which is a child of the panel, using the text field name for example?
So if a panel has 4 text field, I can modify each of it addressing directly by name, and then using GetComponent<Text>().textto change the value.
You MUST NOT call GetComponent<Text>() each time you want to access/modify text.
This is an extremely basic fact about Unity.
It is immediately mentioned in the relevant manual entries.
Since you have 8 textbox and I don't know how long you update each one. It would be good if you cache all of them in the beginning of the game then use them later on without GetComponent<Text>(). This will improve performance a lot and make your frame-rate happy.
Array looks good for something like this. And you need to comment each one too.
public Text[] textBoxArray;
On the editor, Expand the "Text Box Array" and change the array Size to 8.
Now drag each GameObject with the text to the arrays in order. If you do it in order, you can easily remember their names and be able to access them in order.
For example, if the first text gameobecjt you dragged to the array is called text_name, the access it, you use textBoxArray[0]. The second text which is text_age can be accessed with textBoxArray[1]. .....
To make it easier for you later on, you should have multiple line comment that describes which array points to what.You do this so that when you return to modify your code months after, you won't have to look around in the Editor to find what points to what. For example:
/*
textBoxArray[0] = text_name
textBoxArray[1] = text_age
textBoxArray[2] = text_role
textBoxArray[3] = text_field
*/
No performance lost and that decreases the amount of code in your game.
Initializing the arrays by code instead of the Editor
Assuming you want to initialize the arrays by code instead of the Editor. You can do it in the start function like below.
public Text[] textBoxArray;
void Start()
{
//Create arrays of 8
textBoxArray = new Text[8]; //8 texts
//Cache all the Text GameObjects
textBoxArray[0] = GameObject.Find("/infopanel/text_name").GetComponent<Text>();
textBoxArray[1] = GameObject.Find("/infopanel/text_age").GetComponent<Text>();
textBoxArray[2] = GameObject.Find("/infopanel/text_role").GetComponent<Text>();
textBoxArray[3] = GameObject.Find("/infopanel/text_field").GetComponent<Text>();
}
You should notice that GameObject.Find() starts with "/" and that increases performance too as it will only search for Texts under "infopanel" instead of searching in the whole scene.
Assuming that your hierarchy is setup that all your TextMeshes are children of the panel, you could use the Transform.Find method to get each child, then it's TextMesh, and assign a value.
So, for example, if you wanted to assign the value "Joe" to the TextMesh attached to "text_name", which in turn is a child of "infopanel", you could do the following
panel_info = GameObject.Find("infopanel");
panel_info.transform.Find("text_name").GetComponent<TextMesh>().text = "Joe";

Unity3D : Unable to change TextMesh in instantiated object

I instantiate an object and change the text mesh inside it using the below code.
GameObject folder = (GameObject)Instantiate(prefab,<newLocation>,Quaternion.identity);
folder.name = "Folder1";
TextMesh content = GameObject.Find("Folder1").transform.GetChild(0).transform.GetChild(3).
gameObject.GetComponent<TextMesh>();
content.text = "New Content";
But, when I run the scene, the text mesh still has the value from the prefab and is not updated. Has anyone faced a similar issue or any idea on how to resolve it?
You mentioned that the item gets updated properly but then when you create new ones, it does not work anymore.
I would think your problem is that you are naming them with the same name "Folder1". Then you are looking for an object called Folder1 and the first one is returned.
GameObject folder = (GameObject)Instantiate(prefab,<newLocation>,Quaternion.identity);
folder.name = "Folder1";
TextMesh content = folder.transform.GetChild(0).transform.GetChild(3).
gameObject.GetComponent<TextMesh>();
content.text = "New Content";
this could fix your problem. Notice this is no longer looking for an item but using the reference from the new object.
Are you sure you're getting the right object? Your GetChild's are a bit worrying. Maybe you can try giving your object a tag and searching for that instead.
So, you set the tag of the gameobject that has your textmesh to HasTextMesh and then in your code do:
GameObject folder = (GameObject)Instantiate(prefab,<newLocation>,Quaternion.identity);
TextMesh content = GameObject.FindWithTag("HasTextMesh").GetComponent<TextMesh>();
content.text = "New Content";