I'm trying to create Texts via script. I want to create texts with the name of objects of a certain tag.
"For example, if I have two objects named Cube and Sphere and both have a tag of "TargetObj" then their names should be displayed as texts on the screen(in the case Cube, Sphere)"
I want to achieve this regardless of the number of objects. so a loop is needed.
Here is what I've tried so far.
[SerializeField] GameObject LevelCanvas;
targetObjects = GameObject.FindGameObjectsWithTag("TargetObj");
foreach (var obj in targetObjects)
{
Text mytext = LevelCanvas.AddComponent<Text>();
mytext.text = "Find " + obj.name;
Font ArialFont = (Font)Resources.GetBuiltinResource(typeof(Font), "Arial.ttf");
mytext.font = ArialFont;
mytext.material = ArialFont.material;
}
it only shows one object name although I have 2 more objects that were supposed to be shown as well.
You need to create a text object on a new gameobject.
static Text CreateText(Transform parent)
{
var go = new GameObject();
go.transform.parent = parent;
var text = go.AddComponent<Text>();
return text;
}
var mytext = CreateText(LevelCanvas.transform);
myext.text = ...
Many components in unity can only be added once per game object. That means you need a separate game object for every text you want to show.
A typical way to approach this is to create a "prefab" of a game object which has a text element already. This way you can set a default font and other settings.
Then in code you use the Instantiate method on that prefab and via GetComponent() you can access the text component instance to set the desired string to display.
Related
I just want to ask how can I multiple the buttons by using the input field? Like for example, I typed 100 in the input field and then the buttons will become 100. Please bear in mind that I'm new in Unity. Thank you!
First you need to define what button you want to instantiate, on the UI Canvas or a 3D world button.
public class TestingScript : MonoBehaviour{
// the button to create
public GameObject button;
}
You need to create a prefab or assign an existing button in the world for the script to use as a template when creating them. Next you need to create the input field itself and assign the reference to it through code or in the inspector view, here I am going to have it assigned in the inspector.
// assigned in inspector view
public TMP_InputField inputField;
It should look like this in the component view
Now where you call the function is your choosing, I am doing it through a unity button on which I have the script attached
The method here would look something like this
public void CreateButtons()
{
// here we assume the input is always an integer, otherwise you would create a try catch clause
int amount = int.Parse(inputField.text);
// using world 0 position here, you would need to define where you want them yourself
Vector2 pos = new Vector2(0, 0);
for (int i = 0; i < amount; i++)
{
// the loop will execute the amount of times read from input field
Instantiate(button, pos, Quaternion.identity);
pos.x += 0.5f;
}
}
Note I am using TextMeshPro elements here but the standard unity ones would work too.
So I can see that the GameObject is in the List but it gives me a "Object reference not set to an instance of the object" error when trying to change color to it.
public class Paint : MonoBehaviour
{
//inside Create is where the list of objects are created
Create create = new Create();
ColorPicker colorPicker = new ColorPicker();
public void SetColor()
{
create = GetComponent<Create>();
if (create.GraffitiLetters.Count > 0)
{
colorPicker = GetComponent<ColorPicker>();
for (int i = 0; i < create.GraffitiLetters.Count; i++)
{
create.GraffitiLetters[i].GetComponent<Image>().color = colorPicker.GetColor();
}
}
}
}
I bet it has something to do with me having to get hold of the component first but I dunno?
----------------------EDIT--------------------------
OK, new attempt for the same problem.
I have a class called ColorPicker. Inside of it I have a Color color; which gets an rgba value.
Now I want to grab that value from another class. How?
Inside my Paint class I tried this.
ColorPicker colorPicker = new ColorPicker();
colorPicker = GameObject.Find("color").GetComponent<ColorPicker>();
Debug.Log(colorPicker.color);
I've also tried various other ways but I just don't get it. seems like a simple problem.
--------- Second edit------------------
I have tried all of these. I can't understand it. all the questions that seem similar has gotten one of these answers. nothing works for me.
//This Gets NullReferenceException
//Debug.Log("test color" + colorPicker.GetComponent<ColorPicker> ().GetColor());
//This Gets NullReferenceException
//colorPicker.GetComponent<Color>();
//Debug.Log("test 2" + colorPicker.color);
//This Gets NullReferenceException
// colorPicker.transform.Find("color");
// colorPicker.GetComponent<Color>();
// Debug.Log("test 3 " + colorPicker.color);
You did not specify what line gives the Null Reference Exception, so proper help cannot be given. I will write down some things that may be the issue:
Create create = new Create();
This is not the issue, but it's confusing. I don't think you want to instansiate this class, it makes no sense. What value is an empty instance. You're later setting it to this GameObject's component, which makes sense through create = GetComponent<Create>();.
So I'll assume that create is null. This means you haven't attached the Create component/script to the GameObject that has the Paint script on it.
If that is not the case, I'm guessing your issue lies in the next step, namely that the create.GraffitiLetters[i] may not have an Image component.
Sidenote: Since your Paint class is dependant on its GameObject having a Create script, you could set an attribute on the class, that validates it for you:
[RequireComponent(typeof(Create))]
public class Paint: MonoBehaviour
I am developing an inventory system for my game. I have the UI set up, I have this:
As you can see, I have a Bag Panel, inside it there are a number of slots, that are the slots you can see in the right part of the image.
I am populating it this way:
inventoryPanel.SetActive(true);
GameObject bagObject= GameObject.Find("Bag");
List<GameObject> childrens = new List<GameObject>();
Transform[] listSlots = bagObject.GetComponentsInChildren<Transform>();
foreach(Transform child in listSlots)
{
if(!child.gameObject.name.Equals(bagObject.name))
childrens.Add(child.gameObject);
}
for (int i = 0; i < character.ItemsInInventory.Count; i++)
{
if (character.ItemsInInventory[i] != -1)
{
GameObject slot = childrens[i];
print("Slot: " + slot.name);
Image imagen = childrens[i].GetComponent<Image>();
string ruta = GetRutaSprite(character.ItemsInInventory[i]);
Sprite icono = Resources.Load<Sprite>(ruta);
imagen.name = "Item";
imagen.sprite = icono;
print("parent is " + slot.name);
imagen.transform.SetParent(slot.transform);
}
}
When I run this, I got this:
As you can see, Slot0 has dissapeared, and it is being substituted by item. What I would like to achieve is Item be a son of Slot0. I dont know why it happens this way, since I am setting the image's parent to the slot. In the print("Slot: " + slot.name); line it prints "Slot0", but in print("parent is " + slot.name); line it prints Item. Why is that? Also, the sword looks like it is behind something...it is not displayed correctly. I would like to show the icon AND the slot border.
How can I populate my inventory properly?
In your code, you just found the slot, get an image (which is border), and replace sprite on it with your items sprite.
You need to instantiate new image instead. It can be a prefab, or you can use your border image to create a copy from it (do not forget to change color). Or, if you have a separate Image inside slot, and you want to set the sprite for it, you need to get reference on it, but not on border. For this, you need a script on your slot, holding that reference.
for make a minimal changes in your code, you can do like this:
Sprite icono = Resources.Load<Sprite>(ruta);
Image newImage = Instantiate(imagen, slot.transform);
newImage .name = "Item";
newImage .sprite = icono;
print("parent is " + slot.name);
newImage.transform.SetParent(slot.transform);
But I defenitely recommend to rework it: at least, add a script on your slot, holding a reference to your second Image (which is not border).
In my 2D project I create a canvas and a button in code. I would like to set the text of the button in code, but after numerous attempts I can't seem to do it.
My UnityScript code:
#pragma strict
var loginButton : UnityEngine.UI.Button;
function Start () {
var canvas = new GameObject ("canvas", Canvas);
var instance : UnityEngine.UI.Button = Instantiate(loginButton);
instance.GetComponent(UnityEngine.UI.Text).text = "login"; //Error below
instance.transform.position = Vector2(0,0);
instance.transform.SetParent(canvas.transform);
}
This provides an error
"NullReferenceException: Object reference not set to an instance of an object
GameLogicLogin.Start () (at Assets/GameLogicLogin.js:11)"
--------------------------------Edit---------------------------------------
The generated hierarchy looks like this: http://puu.sh/iMYe6/4f4a8f545c.png
On the left at the bottom is the prefab I link to the script.
The following line doesn't cause an error and seems to change the text, but the change doesn't show up in game nor does the original text assigned to the "Text"in the prefab.
instance.GetComponentInChildren(UnityEngine.UI.Text).text = "login";
If you would of built your button in the unity editor you could easily change its text in script like this:
var button = GameObject.Find("buttonObjectName").GetComponent<Button>();
button.GetComponentInChildren<Text>().text = "What ever you like";
I imagine you can easily adjust this to fit your needs without being spoon fed.
You are instantiating a UnityEngine.UI.Button, that doesn't have a component for UnityEngine.UI.Text hence the error.
Is there any reason why you are instantiating that object?
If you are linking in the editor a game object to loginButton, and I think you are, you should do something like this:
var comps = loginButton.gameObject.GetComponentsInChildren(UnityEngine.UI.Text);
comps[0].text = "login";
I have just started unity. I have 4 Images(sprites) aligned in a grid.
As soon as i touch the particular chocolate, its texture changes[I wrote a code for that]. There is a button on screen.After pressing the button, I want to move only those chocolates whose texture has been changed.
I know the following move code but i don't know how to use it here.
void Update () {
float step=speed*Time.deltaTime;
transform.position=Vector3.MoveTowards(transform.position,target.position,step);
}
I just don't know to move that particular sprite whose texture is changed. Thanks
Do you want to be moving the sprites over the course of a duration or instantly?
If it's over the course of a duration I suggest you use Lerp. You can Lerp between two Vector.3's in a time scale. Much cleaner and once learned a very useful function.
Code examples below:
http://docs.unity3d.com/ScriptReference/Vector3.Lerp.html
http://www.blueraja.com/blog/404/how-to-use-unity-3ds-linear-interpolation-vector3-lerp-correctly
However if you want to move it instantly. This can be done very easily using the built in localPosition properties which you can set in or outside the object.
Set your changed sprites Bool moved property (create this) to true on click (if you're using Unity 4.6 UI canvas then look at the IClick interfaces available for registering mouse activity in canvas elements) and then when you press the button, loop through a list in a handler file which contains all your button texture objects and move those that the moved property is set to true for.
foreach(GameObject chocolate in chocolateList)
{
if (chocolate.moved == true)
{
gameObject.transform.localPosition.x = Insert your new x position.
gameObject.transform.localPosition.y = Insert your new y position.
}
}
However please do clarify your intentions so I can help further.
EDIT 1:
I highly suggest you make your sprites an object in the canvas for absolute work clarity. This makes a lot of sense as your canvas can handle these type of things much better. Use Image and assign your image the sprite object (your chocolate piece), define it's width and height and add a script to it called "ChocolatePiece", in this script create two public variables, bool moved and int ID, nothing else is required from this script. Save this new object as your new prefab.
Once you've done this in a handler script attached to an empty gameobject in your canvas make a list of gameobjects:
List<GameObject> chocolatePieces = new List<GameObject>();
You'll want to at the top of your handler script define GameObject chocolatePiece and attach in your inspector the prefab we defined earlier. Then in Start(), loop the size of how many chocolate pieces you want, for your example lets use 4. Instantiate 4 of the prefabs you defined earlier as gameobjects and for each define their properties just like this:
Example variables:
int x = -200;
int y = 200;
int amountToMoveInX = 200;
int amountToMoveInY = 100;
Example instantiation code:
GameObject newPiece = (GameObject)Instantiate(chocolatePiece);
chocolatePieces.Add(newPiece);
newPiece.GetComponent<ChocolatePiece>().ID = i;
newPiece.transform.SetParent(gameObject.transform, false);
newPiece.name = ("ChocolatePiece" + i);
newPiece.GetComponent<RectTransform>().localPosition = new Vector3(x, y, 0);
From this point add to your positions (x by amountToMoveInX and y by amountToMoveInY) for the next loop count;
(For the transform.position, each count of your loop add an amount on to a default x and default y value (the position of your first piece most likely))
Now because you have all your gameobjects in a list with their properties properly set you can then access these gameobjects through your handler script.