Unity how to set a prefab property trought an array - unity3d

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"

Related

Unity 2D - how to check if my gameobject/sprite is below ceratin Y lvl?

I've been trying to get a script working to check if my player is below a certain Y lvl, for a platformer. so it can be respawned to the beginning, But how do I put the y lvl inside a variable to check it? i cant figure it out lol
In the Update() run something like:
if(player.transform.position.y < 1)
{
//do something
}
where 'player' is the GameObject in question.
I am assuming you want to just want to compare (==, <=, >=, all that jazz is what I mean by comparing just in case you were not aware) the Y value to something like 10 for example. This is easy and you don't even need a variable necessarily for this.
//For the object position relative to the world
if(transform.position.y == 10) //"transform" gives you acces to the transform component
{ //of the object the script is attached to
Debug.Log("MILK GANG");
}
//For the object position relative to its Parent Object
if(transform.localPosition.y == 10)
{
Debug.Log("MILK GANG");
}
If you want to change the value of the position of your object then
transform.position = new Vector2(6, 9)//Nice
//BTW new Vector2 can be used if you dont
//want to assign a completely new variable
However, if you want to get a reference (Basically a variable that tells the code your talking about this component) to it.
private Transform Trans;
void Awake() //Awake is called/being executed before the first frame so its
{ //better than void Start in this case
Trans = GetComponent<Transform>();
Trans.position = new Vector2(69, 420); //Nice
}
This is the code way of doing it but there's another way that uses Unity
[SerializeField] private Transform Trans;
//[SerializeField] makes the variable changeable in Unity even if it is private so you
//can just drag and drop on to this and you good to go
Hope this help
if it doesn't
then welp I tried lel
You can use a script added to gameobject to check transform.position of the object.
if(transform.position.y < ylvl)
{
//do something
}
where ylvl is the integer of the height you want to check

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

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

How to find all Cube game Object in the scene?

I'm looking for a way to find all CubeGameObject in the scene. I'm trying to do this :
Cube[] ballsUp = FindObjectsOfType (typeof(Cube)) as Cube[];
But cube isn't a game object type apparently.
I think i need to use something related to PrimitiveType but can figure out what and how to use it...
Thanks
Your Cube is of primitive type. And Primitive type objects are not possible to find using FindObjectsOfType.
There are many ways to solve the above problem. The easiest is by using tags.
When you instantiate your cube object you can use tag "Cube".
GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
cube.tag = "Cube";
Then you can get all the cube objects in scene with cube tags using
GameObject[] arrayofcubes = GameObject.FindGameObjectsWithTag("Cube");
This will give all the array of GameObject cubes in the scene.
FindObjectsOfType can be used to find gameobjects with attached classed and not primitive types.
Another way to proceed is finding all objects with MeshFilters and Searching for the Desired primitive name in the mesh filter arrays
string[] meshNames = new string[5] {"Cube", "Sphere", "Capsule", "Cylinder", "Plane"};
MeshFilter[] allMeshFilters = FindObjectsOfType(typeof(MeshFilter)) as MeshFilter[];
foreach(MeshFilter thisMeshFilter in allMeshFilters)
{
foreach(string primName in meshNames)
{
if (primName == thisMeshFilter.sharedMesh.name)
{
Debug.Log("Found a primitive of type: " + primName);
}
}
}
Geeting all the Object by their primitive type (C#)
You could try using a script. Let's say your GameObjects have a script MyScript, then you could FindObjectsofType GameObject and GetComponent Myscript.
Hope this helps. Although, I know it's not the answer you want, it's definitely an idea worth trying as a last resort :)
You could try this. If you are using the cube primitive of unity the mesh should be called "Cube" and while running "Cube Instance".
var gameOjects = GameObject.FindObjectsOfType<GameObject>();
foreach (var gameOject in gameOjects)
{
var meshFilter = gameOject.GetComponent<MeshFilter>();
if (meshFilter != null && meshFilter.mesh.name == "Cube Instance")
Debug.Log(gameOject.name);
}
tough this isn't very elegant or robust.
A more appropriate way would be to tag all cubes and get them by "FindGameObjectsWithTag"
Then recommended way from Unity of doing this is to create a tag and then use GameObject.FindGameObjectsWithTag to find all of them. GameObject.FindGameObjectsWithTag returns array of objects in this tag.
For example, create a tag called "cubeTags" then go to each cube and change the tag to cubeTags. When you want to find all the cubes, you can just do:
GameObject[] cubes = GameObject.FindGameObjectsWithTag ("cubeTags");
Cube[] ballsUp = new Cube[cubes.Length];
for(int i=0; i<cubes.Length; i++){
ballsUp = cubes[i].GetComponent<Cube>();
}

Move a particular sprite to a target position after clicking the button in unity 4.6

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.

remove graphics from inside a class as3

When I click a button in my game it draws shapes using the graphics in as3. simple shapes such as circles and rectangles.
I want to remove the graphics that have been drawn when something happens in one of my classes.
Basically when there is a hitTestObject (which works fine) I want all graphics on stage to be cleared.
if (gb2.hitTestObject(h1s2))
{
trace ("holed")
ySpeed2=0;
xSpeed2=0;
this.visible=false;
var mcSplash:MovieClip =parent.getChildByName("mcSplash") as MovieClip;
mcSplash.visible=true;
//parent.drawings.graphics.clear();
}
My attempt using parent.drawings.graphics.clear(); was unsuccessful, it gives me this error:
Line 481 1119: Access of possibly undefined property drawings through a reference with static type flash.display:DisplayObjectContainer.
Anyone have any suggestions
UPDATE:
this is how, on the min time line, the drawings occur.
var drawings:Shape = new Shape;
for (i=0; i<numRecs; i++)
{
recStartX = Number(xmlContent.rec[i].startpoint.#ptx);
recStartY = Number(xmlContent.rec[i].startpoint.#pty);
recWidth = Number(xmlContent.rec[i].dimensions.#w);
recHeight = Number(xmlContent.rec[i].dimensions.#h);
fillColor=int(xmlContent.rec[i].look.fillhex);
lineThick = Number(xmlContent.rec[i].look.strokethick);
lineColor = int(xmlContent.rec[i].look.strokehex);
drawings.graphics.lineStyle(lineThick, lineColor);
drawings.graphics.beginFill(fillColor);
drawings.graphics.drawRect(recStartX,recStartY,recWidth,recHeight);
drawings.graphics.endFill();
}
Create an array and push in each shape/rect.
Then iterate through this and remove..
for(var iteration:int = 0; iteration < rectArray.length; iteration++)
this.removeChild(rectArray[iteration]);
or if you are calling this from a class, use
MovieClip(this.root).removeChild(rectArray[iteration]);
Hopefully this is helpful :)
Z
What's drawings?! If you draw in mcSplash, you should use mcSplash.graphics.clear(). If you draw in a child called drawings, you should first get it as a child (after mcSplash get): var drawings = mcSplash.getChildByName('drawings); drawings.graphics.clear();. You could write checks to see what's going on: if (mcSlpash) { if (drawings) {, etc..