Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice
  4. Dismiss Notice

Why is GetComponentsInChildren returning parent's component aswell?

Discussion in 'Scripting' started by Bazz_boyy, Aug 28, 2016.

Thread Status:
Not open for further replies.
  1. Bazz_boyy

    Bazz_boyy

    Joined:
    May 22, 2013
    Posts:
    192
    Yo,

    I'm trying to make a waypoint system. I have a parent GO that holds all the waypoints (also GOs). When I run my script on my parent GO which stores all the waypoints Transforms into a list using GetComponenetsInChildren<>, It's also returning the parents GO.

    Why dis happening yo? Here's my code:

    Code (CSharp):
    1. List<Transform> pathNodes;
    2.  
    3.  
    4.     void OnDrawGizmos()
    5.     {
    6.         Gizmos.color = Color.white;
    7.         pathNodes.AddRange(transform.GetComponentsInChildren<Transform>());
    8.         Vector3 previous = pathNodes[0].position;
    9.  
    10.         foreach (Transform pathNode in pathNodes)
    11.         {
    12.             Gizmos.DrawLine(previous, pathNode.position);
    13.             Gizmos.DrawWireSphere(pathNode.position, 0.25f);
    14.             previous = pathNode.position;
    15.         }
    16.  
    17.     }
     
  2. DonLoquacious

    DonLoquacious

    Joined:
    Feb 24, 2013
    Posts:
    1,667
    This is expected behavior- it says "Returns all components of type in the GameObject or any of its children." on the API page for GetComponentsInChildren. You can remove the list item that corresponds to the Transform of the current GameObject quite easily, just do pathNodes.Remove(transform); before assigning previous.
     
  3. Bazz_boyy

    Bazz_boyy

    Joined:
    May 22, 2013
    Posts:
    192
    Oh right... I guess I breezed over that. Thank you.
     
  4. beastxplode

    beastxplode

    Joined:
    Nov 26, 2016
    Posts:
    3
    The naming for this function is completely misleading and needs to be changed. If you want to save all the children of a gameobject into an array without the parent itself you would have to manually do it like this..
    Code (CSharp):
    1. Transform[] pathNodes = new Transform[transform.childCount];
    2. for (int i = 0; i < pathNodes.Length; i++)
    3.     pathNodes[i] = transform.GetChild(i);
     
  5. spiritworld

    spiritworld

    Joined:
    Nov 26, 2014
    Posts:
    29
    GetComponentInChildren<T> is the most stupid thing I've seen. It basically returns the same as GetComponent if both transforms have same <T> Example:

    Parent has Image
    - Child has image

    Now, calling parent GetComponentInChildren<Image>() returns it's own Image and not the child's.
     
    Z0leee87 and antromagames like this.
  6. spiritworld

    spiritworld

    Joined:
    Nov 26, 2014
    Posts:
    29
    Oh. My . God. It goes other way around too, so calling GetComponentInParent<Image>() from child RETURNS CHILD'S IMAGE
     
    Z0leee87 likes this.
  7. hofcsaba

    hofcsaba

    Joined:
    Jul 17, 2013
    Posts:
    8
    "expected behaviour"
     
    BrightBit and reza_b_mirzaei like this.
  8. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,724
    It is expected and documented behavior, yes. The typical use case for these functions is something like raycast and/or collision handling, where the object that has the collider is often a child of the main object which may have the Enemy or Rigidbody or whatever component you care about. By using GetComponentInParent you can handle the case of the collider being on the same object or a child object of the object that has the component you care about with the same code.

    If this function doesn't meet your particular needs, you are welcome to write one that behaves differently, or to ask Unity to include one in the API. But it is not difficult code to write...
     
    Suddoha, Bunny83 and bobisgod234 like this.
  9. ysleungrockman

    ysleungrockman

    Joined:
    Mar 16, 2014
    Posts:
    31
    This is always crazy and weird to me. With such logic, a parent is also a child of itself... This makes no sense to me. I have to write my own extension method every time...
     
  10. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,724
    Why not just write it once and reuse it?
     
    M4XXX, bobisgod234 and Lurking-Ninja like this.
  11. ysleungrockman

    ysleungrockman

    Joined:
    Mar 16, 2014
    Posts:
    31
    What I mean is I just type it again every time. I prefer to type code instead of just copy and paste. Though my concern is I originally shouldn't need to have this extension method at all. The method we currently have is just illogical and I don't understand why they designed like that.
     
  12. Lurking-Ninja

    Lurking-Ninja

    Joined:
    Jan 20, 2015
    Posts:
    9,923
    That's the question: why? I have a util class I'm using since 2013. Some things has changed in it over time, but... retyping everything every single time is just insane.

    On the contrary. it saves commands, so it saves CPU cycles. They made to call them from components. And majority of the time you use composite game objects and looking for other components on the same game object >somewhere< in the hierarchy. These are search calls, should be used sparingly and obviously you have the option to search for distinct game objects first if you want to do it other ways.
     
  13. AldeRoberge

    AldeRoberge

    Joined:
    Jun 23, 2017
    Posts:
    48
    Sorry to necrobump, but this has been really frustrating. It's one of those "gotchas" Unity has.

    So here's a simple Utility method to return components in children, excluding (or not) the parent object.

    Code (CSharp):
    1.        
    2. public static class ComponentUtils
    3. {
    4.     public static T GetComponentInChildren<T>(this GameObject obj, bool includeInactive = false, bool excludeParent = false) where T : Component
    5.     {
    6.         var components = obj.GetComponentsInChildren<T>(includeInactive);
    7.  
    8.         if (!excludeParent)
    9.             return components.FirstOrDefault();
    10.  
    11.         return components.FirstOrDefault(childComponent =>
    12.             childComponent.transform != obj.transform);
    13.     }
    14. }
    15.  
     
    davidnibi and reza_b_mirzaei like this.
  14. halley

    halley

    Joined:
    Aug 26, 2013
    Posts:
    1,876
    Yep, I have something similar. I would say that your code is a little confusing/mistake-prone in that you have two default arguments with opposite meanings. It would be nicer to have includeInactive=false, includeParent=true (which would default to behaving the same as the original).
     
    AldeRoberge and reza_b_mirzaei like this.
  15. gurth

    gurth

    Joined:
    Sep 21, 2014
    Posts:
    6
    I got baited by method name too.
    Example of solution (not the best performance because of Linq I suppose, but verbose).
    Will not work when Parent won't be first in array.
    Code (CSharp):
    1.  MeshFilter[] meshFilters = GetComponentsInChildren<MeshFilter>().Skip(1).ToArray();
     
    mustafahtp3 likes this.
  16. Gigabitten_Gaming

    Gigabitten_Gaming

    Joined:
    Jul 10, 2017
    Posts:
    32
    OMG There is so much irony in calling this "EXPECTED BEHAVIOR"

    Yes, because all of us here were expecting to get the component in the parent in a function that is literally called "get component in children"

    A child could easily tell you why this is bad, it's extremely obvious. Why are people with negative design ability and/or emotional intelligence tasked with designing this API?

    I'm sorry for being rude, but to be polite is to talk at the wind. Better to just be totally honest -- this is very bad API design.
     
    Last edited: Oct 24, 2023
  17. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    5,917
    This method was implemented probably over a decade ago at this point. Confusing it might be but Unity can't exactly change this behaviour on a whim.

    Mind you it's not that strange a behaviour, to be honest. If you've ever worked with your own tree-like data structures, then any queries in any part of the tree usually includes the the entry point first, then its children after. Usually with an optional parameter/overload to ignore said entry point.

    That said there really needs to be an overload to ignore said entry point, but it's current behaviour does make sense if you think about it from more than just the perspective of a new user.
     
    Bunny83 likes this.
  18. Gigabitten_Gaming

    Gigabitten_Gaming

    Joined:
    Jul 10, 2017
    Posts:
    32
    I completely disagree. That's like getting a German Shepard and telling everyone it's a Golden Retriever. Then, when people tell you that you are wrong, you defensively point the blame back at them because, if they actually knew you, then they would know that when you talk about Goldren Retrievers, you are actually referring to German Shepards. They are wrong and you are right because they are "beginners" and you are the expert! How foolish of them!

    This way of thinking is arrogant and backwards. If an API method says "I do X" but in reality it does not, then it's a badly designed API method. The fact that there are some veterns who are used to such nonsense means absolutely nothing. It's still bad design.
     
  19. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,780
    I tell my dog he can be whoever he wants. Some days he even likes being a poodle, but most days he's a golden. See my avatar? He's in golden retriever mode there...

    Look, I understand your frustration, but as others have pointed out, at this stage it isn't likely to change without even MORE disruption to the ecosystem, and the workaround isn't particularly bad.

    And in general...

    Keep in mind that using GetComponent<T>() and its kin (in Children, in Parent, plural, etc) to try and tease out Components at runtime is definitely deep into super-duper-uber-crazy-Ninja advanced stuff.

    This sort of coding is to be avoided at all costs unless you know exactly what you are doing.

    Botched attempts at using Get- and Find- are responsible for more crashes than useful code, IMNSHO.

    If you run into an issue with any of these calls, start with the documentation to understand why.

    There is a clear set of extremely-well-defined conditions required for each of these calls to work, as well as definitions of what will and will not be returned.

    In the case of collections of Components, the order will NEVER be guaranteed, even if you happen to notice it is always in a particular order on your machine.

    It is ALWAYS better to go The Unity Way(tm) and make dedicated public fields and drag in the references you want.
     
  20. zulo3d

    zulo3d

    Joined:
    Feb 18, 2023
    Posts:
    549
    GetComponentsInChildrenAndTheParentObject just doesn't sound as cool..
     
  21. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,539
    Right, one example is the file system. When you get all files from a certain part recursively it would include the files in the starting folder as well and not just the files in subfolders. Yes, the name can be confusing, but try to come up with a better name that makes it clear to search for components recursively upwards / downwards (those directions could also be misinterpreted). So the suffix "InChildren" and the much later added "InParent" just indicates the searching direction.

    Yes, using those methods specifically with the Transform component may be not optimal. However with almost every other component it usually makes more sense this way. Like it was already mentioned, when you raycast against a collider or have a trigger event you usually get a collider which is often a child of a rigidbody. However it's also possible that the corresponding rigidbody is on the same object as the collider. So GetComponentInParent will get you the closest rigidbody component that this collider belongs to. Likewise when we talk about UI elements like a Button it usually have a Text component as a child. Using GetComponentInChildren takes care of getting the first Text component that an object has. It may be deeply nested or on the object in question.
     
    Lurking-Ninja and spiney199 like this.
  22. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    5,917
    Yeesh, chill out mate.

    Every single Tree-like data structure API I've used has had a method often called FindChild or similar, and that method, 100% of the time, has included the entry point by default, with excluding it as optional. Often with a signature of
    FindChild(Predicate<T> predicate, bool includeSelf = true)
    . It's pretty much a programming standard at this point, so there's no real reason for Unity to go against this standard, as, as mentioned above, there's good reasons why this is the default behaviour.

    Besides, you can complain as much you want, that doesn't change these facts:
    • The method has been around forever so it's behaviour will never be changed
    • The documentation clearly states how it behaves
    • It's consistent with other API's you'll find out there
    Is it a little confusing for a new user? Sure. But so is just about everything in game dev and programming as both of which are intrinsically hard. Once you read the docs, understand how it works, it's not as egregious as it might seem.
     
  23. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,724
    Now imagine that 1,000,000 other people already know the dog as a Golden Retriever and interact with it every day as such.

    What's worse? Telling the one new person to call the dog a golden retriever, or getting 1,000,000 people who already know the dog to change how they interact with it?
     
  24. Gigabitten_Gaming

    Gigabitten_Gaming

    Joined:
    Jul 10, 2017
    Posts:
    32
    The latter is better, and it's not an absurd claim. If the "DogBreed.js" (or whatever this imaginary API is called) API writers changed the API such that Golden Retrievers are called Golden Retrievers and not German Shepherds, the millions of people who were working with the old, flawed system are not going to have much trouble switching to the newer, better system since the newer, better system is so much more usable that the switch is natural and intuitive.

    If they have to refactor some of their code to upgrade to the latest, then that's unfortuante but necesarry as the long term gain of having a better product is worth the short term loss of annoying a small percentage of users.
     
    Last edited: Oct 24, 2023
  25. Gigabitten_Gaming

    Gigabitten_Gaming

    Joined:
    Jul 10, 2017
    Posts:
    32
    At the end of the day, this is not a discussion about engineering or development. Instead, it's a discussion about design and UX. I have a funny feeling that the vast majority of us here are engineers, not UX'ers or product designers (game design does not count as product design or UX)

    Furthermore, in my experience, arguing with engineers about UI/UX or design is usually pointless. It's one of those things where if people can't see some usability truth that is in plain sight, one that is usually super obvious to a someone who studies design and UX, then there is very little that can be done to bring them to the truth. This is one of those times.

    It just so happens to be that if the product to design is the API itself, then the designers have to be experts in both engineering AND design/UX. However, I think these people are extremely rare, and so APIs are usually badly designed. Since the users of these APIs are usually not trained in UX or design, they can't see the flaws or point out how to make it better, but when they do, the designers of the API, who are unskilled in design and UX, often don't listen because they are blind to good design.

    Such is the world we live in.
     
  26. Gigabitten_Gaming

    Gigabitten_Gaming

    Joined:
    Jul 10, 2017
    Posts:
    32
    Sounds to me like there's just a shockingly large amount of APIs out there with poor usability. But it also sounds like at least some of them had the sense to include a flag giving people the option to include the parent or not, which is better than nothing. I'm sure maybe others had a less wrong name which they gave the method, too.

    Also, an example of an API that did not follow this bad design pattern is the node.js API, which is used to querying HTML.
     
    Last edited: Oct 24, 2023
  27. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,724
    I'd say this is just as arrogant an attitude as the attitude you are railing against. And for every person like you vigorously denouncing the status quo, there would be just as many if not more vigorously angry people demanding to know why an API which has been working for years in one way suddenly needed to be changed and that their engineering team only has so much bandwidth and how dare Unity be so irresponsible and arrogant as to force them to make unnecessary changes?

    There isn't really any winning in a situation like this.
     
    spiney199 and Bunny83 like this.
  28. SisusCo

    SisusCo

    Joined:
    Jan 29, 2019
    Posts:
    1,123
    @Gigabitten_Gaming How would you redesign the API today, if you had free rein? I'm curious :)

    I agree that it can be easy to make mistakes with
    GetComponent(s)InChildren
    , because it doesn't make it explicit that the game object on which the method is executed is also included in the search, and because
    includeInactive
    is just an optional bool that is quite easy to forget about.

    That being said, there is also a trade-off in terms of verbosity that has to be made, if these choices are to be made very explicit - which can also have a negative effect on readability (word soup effect / horizontal scrolling needed to read whole row).

    For example:
    Code (CSharp):
    1. var childColliders = GetComponentsInChildren<Collider>();
    vs
    Code (CSharp):
    1. var childColliders = FindAll<Collider>(In.SelfAndChildren, Inactive.Exclude);
    So I can also understand why somebody would opt to make the most common case very short and simple, and leave the more advanced cases to require passing optional arguments or writing custom implementations: sensible defaults is good design after all. And Unity's design approach has also always been more about simplicity than robustness :D
     
  29. Gigabitten_Gaming

    Gigabitten_Gaming

    Joined:
    Jul 10, 2017
    Posts:
    32
    Good points, the only way to fix this without making backward-incompatible changes would be to increase verbosity.

    From a UX/DX point of view (in this case the user is also the developer, so UX and DX are the same thing), verbosity is really nothing more than a crude metric to measure something much more essential to good design, which is the number of items the user has to store in their working memories in order to interface with the product.

    To use the interface called
    GetComponentsInChildren
    , the user has to hold in their working memories the parent object, the children, the fact that the method will return components from both, the component type, and the reasons for using it.

    To use the interface called
    GetComponentsInSelfAndChildren
    , the user has to hold in their working memories the parent object, the children, the fact that the method will return components from both, the component type, and the reasons for using it.

    ...wait a second, they are exactly the same‼️ Except the second, more verbose method name has the added benefit of not egregiously lying to the user about what it does.

    Adding 6 more characters in order for the method name to not lie to the user seems like an extremely reasonable tradeoff to make. Those extra 6 characters do not add or remove complexity from the method's interface, as we have shown above. It only adds much needed clarity. Therefore, it is objectively better.

    As an aside, if your variable/method names have to be extremely long to clearly name them, then it's a red flag that the code ought to have been designed better. If it's not possible to refactor the code to design it better, as might be the case here, then it's better to keep the clear yet verbose names because any information you leave out of the name still has to be in the user's working memory at the time of use, and so giving it a shorter, unclear name is not accomplishing anything good. But what's especially bad design is when people will literally give their variables/methods a misleading name just so that they can be a few characters shorter, which is a complete failure to empathize with the user in one of the most basic and rudimentary ways imaginable.
     
    Last edited: Oct 26, 2023
    SisusCo likes this.
  30. halley

    halley

    Joined:
    Aug 26, 2013
    Posts:
    1,876
    What a waste of time, this discussion. They're never going to change it. Existing code that depends on it is in the millions of lines. HTTP standard 1.0 uses the incorrect spelling "referer" and it's never going to change. Adding words to a function isn't "objectively better" than adding an argument to distinguish them; it may be subjectively better to some people. It doesn't matter what your personal feelings are.

    If you spent this energy on making your game, you'd be that much closer to having paying customers.
     
  31. Gigabitten_Gaming

    Gigabitten_Gaming

    Joined:
    Jul 10, 2017
    Posts:
    32
    I wish that you were not right, but I know in reality that you are. I still think it's worth it to discuss this because it's forcing me to sculp my design thinking just to write all this out, which is good.

    Also, I'm not sure adding more arguments would solve this problem unless a "includeParnet" bool flag were defaulted to false, which would make it not backwards compatible.
     
  32. APSchmidtOfOld

    APSchmidtOfOld

    Joined:
    Aug 8, 2016
    Posts:
    4,473
    It's also a hell easier! :)

    But then, why are GetComponent and GameObhect or Transform Find persistently used in their tutorials? Learn is full of those.
     
  33. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,780
    Why ask why? Try Bud Dry! People are people.
     
    Bunny83 likes this.
  34. Ryiah

    Ryiah

    Joined:
    Oct 11, 2012
    Posts:
    20,137
    Tutorials are meant to get you started. Best practices can come once you're no longer struggling with the basics.
     
    SisusCo, Bunny83 and Kurt-Dekker like this.
  35. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,539
    Well, there are situations where you have to use GetComponent, especially when using raycasts, triggers or collisions. The component architecture is the fundamental core of Unity's GameObject system and GetComponent is the dynamic way of getting them. Sure, when you have a scene or a prefab you can setup references through the inspector which is one of the most powerful feature of Unity. Though when it comes to dynamic interactions GetComponent is the way to go. It also works nicely with interfaces.
     
  36. halley

    halley

    Joined:
    Aug 26, 2013
    Posts:
    1,876
    You can almost imagine that they wouldn't have ever exposed GetComponentInParent/Children, except they already needed that function for the physics system. It works exactly as they needed it, and we are lucky to get public access to it.
     
  37. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,780
    You're probably actually closer to the truth than you realize!!

    Remember all the shortcut goodies they had (still have, obsoleted) in MonoBehaviours: .collider, .camera, .audio, .rigidbody, .renderer, etc.

    I bet with those things you really used GetComponent far less. And back then GetComponent<T>() didn't even work with interfaces!

    The dark dark dark days of componentry...
     
  38. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,539
    True, though all those shortcut properties essentially used GetComponent behind the scenes anyways. Only the transform component actually had caching applied. Yes, in the past the generic version of GetComponent had a constraint on "T" to be of type "Component". At first glance that actually made sense since GetComponent can only get Components. However they haven't thought of interfaces back then. However even at that time the non-generic version of GetComponent did actually work with interfaces.

    Code (CSharp):
    1. IMyInterface obj = (IMyInterface)GetComponent(typeof(IMyInterface));
    This still works but of course

    Code (CSharp):
    1. IMyInterface obj = GetComponent<IMyInterface>();
    is much cleaner now :)
     
    Ryiah, spiney199 and Kurt-Dekker like this.
  39. Gigabitten_Gaming

    Gigabitten_Gaming

    Joined:
    Jul 10, 2017
    Posts:
    32
    "and we are lucky to [have it]" -- You speak as if you don't care whether or not Unity designs a good API or not.

    I'm probably more upset about this than I ought to be (probably because I'm a bit of an extreme perfectionist to a fault), but my preference is for my tooling/stack (which includes Unity) to be good and not mediocre.
     
    Last edited: Oct 27, 2023
  40. halley

    halley

    Joined:
    Aug 26, 2013
    Posts:
    1,876
    You seem to put way too much emphasis on your own interpretations on what other people write. The API is what it is. Through the years, Unity has hired and fired hundreds of people, and added millions of lines of code in an obviously organic method as they raced to find the secret sauce that might make them some money. They will not listen to you or me, for such trifles as the naming of a function, or even the styles and sets of best practices they should adopt. Each team on their staff has wildly swung from one approach to another, and we all get to see the historic cruft and chaff which a decade of churn will grow in a codebase.

    I was being wry when I said "you can almost imagine" because from my experience in using APIs exposed by hundreds of different companies over the years, it's painfully obvious that it's true: they only made GetComponent public when they realized the internal component fetches were going to be necessary, and their public accessors like .audio .transform .rigidbody was not going to scale. Game authors needed a way to do basic general-purpose searching just like the engine did, but the kinds of game authors Unity was courting would have trouble writing the recursive routine on their own.

    The sooner you just accept that their API is their API and your goal is to write a game, not an engine, the sooner you can finish your next game. I accepted it years ago, lumps and all.
     
  41. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,516
    With those things you used GetComponent on every single access, it just looked different.

    - - -

    As far as best practices go, I only use exposed Inspector fields for stuff which I want people making decisions about. If there is a single, deterministically correct thing that should be referenced by a field then I'll have the computer do that for me, thanks - it's the kind of rote crunching they're built for, they're faster than people at it, more consistent, and only make mistakes when we tell them to. ;) That being said, I'll do it at edit time rather than runtime where I can.
     
  42. APSchmidtOfOld

    APSchmidtOfOld

    Joined:
    Aug 8, 2016
    Posts:
    4,473
    Hmm, maybe. But it would probably be best to inform the beginners that "this code exists, yes, and we teach it to you, but, there are best practices you may need to get accustomed to as fast as possible". ;)
     
  43. LeonhardP

    LeonhardP

    Unity Technologies

    Joined:
    Jul 4, 2016
    Posts:
    3,109
    Being rude and offensive is not acceptable behavior on this forum. Please tone the aggressiveness down and refrain from derogatory attributions towards others and their abilities.
     
  44. APSchmidtOfOld

    APSchmidtOfOld

    Joined:
    Aug 8, 2016
    Posts:
    4,473
    Okay, let's live with it since we cannot do else. ;)

    I tested your code. Indeed the parent is included with the children in the list and it also produces unwanted results (see image). You need to limit the size of your list to avoid this:

    Code (CSharp):
    1.  
    2.     [SerializeField] List<Transform> pathNodes;
    3.     [SerializeField] int numberOfNodes;
    4.  
    5.  
    6.     void OnDrawGizmos()
    7.     {
    8.         Gizmos.color = Color.white;
    9.  
    10.         if (pathNodes.Count < numberOfNodes)
    11.         {
    12.             pathNodes.AddRange(transform.GetComponentsInChildren<Transform>());
    13.             pathNodes.RemoveAt(0);
    14.  
    15.         else
    16.             pathNodes.LastIndexOf(pathNodes[4]);
    17.         }
    18.  
    19.         Vector3 previous = pathNodes[0].position;
    20.  
    21.         foreach (Transform pathNode in pathNodes)
    22.         {
    23.             Gizmos.DrawLine(previous, pathNode.position);
    24.             Gizmos.DrawWireSphere(pathNode.position, 0.25f);
    25.             previous = pathNode.position;
    26.         }
    27.  
    28.     }

    The line:

    Code (CSharp):
    1.             pathNodes.RemoveAt(0);

    will remove the parent from the list, and

    Code (CSharp):
    1.             pathNodes.LastIndexOf(pathNodes[4]);
    will determine which pathNode is the last of the list.


    Capture d’écran_2023-10-27_11-40-23.jpg
     
    Last edited: Oct 27, 2023
  45. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,539
    You said that an API method said X but does Y. However GetComponentInChildren says:
    So the behaviour is documented. If you just complain about the naming of the method, what do you think about the C standard library? What about
    atoi
    ,
    feof
    ,
    isalnum
    or
    gets
    ? You essentially complain that the name of the method is too specific? You can not encode every detail of the behaviour of a method into its name. We know that you want a different behaviour. However that's not the point here. The behaviour is there and it's useful as it is. So I would want to know how would you name this method so the API is named "correctly". Don't tell us you want a different behaviour, we know. You complaint about a bad design and that it doesn't do what you expect. So find a name that tells us unambiguous what this method does without creating a method name that is a whole sentence.

    Many details are unclear from the method name. The method also iterates over deeply nested children, not just the children. This is not clear from just the method name. Though my point is that it's difficult to find a descriptive name that fully explains it's function. The C standard methods are just examples where you have to look up and learn what they actually do. You can remember the name once you know what it does. But you can not infer the function from the name.
     
  46. APSchmidtOfOld

    APSchmidtOfOld

    Joined:
    Aug 8, 2016
    Posts:
    4,473
    It's GetComponentsInChildren in fact and it's specified:
    Just to make sure. ;)
     
    Bunny83 likes this.
  47. Gigabitten_Gaming

    Gigabitten_Gaming

    Joined:
    Jul 10, 2017
    Posts:
    32
    I think by criticizing Unity so harshly I've basically just shaken a bee's nest and now I'm getting stung by all the Unity enthusiasts who lurk in the forums, defending the engine they've put thousands of hours into.

    I swear to god that I'm actually an agreeable person in real life who does not like to argue with people. However, it seems stunningly bewildering and absurd to me that there are actually some people who would defend Unity here, either a) claiming the method name is not misleading or b) claiming that its deceptiveness is acceptable. Given the degree of absurdity here, I see no issue making the somewhat impolite/disagreeable claim that there are a lot of developers who are confused about what a well designed API should look like, and many of them are in this forum.
     
    Last edited: Oct 27, 2023
  48. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    5,917
    It wasn't criticism, you were just laying out crass insults for no good reason. Same as the other threads you posted in the 2D forum. Not only were you completely wrong but it was just wholly unnecessary.

    Just take the L and move on. It's better for your mental health.
     
  49. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,516
    I believe that you're confusing the criticism, which is valid, and its delivery, which could certainly have used some work!

    I deliver criticism regularly as a part of my job. The way to make it work is to keep it constructive, make sure it's actionable and helpful, and above all else, make sure it's not personal / insulting.

    It's not even about being nice (though I also care about that). As soon as you put someone on the defensive they become far more resistant to change, so you've made it much harder to get what you want.
     
  50. Gigabitten_Gaming

    Gigabitten_Gaming

    Joined:
    Jul 10, 2017
    Posts:
    32
    In a workspace setting, it's perfectly fine to use good people skills and deliver criticism in a way to protect the ego of its recipient and the relationship of the individuals involved. However, I do not wish to do that here. I've learned that there is only one way to push against the status quo, and that is stubbornly and persistently. Notice how we are all still conversing here. If I were to have given sugar coated criticism, there would have been a high likelihood of being ignored completely, which often happens to descenders who are nice and polite.

    In this post and in duplicates, there are countless examples of people pointing out how this is an misleading method name. Each time a Unity enthusiast with thousands of posts swept in and shuts them up somehow, maintaining the status quo and asserting their superiority in the process. The thing that motivates me to be so vocal is that it does not just happen here -- it happens everywhere. This is simply wrong.. wrong enough to motivate me to be as stubborn as I am being now.

    As an aside, I think it's a virtue to associate with people that can be told those criticisms at face value. If they disagree, then we talk about it. If I am wrong (and I'm wrong very frequently), then I take a hit to my own ego, feel bad, guilty, stupid, etc., and then grow from those negative emotions which I am grateful to have in my life. However, there is never a moment when I fling the criticism back at the criticizer for criticizing. Wouldn't that be an strange and hypocritical thing to do?
     
    Last edited: Oct 28, 2023
Thread Status:
Not open for further replies.