I'm little frustrated finding a child object of an object. I have a "muzzle" (muzzle mesh object) child object on a Gun object. but print(gun.transform.Find("muzzle").gameObject) gives NullReferenceException "Hierarchy" clearly shows "muzzle" object on the Gun yet I can't get hold of "muzzle" child object. What could be wrong? And I must say finding child game object through transform is really ugly. And child object depending on transform is simply wrong. You can have logical child without transform. Thanks.
Can you give a little more detail about the scene? gun.transform makes it sound like you have a third object. Are you sure "gun" is properly assigned to this third object? Or is the script attached to gun, and trying to find it's child, in which case you would just need transform.Find(). I just tested your print statement like this, and it worked fine.
If you're doing this within a script, it's often better to use public variables, which you can then drag objects into in Unity's IDE. For example, in your 'gun' script, you could have the following: Javascript: Code (csharp): var muzzle : GameObject; or C#: Code (csharp): public GameObject muzzle; This variable should then become visible when you select your gun in the hierachy (assuming the gun script is attached). You can then drag your muzzle GameObject on to that variable. Then in your script, you don't need to 'Find' anything. Just use your 'muzzle' variable, which will be a reference to that gameObject. hope this helps, - Ben
Yes, I have a script that needs access to the child object. So in my script, I'm just doing transform.Find("muzzle"). I said gun.transform.Find("muzzle") to illustrate that "muzzle" is a child object of a gun. Anyway, I just need to make "muzzle" to flash on/off when firing and I need the "muzzle" to attached to the front of the gun. "muzzle" is exported with the gun so that when gun is animated, "muzzle" move with it. This answers that I cannot use "muzzle" as separate variable to hold the object. If I do, it won't move with the gun's animation. I can have the muzzle move with the gun if I attach it as child of the muzzle bone but then I'm facing the same problem. I can't get hold of child object.
Is muzzle inactive? To hide it? If so it won't respond to a Find() attempt. If you do the suggestion made in the previous post, but making a public variable which is assigned to the child, then you will won't have a problem "finding" it. Since it's then assigned, I believe it's easy to just turn it off/on then.
I eventually found I need to include a path, so to find my "gm1" (my muzzle actually heh), I needed to find it like so: "mesh AAA Turret/meshROTATE/meshELEVATE/gm1" The "mesh AAA Turret" is essentially the root mesh in the scene. It would actually be in my ENEMYTURRET prefab, which I don't need to reference (I guess because that's the level you start at) What's kind of a pain is that I need an extra variable containing the "mesh AAA Turret/", as I have guns with "mesh Missile Turret/" and so forth, but at least below the inital object everything is named the same for all my turret models. This works, but doesn't seem quite right to me, like I wish I could just grab the gm1 transform from the get-go!
@Tempest, "muzzle" is not inactive when I first trying to access. Like I said, I need the muzzle flash to move with the gun. Gun is animating when fired. To make muzzle flash to animate with the gun, it needs be attached to the muzzle bone, front of the gun. This means that I need to find muzzle bone and I have the same problem.
@quentinp, do you mean that I need to use full path? "muzzle" is burried deep in the hierarchy. It sound discouraging.
So does this mean that you're creating, and then deleting muzzle, or simply showing, then hiding muzzle? If it's "buried deep" then it's not a child of the parent, but a child, of a child, of a child..etc of a parent. If you're not creating/deleting the muzzle, then a public variable will allow you to control it, regardless of where it is in the hierarchy.
@Tempest, yes "muzzle" is child of child of child... of gun. Is that the problem? Do I need to give full path name to find it? If you use the variable to hold "muzzle" object, how to then attach it to front of the gun. Like I said, the gun is animating when firing. Gun is skinned mesh and I believe when skinned mesh is animating, it will animate independently unless "muzzle" is attached to the proper bone.
Yes, the problem is that muzzle is not, in fact, a direct child of gun, and thus is not found without respecting the hierarchy which is established. You need to either put in the full hierarchy path, or create a public variable which accomplishes the exact same thing you're doing when you do the transform.Find(). Creating a public variable in the script, and attaching to the muzzle to it, does not change the hierarchy, it simply allows your script to know what GameObject (muzzle in this case), to talk to. Code (csharp): public GameObject muzzle; can accomplish the same as Code (csharp): GameObject muzzle = transform.Find("/../../muzzle").gameObject; Edit: In the first case, a field would appear in the inspector for you to drag the muzzle object to. This would link your script, to that object. What you're doing with the transform.Find is the exact same function, which is linking the game object to your script.
I now understand about the first method. I didn't know that I can drag any child object to a variable. Thanks for the tip. And using full path seems like a big mess. In the case of gun, it's not so bad. It's about 4 level deep, however, if I were to find a finger bone of a character, it could be ~10 level deep. I can't believe that there isn't an API that traverse children recursively. Bummer.
transform child relationships indicate a spatial relationship. logical relationships are often implemented using public variables pointing to components you need for scripting. These public variables do not have any spatial effect. In other words: make a public variable "muzzle", go to your script the game hierarchy window, drag the muzzle into the public variable and you will be able to access muzzle from your script, while it will still depend on the hierarchy and bones for its position.
Yup, I now understand the easy way. Thanks. It works in this case, however, there might be a case I need to find child object dynamically. Find(), requiring full path seems like a huge limitation for deep heirarchy. There should be an API that find child object recursively, don't you think?
Thanks for explaining that tomvds. That's what I was trying to say, but I just wasn't explaining it well. @Chrisk Well, you could have a script which, when searching, looks deeper than the first level of children. You can also assign tags, and do searches by tags, which remove the need for remembering/discovering hierarchy.
I'll keep that in mind too. But doesn't the tag search from the global namespace instead from the current object? This probably means the tag needs to have unique name as well to avoid name collsion, correct? My observation of Unity API is that it's very powerful and flexible yet, it's missing some basic APIs, especially dealing with finding GameObjects, Components and its children; Some requires "types" instead of "name" string; Some only work one level deep, some works recursively; And convoluted to access child object, e.g. this.transform.Find("root/child/child/child/target").gameObject instead of this.FindChild("target") Anyway, thanks for everyone who helped me.
You can also use GameObject.BroadcastMessage to send a message down the hierarchy to all children, and have the child react to it if needed.
Code (csharp): public GameObject GetChild( string name ) { Component[] transforms = GetComponentsInChildren( typeof( Transform ), true ); foreach( Transform transform in transforms ) { if( transform.gameObject.name == name ) { return transform.gameObject; } } return null; }
@AngryAnt, cool. yeah things like this would be useful to everyone. It's not hard to write but I'm wondering when I write my own, it may not be the most efficient way and why user have to write such a basic API themselves. Why can UT dev add it into the standard API, of course with some caveat about abuse. We need complete set of Get or Find to Component or GameObject using ID, Type, Name, Tag from its children or from the Global list Right now, API is completely unorthogonal. If missing, users have to fill the gap. Thanks.
This is not official UT policy (since I'm not aware exactly what it is), but personally I prefer APIs to be slim and only solve the problems which I commonly face and those which are larger in complexity. Obviously they need to be well designed as well - enabling me to add solutions for corner cases like this easily. You're quite right that any search method (such as this) is not very effective which I guess is exactly why it is not part of the API: Its ineffective and not the preferable way to solve the problem. The preferable way of referring to a child GO somewhere down the chain would be to drag-drop assign it to a public variable - like described earlier in this thread.
Efficiency is one thing but getting the job done is another. When things are static, I agree that public variable is the right way to go, if dynamic, however, there is no other way other than searching through the hierarchy, whether efficient or not it has to be done. If there is only one usecase, it's still necessary. Why would we have to write when such case arise?? I don't think everyone can completely get away with it because we cannot say for sure we never use it. I rather UT to provide it to us even if it's not used often. I trust them to write it at least as efficient as I can write, not that I too lazy to write it myself. ps. Adding few more APIs will not affect performance or efficiency. I think being orthogonal adds many benefits especially when a new user is trying to learn the system. I spend needless time trying to understand why it's designed this way. I rather start using API with low learning curve and as I learn, I can replace with more efficent method. At the begining I just want things to work without pulling too much of my hairs. Isn't orthogonality being very important espect designing APIs without cutting corners anyway?
One thing that might work (now that I know it exists heh) - the SendMessage function may allow you to have your muzzle do something without directly accessing it? Code (csharp): gameObject.SendMessage("DoMuzzle"); And attached to your muzzle: Code (csharp): function DoMuzzle(){ //stuff }
It will work but I'm not sure if sending message down to all its children everytime you fire a weapon is the right way to do it. Besides, having many scripts might make scene setup complicated. Without a visual script editor, it's hard to keep track of how all the scripts are connected together. Anyway. I think I'll resort to "public variable" method in this case. Thanks.
Hey Chris (Or Anyone Else) Please let me know the details on how to get muzzle flash working with a animated fire clip.
Angry Ant I understood your position that but respectfully I have to disagree about finding children being not complex enough to be covered by the API. I think APIs should simplify our life as much as possible, (which Unity does greatly) however finding children is only simple if you understand about transforms properties being able to be leveraged for such a purpose. I think it should be covered API side.
By the way here is the javascript equivalent of the script above: Code (csharp): function GetChild( name : String) : GameObject { transforms = GetComponentsInChildren( typeof( Transform ), true ); var i = 0; for (i=0;i<transforms.length;i++) { if( transforms[i].gameObject.name == name ) { return transforms[i].gameObject; } } return null; }
I am running into this same problem here. I have a few levels in my game, each level having varying numbers of a type "GameItem". I am storing all of these below one parent game object. It is very easy to store the transforms of these game items in an array, but so far have not figured out how to access the functions for the "GameItem" class that is attached to these objects. The only thing I can access are things off the transform type, so therefore I can't really do anything with these items. Doing it with a public variable just isn't a good way to do it IMO, since the numbers vary according to the level, and they all do different things and have different names (yet share certain attributes in the GameItem class). I am using public variables for certain other things where it makes fine sense to do so. However in this case, it seems doing it dynamically is THE way to do it. Is this just not the right way to use Unity? Is there an easy way to accomplish the task of using the custom class functions off a transform object?
Erm..when I run this Javascript function it just seems to return the parent gameObject.. ie whatever string I pass in it seems to return a gameobject with the same name...itself. ?
Come on guys this is archaic! We have known hierarchies (and scripts) being imported from external 3D apps and we can't reference them directly with namespaces without writing our own APIs? How is having two gameObjects with the same name a good idea? What is the "Global List"? This is all completely counter intuitive and boring. If all gameObjects require a transform just make all gameObjects transforms with components (shapes) like Maya. Creating public variables by dragging and dropping in the interface is tedious and prone to human error. The whole point of using scripts is to glue a scene together programmatically. http://forum.unity3d.com/threads/63...ound-prefabs-GameObjects-types-and-references So... since Unity allows for objects with the same name the only way to distinguish between them is by listing them in arrays http://benbritten.com/2009/09/06/unity-tip-for-the-day-always-name-your-new-gameobjects/
the code here does not work for me, so i modified it. Here is what worked for me: Code (csharp): public static GameObject GetChildGameObject(GameObject fromGameObject, string withName) { //Author: Isaac Dart, June-13. //Modified: Timo Ruoss, Aug-13. var count = fromGameObject.transform.GetChildCount(); List<Transform> ts = new List<Transform>(); for (int i = 0; i < count; i++) { ts.Add(fromGameObject.transform.GetChild(i)); } foreach (Transform t in ts) { if (t.gameObject.name == withName) return t.gameObject; else { var result = GetChildGameObject(t.gameObject, withName); if (result != null) return result; } } return null; } should not be used every frame.