Unity2d: Trying to change the color of a GameObject from a different class - unity3d

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

Related

Unity how to set a prefab property trought an array

Could you please help me to write the right syntax? I am stuck with the following code:
GameObject cube = (GameObject)Instantiate(cube_prefab, new Vector3(x, y, 0), Quaternion.identity, transform);
cube.GetComponentInChildren<TextMeshPro>.text = "test" **// WORKS FINE**
Take into account that inside my prefab i have more TextMeshPro, so my question is: how can I get to the second object if i can't access trought an array ? sounds weird for me
cube.transform.GetChild(0).GetComponent<TextMeshPro>().text = "AAA" // DOESN'T WORK
Thanks in advance
The GetChild(int) method is a method of transform. In your example, you're calling GetChild(0) from the GameObject instead. So the fix in your example would use the transform property of your "cube", find the child, then get the component of the child item:
GameObject cube = (GameObject)Instantiate(cube_prefab, new Vector3(x, y, 0), Quaternion.identity, transform);
cube.GetComponentInChildren<TextMeshPro>.text = "test" **// WORKS FINE**
cube.transform.GetChild(0).GetComponent<TextMeshPro>.text = "test"
Here's the Unity docs for GetChild(int).
If you wanted to iterate over the next level of children for your game object, you could do this:
var t = cube.transform;
var childCount = t.childCount;
for ( int i = 0; i < childCount; i++ )
{
if ( t.GetChild(i).TryGetComponent<TextMeshPro> ( out var tmp ) )
{
tmp.text = $"TextMeshPro found on child {i}";
}
}
Be aware, that this will only iterate over the direct children of "cube", not the children of those children. You would have to check the child count of each child to check further down the family tree.
Sorry if I sound like I'm preaching, but it seems you just try to guess what the syntax is, without knowing what it each thing really does, and it won't do you any good. You should look into methods with generics (especially how to call them) and try to write code meaningfully instead of throwing brackets here and there, and expect things to happen.
With that out of the way, let's look at your issue.
The name 'GetChild' does not exist in the current context, because your cube is of GameObject type, which indeed doesn't have a GetChild method. The component that does have it is Transform. You should call it like: cube.transform.GetChild(0)...
If you fix that, the next issue is that GetChild method doesn't use generics (<Type>) and even if it did, first you provide should provide a type in angle brackets, and then write regular brackets () to indicate method call. What you probably wanted is to first get child, and then to get a component in it: cube.transform.GetChild(0).GetComponent<TextMeshPro>().text = "test";
In cube.GetComponentInChildren<TextMeshPro>.GetChild(0).text you miss brackets: cube.GetComponentInChildren<TextMeshPro>().GetChild(0).text. Morover, the TextMeshPro doesn't have a GetChild method, you must have confused ordering of your method calls.
In cube.GetComponentInChildren<TextMeshPro>[0] you try to use syntax as if you were using arrays, while GetComponentInChildren is just a method, not a property that is an array.
To answer your question shortly: use yourGameObject.transform.GetChild(childIndex).GetComponent<TextMeshPro>().text transform.GetChild() to navigate down to your desired gameObject and only then call GetComponent (remember brackets!) to get to your text property.
the right syntax was
cube.transform.GetChild(0).gameObject.GetComponent().text = "test"
cube.transform.GetChild(1).gameObject.GetComponent().text = "test"

Unity how to Create Texts via script?

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.

Creating multiple buttons using input field in Unity

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.

Unity 5 change button text created with UnityScript

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";

Setting a textfield in a class in but displaying a number?

I'm learn as3, and building some exercises from the adobe online tutorials. I'm trying to do a very simple task and I think my code is exactly the same as the tutoriala nd it's not working! I just can't work it out...
I'm trying to change the textfield in a button from that buttons class.
The button is called GameButton, the textfield is called blabel and is classic text and dynamic text. Here is the code for the GameButton class. Instead of displaying "Click" as below it just changes the label to the number 1. The trace statement is working etc it is going there, but the text isn't passing through or something. Please help!!!
package {
import flash.display.MovieClip;
public class GameButton extends MovieClip {
public function GameButton() {
trace("Gamebutton has been created");
this.blabel.text = "Click";
stop();
}
}
}
The long and short of it is you can create the button in code, or else you can try listening for added to stage events coming from the parent object you're adding the children to (maybe the stage, maybe another DisplayObjectContainer). The problem with the listening method is I'm not sure how you would know which child just dispatched the event without making some messy code. I think the first option is generally easier and makes more sense, the only caveat is that you have to place the instances using x/y coordinates or apply scaleX, scaleY to stretch or shrink objects instead of doing it using the authoring tool. You can still use the drag and drop parts of flash to figure out coordinates and build individual movie clips etc.
Enough talk on to some code:
package
{
import flash.display.MovieClip;
public class GameButton extends MovieClip {
private var blabel:TextField; //This can be any display object class or a class that extends from a display object class (Sprite, MovieClip, MyCustomButton etc.)
public function GameButton() {
blabel = new TextField(); //The type after new, should be the same, or a sub-class (extension) of the type used in the variable declaration above
addChild(blabel);
//blabel.x=10; //optional over ten pixels from left
//blabel.y=10; //optional down ten pixels from top
//blabel.scaleX=.5; //optional half the width
//blabel.scaleY=2; //optional 2 times taller
trace("Gamebutton has been created");
blabel.text = "Click";
stop();
}
}
}